我在C中编写了一个小型服务器守护程序,处理连接,断开连接和接收等基本部分已经存在,但接收问题仍然存在。
我使用“recv”一次读取256个字节到一个char数组,因为它可以包含多行数据作为一个大块,我需要能够分开拆分每一行来处理它。
仅此一点不会成为问题,但由于线路可能会被切断,因为它不再适合缓冲器,我还需要能够看到线路是否被切断。也不是那么糟糕,只需检查\r
或\n
的最后一个字符,但如果该行被截断了?我的代码不容易“只是继续阅读更多数据”,因为我正在使用select()
来处理多个请求。
基本上,这是我的情况:
//This is the chunk of code ran after select(), when a socket
//has readable data
char buf[256] = { 0 };
int nbytes;
if ((nbytes = recv(i, buf, sizeof(buf) - 1, 0)) <= 0)
{
if (nbytes == 0)
{
struct remote_address addr;
get_peername(i, &addr);
do_log("[Socket #%d] %s:%d disconnected", i, addr.ip, addr.port);
}
else
do_log("recv(): %s", strerror(errno));
close(i);
FD_CLR(i, &clients);
}
else
{
buf[sizeof(buf) - 1] = 0;
struct remote_address addr;
get_peername(i, &addr);
do_log("[Socket #%d] %s:%d (%d bytes): %s", i, addr.ip, addr.port, nbytes, buf);
// split "buf" here, and process each line
// but how to be able to get the rest of a possibly cut off line
// in case it did not fit into the 256 byte buffer?
}
我正在考虑使用更高范围的临时缓冲区变量(可能是malloc()
'd)来保存当前缓冲区,如果它太长而无法立即适应,但我总是对不必要地引入感到不舒服如果有更好的解决方案,那么高范围的变量:/
我感谢任何指针(除了XKCD之外的))!
答案 0 :(得分:3)
我猜你需要添加另一个包含不完整行的每个流缓冲区,直到收到后来的换行符。
答案 1 :(得分:0)
我会使用某种动态扩展缓冲区(如GString来累积数据。
可能有用的另一件事是使用fcntl()
将套接字置于非阻塞模式。然后你可以循环recv()
直到得到-1。检查errno
,它将是EAGAIN
或EWOULDBLOCK
(并且不需要具有相同的值:检查两者)。
最后评论:我发现使用libev(google it;我无法发布多个链接)比使用select()
更有趣。