1、recv 和 recvfrom
=0 当返回值为0时,表示对端已经关闭了这个链接,我们应该自己关闭这个链接,即close(sockfd)。另外因为异步操作会用select或 epoll做事件触发,所以:
① 如果使用select,应该使用FD_CLR(sockfd,fd_set)将sockfd清除掉,不再监听
② 如果使用epoll,系统会自己将 sockfd 清除掉,不再进行监听。
>0 当返回值大于0 且 小于 sizeof(buffer) 时,表示数据肯定读完。(如果等于sizeof(buffer),可能有数据还没读,应该继续读,不可能有大于)
<0 当返回值小于0,即等于-1时,分情况判断:
① 如果 errno 为 EAGAINE 或 EWOULDBLOCK /* Operation would block */
表示暂时无数据可读,可以继续读,或者等待epoll或select的后续通知。(EAGAINE,EWOULDBLOCK产生的原因:可能是多进程读同一个sockfd,可能一个进程读到数据,其他进程就读取不到数据(类似惊群效应),当然单个进程也可能出现这种情况。对于这种错误,不需用close(sockfd)。可以等待select或epoll的下一次触发, 继续读。),这里有一点需要说明的是当采用epoll的边沿触发模式时,必须一次性将缓冲区的数据全部读完,即读到errno == EAGAINE 为止。
② 如果 errno 为 EINTR
表示被中断了,可以继续读,或者等待epoll或select后续的通知。
否则,真的是读取数据失败。(此时应该close(sockfd))
2、send和sendto
返回值是实际发送的字符数,因为我们知道要发送的总长度,所以,如果没有发送完,我们可以继续发送。
<0 当返回值为-1时,我们需要判断 errno:
① 如果errno为 EAGAINE 或 EWOULDBLOCK ,表示当前缓冲区写满,可以继续写,
或者等待epoll或select的后续通知,一旦发送缓冲区由满变为不满,就会触发写操作,这个也是经常利用的一个特性。
② 如果errno为EINTR ,表示被中断了,可以继续写,或者等待epoll或select的后续通知。
否则真的出错了,即 errno 不为 EAGAINE 或 EWOULDBLOCK 或 EINTR,此时应该close(sockfd)
>=0 >=0且不等于要求发送的长度,应该继续send直到发送完毕,如果等于要求发送的长度,发送完毕。