解决:阻塞socket连接成功情况下recv返回值为-1

引言

直入正题 在前几天进行Web服务器的编写时遇到了这么一个奇怪的问题 就是在socket连接成功且在epoll触发可读事件以后recv却没有收到任何东西 返回-1 在解决后遂记录一篇博客

首先在刚开始我使用了ET非阻塞,所以在出现recv返回值为-1 且 errno等于EAGAIN时当然首先想到的就是一次没有收到这个包 循环接收即可 但当我改为循环接收时却发现每一次都没有收到这个包 即陷入了死循环 这就很奇怪了, 这个时候鸭鸭学长告诉要不改成LT 但是不recv看看包是否发到,结果发现包确实是接收到了, 但当我加上recv时 心想应该出现阻塞或接收成功时却出现了死循环的情况,这是阻塞啊,奇怪奇怪, 怎么会出现这种情况呢,这个时候突然想起recv的第四个参数有一个是可以使本次recv成为非阻塞的,难道是参数的问题,一看socket类的构造函数,顺手把第四个参数的默认参数写成了-1,这个时候问题的答案也就水落石出了,-1的补码为1111 1111 1111 1111,下面是recv的第四个参数

/* Bits in the FLAGS argument to `send', `recv', et al.  */
enum
  {
    MSG_OOB     = 0x01,    /* Process out-of-band data.  */
#define MSG_OOB     MSG_OOB
    MSG_PEEK        = 0x02,    /* Peek at incoming messages.  */
#define MSG_PEEK    MSG_PEEK
    MSG_DONTROUTE   = 0x04,    /* Don't use local routing.  */
#define MSG_DONTROUTE   MSG_DONTROUTE
#ifdef __USE_GNU
    /* DECnet uses a different name.  */
    MSG_TRYHARD     = MSG_DONTROUTE,
# define MSG_TRYHARD    MSG_DONTROUTE
#endif
    MSG_CTRUNC      = 0x08,    /* Control data lost before delivery.  */
#define MSG_CTRUNC  MSG_CTRUNC
    MSG_PROXY       = 0x10,    /* Supply or ask second address.  */
#define MSG_PROXY   MSG_PROXY
    MSG_TRUNC       = 0x20,
#define MSG_TRUNC   MSG_TRUNC
    MSG_DONTWAIT    = 0x40, /* Nonblocking IO.  */
#define MSG_DONTWAIT    MSG_DONTWAIT
    MSG_EOR     = 0x80, /* End of record.  */
#define MSG_EOR     MSG_EOR
    MSG_WAITALL     = 0x100, /* Wait for a full request.  */
#define MSG_WAITALL MSG_WAITALL
    MSG_FIN     = 0x200,
#define MSG_FIN     MSG_FIN
    MSG_SYN     = 0x400,
#define MSG_SYN     MSG_SYN
    MSG_CONFIRM     = 0x800, /* Confirm path validity.  */
#define MSG_CONFIRM MSG_CONFIRM
    MSG_RST     = 0x1000,
#define MSG_RST     MSG_RST
    MSG_ERRQUEUE    = 0x2000, /* Fetch message from error queue.  */
#define MSG_ERRQUEUE    MSG_ERRQUEUE
    MSG_NOSIGNAL    = 0x4000, /* Do not generate SIGPIPE.  */
#define MSG_NOSIGNAL    MSG_NOSIGNAL
    MSG_MORE        = 0x8000,  /* Sender will send more.  */
#define MSG_MORE    MSG_MORE
    MSG_WAITFORONE  = 0x10000, /* Wait for at least one packet to return.*/
#define MSG_WAITFORONE  MSG_WAITFORONE
    MSG_BATCH       = 0x40000, /* sendmmsg: more messages coming.  */
#define MSG_BATCH   MSG_BATCH
    MSG_ZEROCOPY    = 0x4000000, /* Use user data in kernel path.  */
#define MSG_ZEROCOPY    MSG_ZEROCOPY
    MSG_FASTOPEN    = 0x20000000, /* Send data in TCP SYN.  */
#define MSG_FASTOPEN    MSG_FASTOPEN

    MSG_CMSG_CLOEXEC    = 0x40000000  /* Set close_on_exit for file
                       descriptor received through
                       SCM_RIGHTS.  */
#define MSG_CMSG_CLOEXEC MSG_CMSG_CLOEXEC
  };

也就是说在参数设置-1的情况下阴差阳错的注册了第四个参数的所有选项, 其中的MSG_DONTWAIT使得阻塞情况下陷入了循环接收 , MSG_OOB带外数据接收使得触发可读事件却无法正常接收数据,至此这个问题就解决了。

同时我们也可以看出在非阻塞的情况下并非在errno == EAGAIN的情况就是可以忽略的

原文链接: https://www.cnblogs.com/lizhaolong/p/16437373.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    解决:阻塞socket连接成功情况下recv返回值为-1

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/395785

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月5日 下午1:42
下一篇 2023年4月5日 下午1:42

相关推荐