简体   繁体   English

Linux,C,epoll(),read()数据未完成?

[英]Linux, C, epoll(), read() data incompleted?

Linux, C. Below issue only happens by using epoll(). Linux,C。以下问题仅通过使用epoll()发生。 If I use select() on server socket, there is no data loss. 如果在服务器套接字上使用select(),则不会丢失数据。

============================= =============================

Update: I received errno =11 (Try again) in read(). 更新:我在read()中收到errno = 11(重试)。 Do I need to continue, or break the while loop? 我需要继续还是打破while循环?

============================= =============================

I have client side, send 1280 K data in 10 times (each time, I send 128K data); 我有客户端,在10次中发送1280 K数据(每次,我发送128K数据);

I have server side, use epoll() to watch incoming data. 我在服务器端,使用epoll()监视传入的数据。

Once I got notified, I use below code to read data: 收到通知后,我将使用以下代码读取数据:

nbytes = Nread(current_fd, buffer, bytes_to_be_read);

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 < 1) {
                          printf("errno: %d\n", errno);
                          break;  //I do received 2 errors of Try Again. How to try again?
                  }

                  left -= r;
                  buffer += r;
          }
          printf("=> done, %ld\n", total - left);
          return count - left;
  }

In Nread, I expected to read bytes_to_be_read (65536) bytes and return. 在Nread中,我希望读取bytes_to_be_read(65536)字节并返回。

But, when run the tool, I found server side just receive something like this. 但是,运行该工具时,我发现服务器端只会收到类似的信息。 Look like I did not read all data from the buffer in some cases. 在某些情况下,我似乎没有从缓冲区读取所有数据。 Why? 为什么?

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

=============== ===============

update: 更新:

if I use this code to read all data, then there is no bytes loss. 如果我使用此代码读取所有数据,则不会丢失任何字节。 but the performance is bad: 但是性能很差:

 36 int read_all(int fd, char *buffer)
 37 {
 38         ssize_t count = 0, bytes = 0;
 39
 40         while(1){
 41                 bytes = read(fd, buffer, sizeof(buffer));
 42                 if (bytes < 1)
 43                         break;
 44                 count += bytes;
 45         }
 46         return count;
 47 }

=================================== ===================================

EPOLL() EPOLL()

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)    ;
           }

}
        break;  //I do received 2 errors of Try Again. How to try again?

By going back to your epoll loop. 回到您的epoll循环。

        data: 60734  //??? why I am not able to read all 65536 bytes?

Because they hadn't been received yet. 因为尚未收到。

I think you may miss the big picture on how you do non-blocking I/O with epoll . 我认为您可能会错过如何使用epoll进行非阻塞I / O的epoll

  1. epoll tells you when there's data. epoll告诉您何时有数据。
  2. You read as much as you can at that time. 您当时可以阅读的内容尽可能多。
  3. You go back to step 1. 您返回到步骤1。
 event.events = EPOLLIN | EPOLLET;

You are doing edge triggered polling. 您正在执行边缘触发的轮询。 Which means your last read is probably not reading all the available data. 这意味着您上次读取的可能不是读取所有可用数据。 It stops after reading 64k data, even if there is more data available. 即使有更多数据可用,它也会在读取64k数据后停止。 But the poll will not trigger again due to the edge trigger. 但是由于边缘触发,轮询不会再次触发。 Suggest removing EPOLLET . 建议删除EPOLLET

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM