清空套接字是什么意思?

29

除了像读写文件一样读写套接字,我对套接字并不是很了解。我知道一些关于使用套接字选择器的内容。我不明白为什么要刷新套接字,实际上发生了什么?比特就在内存中挂起直到被推出去吗?我在网上读了一些关于套接字的东西,但都非常抽象和高级。

这里实际上发生了什么?


从用户的角度来看,不存在刷新套接字这样的事情。然而,在内部是存在的。 - undefined
5个回答

56

写入网络套接字并发送数据需要一定的开销。如果每当一个字节进入套接字时都要发送数据,那么每个实际数据字节会有40多字节的TCP标头(当然,假设您使用的是TCP套接字,其他套接字的值将不同)。为了避免这种效率低下的情况,套接字维护一个本地缓冲区,通常略大于1000字节。当该缓冲区被填满时,将在数据周围包装一个标头并将数据分组发送到目的地。

在许多情况下,你不需要立即发送每个数据包;如果你正在传输文件,早期数据可能没有任何用处,除非文件的最终数据可用,因此这种方法很有效。但是,如果您需要强制立即发送数据,刷新缓冲区将发送尚未发送的任何数据。

请注意,在关闭套接字时,它会自动刷新任何剩余数据,因此不需要在关闭之前进行刷新。


2
NAGL 如何与此相关联,你知道吗? - rogerdpack
@rogerdpack它决定何时发送数据。与这个答案相反,它不仅仅发生在缓冲区满的时候。 - undefined

14

你不能真正地刷新一个套接字。

(来自如何强制套接字发送其缓冲区中的数据?)

你不能强制它。就是这样。TCP会自行决定何时发送数据。通常情况下,当你在TCP套接字上调用write()时,TCP确实会发送一个段,但是没有保证也没有办法强制这样做。有很多原因导致TCP不发送一个段:窗口关闭和Nagle算法是两个首先想到的原因。

阅读完整的帖子,它非常深入并为我澄清了很多事情。


4

Nagle算法常用于套接字中。简而言之,它会等待直到有足够的数据要发送。问题在于要在传输延迟和发送数据包的开销之间取得平衡。

数据负载越大,浪费的带宽就越小,因为头部是(大体上)固定大小的。此外,中间系统通常有基于数据包速率而非整体数据速率的性能限制。


2
这个答案并没有真正解释清楚如何与刷新套接字相关联。 - Quinn Taylor
这个答案与问题的相关性是什么?flush会覆盖Nagle算法并立即发送吗? - Al-Alamin
@QuinnTaylor 实际上是有的,一旦你意识到从用户的角度来看,根本就没有所谓的刷新套接字这回事。 - undefined
@Al-Alamin 除了这里所描述的方法,没有其他办法可以冲洗插座。 - undefined

1
在最低层级上,您使用recv()/WSARecv()和send()/WSASend()系统调用与TCP套接字进行交互,套接字没有刷新系统调用。
刷新是一个用户空间的概念。当一个库将操作系统套接字函数封装到自己的API中时,它可以实现自己的缓冲区,并且刷新会导致应用程序级别的缓冲区传递给send()系统调用。
请记住,send()系统调用不能保证立即发送,因为内核可能会在发送之前将传出数据缓冲约0.2秒,除非在套接字上设置了TCP_NODELAY标志。

1

我在套接字编程中从未使用过flush。我记得有一些模式可以设置,其中面向流的发送尝试减少发送的小数据包数量。但是,您应该使用sendall()确保缓冲区中的所有内容都已发送。

随着您的关闭,shutdown()函数非常有用。当然,如果您不想让东西挂起,必须使用close()调用。

请查看Beej's guide以获取更多信息。


3
sendall()和flush()是一样的。 - Georg Schölly

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