【问题标题】:What really happened when socket recv/send data in Python在 Python 中套接字接收/发送数据时真正发生了什么
【发布时间】:2016-04-22 18:22:57
【问题描述】:

我从Socket Programming HOWTO in Python Documentation读到了这篇文章

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

现在我们来看看套接字的主要绊脚石 - send 和 recv 在网络缓冲区上操作

socket object在Python中是一个文件描述符,你可以使用makefile()来获取一个与socket关联的file object

根据警告,

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

上运行

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

我画了一张图片来表达我对socket 的底层“两个缓冲区”的看法。

socket transfer data model

所以我的问题是如何理解上面的引用?我的“两个缓冲区”模型理解正确吗?希望得到您的回复,谢谢!

【问题讨论】:

    标签: python sockets


    【解决方案1】:

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

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

    在两种情况下,通常会使用makefile:(1) 您有一些其他现有代码需要一个类似文件的对象,您希望使用该对象来构造要通过网络,或 (2) 您想要缓冲行为,例如,出于性能原因(当然,您始终可以使用 strbytes 对象自己实现此类缓冲,但通常更多方便简单地写入类似文件的对象)。

    【讨论】:

      猜你喜欢
      • 2013-11-19
      • 2017-07-13
      • 2013-03-21
      • 1970-01-01
      • 2019-07-04
      • 2017-01-12
      • 1970-01-01
      • 2016-09-12
      相关资源
      最近更新 更多