2011-06-21 96 views
1

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

你们认为它处理了所有的异常可能同时接受发生的呢?你也可以给我提供处理套接字异常的教程或例子吗?示例代码在网上不包括细节..提前

回答

1

recv可以返回任何的的东西,你的代码需要处理每一个正确:

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

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

3)零。这意味着连接的另一端在套接字上执行成功shutdown()(或close())。 (一般情况下,从0 read()或recv的回报()是指EOF

的“错误”的情况下进一步分解为“EAGAINEWOULDBLOCK”和“一切”。前两个意味着它是一个非阻塞的套接字,目前还没有数据可以给你。你可能想回去,并呼吁调查()(或选择()或epoll的())再次以避免忙等待...

“其他一切”指的是真正的错误。你也需要处理这些;请参阅POSIX spec for recv()以获取完整列表。

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

哦,它使用sizeof(char),这是一个明确的信号,它是由人谁不熟悉C或C++编程语言。

+0

感谢您的回复。你知道任何好的示例代码或教程吗?我在网上查看,他们只涉及基本的东西。提前致谢。 – codereviewanskquestions

+0

不是副手......我总是自己动手。这是一个非常简单的嵌套if/then结构来处理所有情况,但是_how_要处理每个情况取决于特定的应用程序。 (特别是错误,你是否返回一个代码或抛出一个异常?那么,这取决于你自己的约定。) – Nemo

+0

感谢您的回答:) – user800799

0

感谢您无法知道normaly“多少DATAS客户端发送”。您应该使用可伸缩数据格式(标题中具有数据长度)或数据标记分隔符。例如,您可以在数据和下一个数据之间添加\ xff。或者,您应该使用固定的数据格式。