除了像读写文件一样读写套接字,我对套接字并不是很了解。我知道一些关于使用套接字选择器的内容。我不明白为什么要刷新套接字,实际上发生了什么?比特就在内存中挂起直到被推出去吗?我在网上读了一些关于套接字的东西,但都非常抽象和高级。
这里实际上发生了什么?
除了像读写文件一样读写套接字,我对套接字并不是很了解。我知道一些关于使用套接字选择器的内容。我不明白为什么要刷新套接字,实际上发生了什么?比特就在内存中挂起直到被推出去吗?我在网上读了一些关于套接字的东西,但都非常抽象和高级。
这里实际上发生了什么?
写入网络套接字并发送数据需要一定的开销。如果每当一个字节进入套接字时都要发送数据,那么每个实际数据字节会有40多字节的TCP标头(当然,假设您使用的是TCP套接字,其他套接字的值将不同)。为了避免这种效率低下的情况,套接字维护一个本地缓冲区,通常略大于1000字节。当该缓冲区被填满时,将在数据周围包装一个标头并将数据分组发送到目的地。
在许多情况下,你不需要立即发送每个数据包;如果你正在传输文件,早期数据可能没有任何用处,除非文件的最终数据可用,因此这种方法很有效。但是,如果您需要强制立即发送数据,刷新缓冲区将发送尚未发送的任何数据。
请注意,在关闭套接字时,它会自动刷新任何剩余数据,因此不需要在关闭之前进行刷新。
你不能真正地刷新一个套接字。
你不能强制它。就是这样。TCP会自行决定何时发送数据。通常情况下,当你在TCP套接字上调用write()时,TCP确实会发送一个段,但是没有保证也没有办法强制这样做。有很多原因导致TCP不发送一个段:窗口关闭和Nagle算法是两个首先想到的原因。
阅读完整的帖子,它非常深入并为我澄清了很多事情。
Nagle算法常用于套接字中。简而言之,它会等待直到有足够的数据要发送。问题在于要在传输延迟和发送数据包的开销之间取得平衡。
数据负载越大,浪费的带宽就越小,因为头部是(大体上)固定大小的。此外,中间系统通常有基于数据包速率而非整体数据速率的性能限制。
我在套接字编程中从未使用过flush。我记得有一些模式可以设置,其中面向流的发送尝试减少发送的小数据包数量。但是,您应该使用sendall()确保缓冲区中的所有内容都已发送。
随着您的关闭,shutdown()函数非常有用。当然,如果您不想让东西挂起,必须使用close()调用。
请查看Beej's guide以获取更多信息。