错误码EWOULDBLOCK,错误码EINTR,SIGPIPE信号

错误码EWOULDBLOCK

在某些套接字的函数操作不能立即完成时,会出现错误码EWOULDBLOCKEAGAIN

Linux EINTR错误码

在类UNIX/Linux中调用一些socket函数时(connect,send,recv,epoll_wait等),除了在函数调用出错时会返回-1,这些函数可能被信号中断时也会返回-1,此时我们可以通过错误码errno判断是不是EINTR,来确定是不是被信号中断。如果是,则说明被信号中断,我们需要再次调用该函数进行重试。

bool SendData(const char* buf, int buf_length)
{
    //已发送的字节数
    int sent_bytes = 0;
    int ret = 0;
    while(true)
    {
        ret = send(m_hSocket, buf + sent_bytes, buf_length - sent_bytes, 0);
        if(nRet == -1)
        {
            if(errno == EWOULDBLOCK)
            {
                break;
            }
            else if(errno == EINTR)
                continue;
            else 
                return false;
        }
        else if(nRet == 0)
            return false;
        sent_bytes += ret;
        if(sent_bytes == buf_length)
            break;
    }
    return true;
}

Linux SIGPIPE信号

为了描述方便,以下将TCP的通信双方用A和B来代替。当A关闭连接时,若B继续向A发送数据,则根据TCP的规定,B会收到A的一个RST报文应答,若B继续向这个服务器发送数据,系统就会产生一个SIGPIPE信号给该B进程,告诉它这个连接已经断开了。系统对SIGPIPE信号的默认处理行为是让B进程退出。

操作系统对SIGPIPE信号的这种默认处理行为非常不友好,TCP是全双工的信道,可以看作两条单工信道,TCP连接两端的两个端点各负责一条。当对端执行close()关闭时,虽然本意是关闭整个两条信道,但本端只收到FIN包。按照TCP规定的语义,表示对端只关闭了其所负责的那一条单工信道,虽然不再发送数据,但仍然可以继续接收数据。

也就是说,因为TCP的限制,通信的一方无法获知对端的socket是调用了close()还是调用了shutdown()函数。

int shutdown(int socket,int how);

shutdown函数的参数how可以被设置为SHUT_RD,SHUT_WR,SHUT_RDWR分别表示关闭收通道,发通道或者同时关闭收发通道。

对一个已经收到FIN包的socket调用read/recv方法,如果接收缓冲区已经为空,则会返回0,这就是连接关闭状态。但第1次对其调用write/send方法时,如果发送缓冲区没问题,则发送成功(即write/send函数的返回值大于0),但发送的报文会导致对端回应RST报文。因为上一次程序调用write/send是正常的,所以再次尝试调用write/send函数时,会因为产生SIGPIPE信号而导致进程退出

为了避免出现这种情况,我们可以捕获SIGPIPE信号并对其进行处理或者忽略该信号,忽略该信号的代码如下:

signal(SIGPIPE, SIG_IGN);

这样设置后,第2次调用write/send方法时会返回-1,同时,errno错误码被置为SIGPIPE,程序便能知道对端已经关闭。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值