2016-04-22 82 views
2

发送数据到底发生了什么我已经从Socket Programming HOWTO in Python Documentation当套接字接收/ Python中

阅读您可以将您的客户端套接字到一个类文件的野兽,使用读写。 ...除了警告你,你需要在套接字上使用flush。这些都是缓冲的“文件”,一个常见的错误是写一些东西,然后阅读答案。如果没有在那里刷新,您可能会永远等待回复,因为请求可能仍在输出缓冲区中。

现在我们就来插座的主要绊脚石 - send和recv在网络缓冲区操作

在Python socket object是一个文件描述符,并且可以使用makefile()获得与插座相关的file object

据警告,

您需要在插座使用平齐。这些是缓冲“文件” ...如果没有在那里刷新,您可能会永远等待回复,,因为请求可能仍然在您的输出缓冲区 ...发送和recv操作网络缓冲区

我想当socket send/recv,实际上有两个缓冲区:“文件缓冲区”和“网络缓冲区”。如果将socket转换为file like object并使用write(data),首先将数据写入“文件输出缓冲区”,然后使用flush将数据写入“网络发送缓冲区”。所有这些都可以解释文档中的警告:在write之后使用flushread可能永远阻塞。

我画了一张照片,以显示我对socket潜在“两种缓冲区”的看法。

socket transfer data model

所以我的问题是如何理解上面的报价?我的“两种缓冲”模式是否理解正确?希望你的回复,谢谢!

回答

0

是的,你的模型基本上是正确的。理解该引用中引用的“网络缓冲区”驻留在操作系统中(即不在您的进程地址空间范围内)可能会有所帮助,而“文件缓冲区”实际上是在您的进程中由python运行时。这就是为什么flush是必需的:图中文件缓冲区和网络缓冲区之间的边界基本上是操作系统的“系统调用接口”。

换句话说,当您拨打socket.send时,缓冲区中的数据字节会直接传送到操作系统网络缓冲区(受空间可用性影响)。然后根据标准网络机制(TCP等)将它们发送到网络对等体。但是,当您使用makefile时,您基本上正在构建一个缓冲机制。当你写入“类文件对象”时,字节被简单地转移到一个与文件相关的隐藏缓冲区(但仍然在你的进程的地址空间内)。调用flush则相当于socket.send;将这些字节移动到操作系统的缓冲区中进行传输。

存在两种情况,其中一种通常使用makefile:(1)您还有一些其他现有代码需要使用类似文件的对象,以便通过网络构建要发送/接收的字节,或者(2)你想要缓冲行为,比如性能方面的原因(当然,你总是可以使用strbytes对象来实现这种缓冲,但是简单地写入文件类对象通常更方便)。