2015-09-21 4 views
0

Это новая тема для обсуждения этой темы: Linux, C, epoll(), read() data incompleted?Linux, C, Epoll() следующим образом: сервер не получил уведомление для остальных байт

У меня есть Epoll) использовать серверный сокет режим (Level-триггера.

Клиент отправляет данные 10 * 128K;

На стороне сервера, я использовал буфер 64K для получения, поэтому я должен быть уведомлен хотя бы 20 раз, чтобы получить все байты от клиента.

Но моя отладка показывает, что я только что уведомил 19 раз, и некоторые байты отсутствуют! Почему я не уведомляюсь о остальных байтах?

======== EDIT 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

Вы не получили много радости в последний раз, когда задавали этот вопрос. Потому что вам нелегко ответить людям. Укажите [MCVE] (https://stackoverflow.com/help/mcve). Например, 'total' используется, но не определен в' Nread'. Как мы должны интерпретировать результаты, когда нам приходится постоянно выводить из вас информацию о вас?Пожалуйста, предоставьте MCVE. – kaylum

+0

Спасибо Алан. Я обновляю код, чтобы отразить общее количество. –

+0

Возврат -100 вместо -1 не является чем-то вроде улучшения этого кода. Это бессмысленно. Вам нужно исправить * настоящие * проблемы с этим кодом, ваши ожидания и ваше понимание того, что вам сейчас сказали дважды, [здесь] (http://stackoverflow.com/questions/32661436/linux-c- epoll-read-data-unfompleted) и [здесь] (http://stackoverflow.com/a/32706074/207421). – EJP

ответ

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