关于epoll中的read函数说明

之前写过一篇关于 Linux 下面采用 epoll 设计服务器应用程序的文章,时隔很久了,最近发现一个问题,是关于 read 函数读取报文时候问题,这里提出来。
epoll 并不像 windows 下的完成端口那样,可以通知用户此次事件(收数据或者发数据)的数据量有多少,因此在读取数据的时候就比较麻烦了,因为 epoll 通知你只是有新数据到达了,并不告诉你有多少,因此需要应用层运用循环不断的收数据,知道结束。结合下面的源代码进行分析一下。
while(m_RcvedLen < TotalSize) {
    if((Rcv = read(m_sClient, m_Buffer, (TotalSize - m_RcvedLen))) < 0) {
      if(EAGAIN == errno) {
        break;
      }
      else {
        perror("read fail");
        close(m_sClient);
        return -1;
      }
    }
    else if(0 == Rcv){
      close(m_sClient);        
      return -2;
    }
    else {
      m_RcvedLen += Rcv;
    }
  }
 
上面的代码是先读报头,后读报体的。原来是直接读,给 read 函数的第三个参数一个很大的值,知道 read 函数返回错误 EAGAIN 才表示没有数据可以读了,但是这样会出现一个问题,当客户端发送了数据之后就直接关闭 socket ,此时服务端第一包读取正常,这时循环继续读下一报,此时 read 函数不会返回 EAGAIN ,而是返回 0 ,表示客户端已经关闭连接了。所以,在服务端读取的时候,一定要先读报文,从报文中获得此次报文的大小,然后依次来作为接收结束的判断条件。这样上层就可以根据 read 函数的返回值不同,区分出( 1 )还有报文可读( 2 )报文已经读完( 3 )对方关闭 socket 三种情况了。

你可能感兴趣的:(职场,epoll,read,休闲)