我正在使用epoll进行网络编程,我有这段代码......
int read = read(socket, buf, bufsize);
我有一个巨大的缓冲区大小,我认为它将接收客户端发送的所有内容。 但是,我开始面临像数据包分割这样的问题。
一个例子是,如果客户端发送了500个字节,但它以某种方式进入了两个250字节的数据包,则无法处理这种情况。
我在网上查了一下,找到了这段代码
int handle_read(client *cli, struct epoll_event *ev) {
size_t len = 4096;
char *p;
ssize_t received;
cli->state = 1;
if (cli->buffer != NULL) {
//free(cli->buffer);
//printf("Buff not null %s\n", cli->buffer);
}
//allocate space for data
cli->buffer = (char*)malloc( (size_t)(sizeof(char) * 4096) );
p = cli->buffer;
do { //read until loop conditions
received = recv(ev->data.fd, p, len, 0);
if (received < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
//if error, remove from epoll and close socket
printf("Handle error!!!\nClient disconnected!\n");
epoll_ctl(epollfd, EPOLL_CTL_DEL, ev->data.fd, ev);
close(ev->data.fd);
}
p = &cli->buffer[received];
} while (received >= len && errno != EAGAIN && errno != EWOULDBLOCK);
return received;
}
你们认为它能处理接收时可能发生的所有异常吗?还能请你提供处理套接字异常的教程或示例吗?在线示例代码不包含详细信息..提前致谢
答案 0 :(得分:1)
recv
可以返回三个中的任何内容,并且您的代码需要正确处理每个内容:
1)正数。这意味着它读取了一些字节。
2)负数。这意味着发生了“错误”。
3)零。这意味着连接的另一端在套接字上执行了成功的shutdown()
(或close()
)。 (通常,从read()或recv()返回0意味着EOF
。)
“错误”案例进一步细分为“EAGAIN
或EWOULDBLOCK
”和“其他所有内容”。前两个只是意味着它是一个非阻塞套接字,目前没有数据可以提供给你。您可能想要返回并再次调用poll()(或select()或epoll())以避免繁忙等待......
“其他所有”意味着真正的错误。你也需要处理它们;请参阅POSIX spec for recv()以获取完整列表。
鉴于这一切,我会说你的示例代码有几个原因是坏的。它没有正确处理0(关闭连接)。它不处理任何错误。当recv()
返回EAGAIN
/ EWOULDBLOCK
时,它会进行忙碌循环。
哦,它使用sizeof(char)
,这是一个肯定的标志,它是由不熟悉C或C ++编程语言的人编写的。
答案 1 :(得分:0)
您无法在正常情况下知道“客户端发送了多少数据”。您应该使用可伸缩数据格式(标头中有数据长度)或数据令牌分隔符。例如,您可以在数据和下一个数据之间添加\ xff。或者,您应该使用固定数据格式。