读处理问题

时间:2011-06-21 03:54:46

标签: c++ sockets networking

我正在使用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;
}

你们认为它能处理接收时可能发生的所有异常吗?还能请你提供处理套接字异常的教程或示例吗?在线示例代码不包含详细信息..提前致谢

2 个答案:

答案 0 :(得分:1)

recv可以返回三个中的任何内容,并且您的代码需要正确处理每个内容:

1)正数。这意味着它读取了一些字节。

2)负数。这意味着发生了“错误”。

3)零。这意味着连接的另一端在套接字上执行了成功的shutdown()(或close())。 (通常,从read()或recv()返回0意味着EOF。)

“错误”案例进一步细分为“EAGAINEWOULDBLOCK”和“其他所有内容”。前两个只是意味着它是一个非阻塞套接字,目前没有数据可以提供给你。您可能想要返回并再次调用poll()(或select()或epoll())以避免繁忙等待......

“其他所有”意味着真正的错误。你也需要处理它们;请参阅POSIX spec for recv()以获取完整列表。

鉴于这一切,我会说你的示例代码有几个原因是坏的。它没有正确处理0(关闭连接)。它不处理任何错误。当recv()返回EAGAIN / EWOULDBLOCK时,它会进行忙碌循环。

哦,它使用sizeof(char),这是一个肯定的标志,它是由不熟悉C或C ++编程语言的人编写的。

答案 1 :(得分:0)

您无法在正常情况下知道“客户端发送了多少数据”。您应该使用可伸缩数据格式(标头中有数据长度)或数据令牌分隔符。例如,您可以在数据和下一个数据之间添加\ xff。或者,您应该使用固定数据格式。