为什么需要睡觉(1)让插座漏掉?

时间:2014-10-06 01:55:08

标签: c++ c sockets

我从中下载了一个简单的静态Web服务器的源代码 http://www.ibm.com/developerworks/systems/library/es-nweb/sidefile1.html

但是,我对第130行感到困惑:

#ifdef LINUX
sleep(1);       /* to allow socket to drain */    
#endif

exit(1);

由于套接字没有关闭,这是否意味着我需要等待客户端关闭套接字?

2 个答案:

答案 0 :(得分:4)

无论作者的意图如何,不必要不正确exit()就足够了。在TCP套接字上调用close()或调用exit()来终止进程时,除非SO_LINGER套接字选项已设置为非默认设置,否则内核将保留套接字(s)处于等待状态并尝试传递任何未传递/缓冲的数据。您可以使用netstat看到这一点,并且快速重新启动未快速重新启动的TCP服务器将很快重新打开端口(有一种正确的方法可以实现此目的)。

我在接受的答案中不同意一些事情。

close()exit()应该对套接字产生相同的影响,传统上,如果您要close exit套接字是否只是write()套接字的风格问题。

它应该与溢出TCP发送缓冲区无关,因为它发生在所有写入之后。完全写缓冲区将立即通过sleep(1)返回码返回错误;最后睡觉与此无关。

{{1}}应该对套接字缓冲区或可靠的数据传递没有影响。如果有的话,这段代码会在写入后限制Web服务器子进程,因此实际上没有任何好的效果,并且实际上可能会增加拒绝服务攻击的可能性。

我正在描述默认操作。可以通过许多选项更改默认值。

对于"圣经"有关套接字编程的信息,请参阅W. Richard Steven的 UNIX网络编程 - 网络API:套接字和XTI ,详细介绍了这一点。

答案 1 :(得分:1)

对我来说,这看起来像是一些草率的代码。

如果打开套接字的进程终止,并且套接字有一些未写入的数据,则内核将拆除套接字而不刷新未发送的数据。

当您向套接字写入内容时,写入的数据不一定会立即传输。内核维护一个小缓冲区,用于收集写入套接字的数据。或管道。让进程继续进行更有效率,然后内核将在有时间的情况下负责实际传输写入的数据。

进程显然可以比通过典型的网络接口传输数据更快地将数据写入套接字,并且内部套接字缓冲区的大小是有限的,因此如果进程继续将数据写入套接字,则在某些时候它将填满内部缓冲区,并且必须等到内核实际传输数据,并从内部缓冲区中删除写入的数据,然后才能写更多内容。

[*]我省略了一些技术细节,例如在接收方确认数据之前,数据不会被考虑。

无论如何,sleep()调用的意图似乎是在进程终止之前允许实际传输内部缓冲区一些时间,因为如果它在实际数据写入之前执行,则正如我刚才提到的,内核不会发送它并终止套接字。

这是一个糟糕的例子。这不是做这些事情的正确方法。套接字应该只是close()d。这样可以正确地清除问题并确保一切都按照它应该去的地方进行。我看不出有什么正当的理由说明为什么这个例子没有正确关闭套接字,而不是搞这种hackery。