套接字recv /在Python中发送数据时发生了什么

时间:2016-04-22 18:22:57

标签: python sockets

我已从Socket Programming HOWTO in Python Documentation

中读到此内容
  

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

     

现在我们来到套接字的主要障碍 - 发送和recv操作网络缓冲区

Python中的

socket object是一个文件描述符,您可以使用makefile()来获取与套接字关联的file object

根据警告,

  

你需要在套接字上使用flush。这些是缓冲的“文件” ...如果没有刷新,你可能会永远等待回复,因为请求可能仍在你的输出缓冲区中 ...发送和接收操作网络缓冲区

我认为当socket send/recv时,实际上有两个缓冲区:"文件缓冲区"和"网络缓冲区"。如果您将socket转换为file like object并使用write(data),则首先将数据写入"文件输出缓冲区",然后写入"网络发送缓冲区&#34 ;使用flush。所有这些都可以解释文档中的警告:在flush之后使用writeread可能会永久阻止。

我画了一张照片来展示我对底层"两个缓冲区" socket

socket transfer data model

所以我的问题是如何理解上面的引用?是我的"两个缓冲区"模特要懂吗?希望你的回复,谢谢!

1 个答案:

答案 0 :(得分:0)

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

换句话说,当您调用socket.send时,缓冲区中的数据字节将直接传输到操作系统网络缓冲区(视空间可用性而定)。然后,它们将根据标准网络机制(TCP等)发送到网络对等体。但是,当您使用makefile时,您实际上是围绕此构建缓冲机制。当您写入"类似文件的对象"时,字节只会被转移到与文件关联维护的隐藏缓冲区(但仍在您的进程'地址空间内)。然后拨打flush,相当于socket.send;将这些字节移动到操作系统的缓冲区中进行传输。

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