如何正确写入套接字

时间:2015-01-31 12:27:00

标签: c linux sockets

在关于man的Linux的write()页面中,它表示如果EINTREAGAIN write()将返回{{1} }}。执行-1时,如果遇到此类错误,可能会重试。在执行read()时,应该在这种情况下做些什么?

3 个答案:

答案 0 :(得分:1)

据我所知,处理此类情况的一种方法是将write()调用包装在一个函数中,该函数检查返回值以及errno变量。

EAGAINEINTR等案例表示write()失败的情况,因为某些信号中断或O_NONBLOCK已设置但write()会阻止。这意味着您可以通过探测write()状态重试errno

我不确定,但是,如果保证write()最终会成功,如果你坚持(当然,如果你没有得到任何不同的{{}} 1}}状态)。

您可以执行类似

的操作
errno

我还看过代码,其中上述情况通过执行

来处理
ssize_t insist_write(int fd, const void * buff, size_t cnt)
{
    ssize_t ret; 
    size_t original_cnt = cnt;
    while (cnt > 0)
    {
        ret = write(fd, buff, cnt);
        if (ret < 0) 
        {
            // EINTR for interrupted writes, EAGAIN - EWOULDBLOCK for file/socket
            // blocking case (see man page)
            if ((errno != EINTR) && (errno != EAGAIN) && (errno != EWOULDBLOCK))
               return ret;
            else 
               ret = 0;
        }
        // update buff and remaining bytes to write
        buff += ret;
        cnt -= ret;
    }
    return original_cnt;
}

而不是我写的内容,暗示这样的情况将在每个应用程序的基础上处理(一个这样的例子是在返回if (ret < 0) { return ret; } 之前指定最大write()次尝试次数。

答案 1 :(得分:1)

您可以在EINTR.

的情况下重试

如果您处于非阻塞模式,则只能获得EAGAIN/EWOULDBLOCK,在这种情况下,仅在循环中重试是不合适的。您应该select()直到套接字变为可写,然后重试。这只能在对等体读取内容时发生,这就是为什么在发送端刻录CPU周期不合适的原因。

答案 2 :(得分:-1)

通过检查write()EINTR,您可以打包到EAGAIN。在this问题中建议在这些情况下再次尝试write()的简单循环,并且可能效果很好: