Linux中,C,epoll的(),读()数据未完? [英] Linux, C, epoll(), read() data incompleted?

查看:114
本文介绍了Linux中,C,epoll的(),读()数据未完?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

的Linux,C以下问题只能通过epoll的发生()。如果我的服务器套接字使用select(),不存在数据丢失。

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

更新:
我在读收到错误号= 11(再试)()。
我需要继续,或打破while循环?

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

我有客户端,在10次(每次,我送128K数据)发送1280 K个数据;

我有服务器端,使用epoll的()观看输入数据。

一旦我得到通知,我使用下面code读取数据:

 的nbytes = NREAD(current_fd,缓冲,bytes_to_be_read);INT NREAD(INT FD,字符*缓冲区,为size_t计数)
  {
          ssiz​​e_t供ř;
          size_t型左=计数;
          输出(===> \\ n);
          而(左大于0){
                  R =读(FD,缓冲,左);
                  的printf(数据:%LD \\ N,R);
                  如果(为r 1){
                          的printf(错误号:%d个\\ N,错误号);
                          打破; //我收到尝试的2个错误再次。如何再试一次?
                  }                  左 - = R;
                  缓冲区+ = R;
          }
          的printf(=>完成后,LD%\\ n,总 - 左);
          返回计数 - 左;
  }

在NREAD,我希望阅读bytes_to_be_read(65536)个字节和回报。

但是,当运行该工具,我发现服务器端收到只是这样的事情。看起来像我没有在某些情况下,缓冲区中读取的所有数据。为什么呢?

  1 ===>
数据:65536
= GT;完成后,65536
2 ===>
数据:65536
= GT;完成后,65536
3 ===>
数据:60734
数据:4802
= GT;完成后,65536
4 ===>
数据:55934
数据:-1
错误号:11
= GT;完成后,55934 //数据是不够的。缺少的部分应该很快到来。但我为什么不通知?
5 ===>
数据:60736
数据:4800
= GT;完成后,65536
6 ===>
数据:65536
= GT;完成后,65536
7 ===>
数据:65536
= GT;完成后,65536
8 ===>
数据:65536
= GT;完成后,65536
9 ===>
数据:65536
= GT;完成后,65536
10 ===>
数据:65536
= GT;完成后,65536
11 ===>
数据:65536
= GT;完成后,65536
12 ===>
数据:65536
= GT;完成后,65536
13 ===>
数据:65536
= GT;完成后,65536
14 ===>
数据:65536
= GT;完成后,65536
15 ===>
数据:65536
= GT;完成后,65536
16 ===>
数据:65536
= GT;完成后,65536
17 ===>
数据:65536
= GT;完成后,65536
18 ===>
数据:65536
= GT;完成后,65536
19 ===>
数据:65536
= GT;完成后,65536

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

更新:

如果我用这个code读取所有数据,那么就没有字节的损失。但表现糟糕的:

  36 INT read_all(INT FD,字符*缓冲)
 37 {
 38 ssize_t供计数= 0,字节= 0;
 39
 40,而(1){
 41字节=读(FD,缓冲器,的sizeof(缓冲液));
 42,如果(字节< 1)
 43休息;
 44数+ =字节;
 45}
 46返回计数;
 47}

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

EPOLL()

  EFD = epoll_create1(0);
event.data.fd = listener_fd;
event.events = EPOLLIN | EPOLLET;
epoll_ctl(EFD,EPOLL_CTL_ADD,listener_fd,&安培;事件);而(1){
    n_fds = epoll_wait(EFD,事件,MAX_EPOLL_EVENTS,-1);
    对于(i = 0; I< n_fds;我++){
                ...........
       如果(islistener){
             .....
            //处理新的连接
       }
      其他{
           bzero(缓冲,recv_buf_size);
           如果((N = NREAD(FD,缓冲器,recv_buf_size))≤; = 0){
                  //错误
           }
           其他
           {
                   //增加字节总数:
                    __sync_fetch_and_add(及(mythreads-> total_bytes_transferred)中,n);
           }}


解决方案

  event.events = EPOLLIN | EPOLLET;

您正在做的边沿触发轮询。这意味着你的最后一次读取很可能无法读取所有可用的数据。它停止读取64k的数据后,即使有更多的可用数据。但是轮询将不会由于边缘触发再次触发。建议删除 EPOLLET

Linux, C. Below issue only happens by using epoll(). If I use select() on server socket, there is no data loss.

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

Update: I received errno =11 (Try again) in read(). Do I need to continue, or break the while loop?

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

I have client side, send 1280 K data in 10 times (each time, I send 128K data);

I have server side, use epoll() to watch incoming data.

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.

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()

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

}

解决方案

 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. But the poll will not trigger again due to the edge trigger. Suggest removing EPOLLET.

这篇关于Linux中,C,epoll的(),读()数据未完?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆