Linux,C,epoll()读取:服务器没有收到其余字节的通知

时间:2015-09-21 22:54:38

标签: c linux sockets epoll

这是讨论此主题的新主题:Linux, C, epoll(), read() data incompleted?

我有epoll()服务器套接字使用Level-Trigger模式。

客户端发送10 * 128K数据;

服务器端,我使用了64K的缓冲区来接收,因此我应该至少通知20次以从客户端接收所有字节。

但是我的调试显示我只收到了19次通知,并且丢失了一些字节!为什么我没有收到其余字节的通知?

========编辑1 =======

基本上,客户端会发送这些字节,这些字节应该到达服务器端。 (因为我可以通过另一个函数接收它们,尽量读取所有字节并返回,直到没有更多字节可用于读取 - 但这将导致接收低性能)。

但是来到这个Nread(),我应该得到通知,Nread应该被召唤20次以上,但现在只召唤了19次。

参见代码:

efd = epoll_create1 (0);
event.data.fd = listener_fd;
event.events = EPOLLIN | EPOLLET;
epoll_ctl(efd, EPOLL_CTL_ADD, listener_fd, &event);

while (1){
    n_fds = epoll_wait (efd, events, MAX_EPOLL_EVENTS, -1);
    for (i = 0; i < n_fds; i++){
                ...........
       if (islistener) {
             .....
            //handle new connections
       }
      else{
           bzero(buffer, recv_buf_size);
           if ((n= Nread(fd, buffer, recv_buf_size)) <= 0) {
                  //error
           }
           else
           {
                   //add bytes to total:
                    __sync_fetch_and_add(&(mythreads->total_bytes_transferred), n)    ;
           }

}

int Nread(int fd, char *buffer, size_t count)
  {
          ssize_t r;
          size_t left = count;
          printf("===>\n");
          while (left > 0){
                  r = read(fd, buffer, left);
                  printf("data: %ld\n", r);
                  if (r < 0) { 
                          if (errno == EINTR || errno == EAGAIN)
                                break;
                          else
                                return -100; //error
                  else if (r == 0)
                          break;
                  }
                  left -= r;
                  buffer += r;
          }
          printf("=> done, %ld\n", count - left);
          return count - left;
  }

输出:

1===>
data: 65536
=> done, 65536
2===>
data: 65536
=> done, 65536
3===>
data: 60734
data: 4802
=> done, 65536
4===>
data: 55934
data: -1
errno: 11
=> done, 55934  //data is not enough. the missing part should come soon. but why I am not notified?
5===>
data: 60736
data: 4800
=> done, 65536
6===>
data: 65536
=> done, 65536
7===>
data: 65536
=> done, 65536
8===>
data: 65536
=> done, 65536
9===>
data: 65536
=> done, 65536
10===>
data: 65536
=> done, 65536
11===>
data: 65536
=> done, 65536
12===>
data: 65536
=> done, 65536
13===>
data: 65536
=> done, 65536
14===>
data: 65536
=> done, 65536
15===>
data: 65536
=> done, 65536
16===>
data: 65536
=> done, 65536
17===>
data: 65536
=> done, 65536
18===>
data: 65536
=> done, 65536
19===>
data: 65536
=> done, 65536

1 个答案:

答案 0 :(得分:0)

if ((n= Nread(fd, buffer, recv_buf_size)) <= 0) {
              //error

流结束不是错误。见下文。

//data is not enough. the missing part should come soon. but why I am not notified?

已通知。这就是你下次阅读的原因。但是你没有得到剩余的65536-55934个字节,下次你得到了一个完整的缓冲区。

每次发出读取时,您都没有理由期望65536字节。如果愿意,TCP可以一次传送一个字节。唯一相关的问题是你是否得到了你所期望的所有字节,并且你不能说你没有。

其他说明:

  • 如果r == 0打印errno无效。您不能区分两种错误和流结束的情况。

  • 您也不能区分任何错误情况。只有在errno == EAGAIN

  • 重新阅读时,它才有效
  • 我根本没有看到Nread()方法的要点。它只是需要打破的代码。只需在read()循环内拨打recv()epoll()即可。