POSIX套接字的send()函数在发送完整缓冲区之前返回。

3

以下是代码的大致样子:

int main() {
    // All the details needed before using the send() function here...

    send(socket, buffer, 1024*1024*1024, 0);
    return 1;
}

如果无论缓冲区的大小,send()都应该是阻塞的,那么我认为它不应该在整个缓冲区发送之前返回。但是根据我的观察,如果给定一个足够大的缓冲区,它会在send()发送整个缓冲区之前返回。
然而,如果在return语句之前添加以下代码:
while(1){}

send() 阻塞并按预期发送了所有数据。

send() 应该像这样阻塞,还是 send() 函数本身有问题?

提前致谢。


C语言没有socket函数。如果您使用POSIX套接字,请添加适当的标签[tag:posix]。 - phuclv
3个回答

3
当使用阻塞套接字时,send()函数会一直阻塞,直到最后一个数据传递到本地TCP堆栈的队列中。
因此,send()可能在部分数据仍在本地TCP堆栈中排队时返回。由于您的进程在send()调用之后退出,在退出期间本地TCP堆栈中可能存在未传递的数据。
如果启用了延迟关闭功能,则TCP堆栈可能会在退出后继续数据传输。如果禁用了延迟关闭功能,则TCP堆栈可能会重置连接而不尝试将未传递的数据传输到对等方。
如果启用了延迟关闭功能并优雅地关闭TCP连接,则TCP堆栈应该(尝试)将排队的数据传递给对等方。
通过添加close()调用来优雅地关闭连接。并确保启用了合理的超时时间的SO_LINGER:
send(socket,buffer, 1024*1024*1024,0);

const struct linger linger_val = { 1, 600 };
setsockopt(socket, SOL_SOCKET, SO_LINGER, &linger_val, sizeof(linger_val));

close(socket);
return 1;

通常情况下,不需要更改SO_LINGER。有关SO_LINGER的更多信息,请参阅socket(7)手册页

SO_LINGER
              When enabled, a close(2) or shutdown(2) will not return until
              all queued messages for the socket have been successfully sent
              or the linger timeout has been reached.  Otherwise, the call
              returns immediately and the closing is done in the background.
              When the socket is closed as part of exit(2), it always
              lingers in the background.

@suoyong:尝试增加SO_LINGER值。示例已添加到答案中。 - SKi

0

感谢回复,send()函数比write()函数更高层,但这并不能解释while(1){}代码。再次感谢。 - Courage

0

send() 是一个阻塞调用,但它会一直阻塞到所有数据都被推送到 sendbuffer 中。您可以修改程序,在套接字发送完所有数据后退出。这可以通过减小 sendbuffer 的大小来实现。您可以使用 setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)send_buffer, send_buffer_sizeof);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接