如何写入非阻塞套接字(使用 epoll 时)

Cap*_*man 0 c sockets linux epoll

当在非阻塞套接字上使用 epoll 进行异步套接字 IO 时,读取似乎很简单:直到epoll_wait套接字准备好读取,然后读取直到获得EAGAIN/ EWOULDBLOCK

但是怎么发送呢?据推测,执行单个大型send操作会阻塞,因此您将始终得到EAGAIN/ EWOULDBLOCK。你打算做什么?

Mar*_*lli 5

据推测,内核将无法立即发送所有send数据,这就是为什么成功时返回发送的字节数。重要的是返回的数字可以(并且很可能)小于调用中指定的总长度。仅当根本无法发送任何字节时,您才会得到EAGAIN/EWOULDBLOCK答案。因此,当发送大量数据时,您只需要正确处理(很可能)并非一次发送所有数据的可能性。

注意:这对于数据报 (UDP) 套接字有所不同,因为无法发送部分数据报。有关详细信息,请参阅POSIX:UDP 套接字上的 write() 返回值。

下面是一个假设 (TCP) 套接字的示例SOCK_STREAM

size_t len;
size_t sent;
char *buf;

/* ... prepare data ... */

while (sent < len) {
    ssize_t n;

    if ((n = send(sockfd, buf + sent, len - sent, flags)) == -1) {
        if (errno == EAGAIN || errno == EWOULDBLOCK)
            continue;

        perror("send failed");
        exit(1);
    }
    
    sent += n;
}
Run Code Online (Sandbox Code Playgroud)

  • 需要明确的是,只有在没有阻塞的情况下根本无法传输任何字节的情况下,以非阻塞模式打开的文件描述符上的“发送”(或“写入”)才会失败,并显示“EAGAIN”/“EWOULDBLOCK”。此外,部分发送并不意味着立即尝试发送其余数据必然会发送失败。 (3认同)