Python Socket Flush

Bob*_*ury 6 python sockets

我试图确保每次调用socket.send函数时,我的缓冲区被发送(刷新)到我的服务器(使用unix socket在C中).

根据我的理解(以及我在这个板上看到的),只是禁用了naggle算法.应该这样做,但我的服务器仍然以4096字节(默认设置)的块接收我的数据...

我在Python v2.5.4中使用以下代码:

 self.sck = socket( AF_INET, SOCK_STREAM )

 self.sck.setsockopt( IPPROTO_TCP, TCP_NODELAY, 1 ) # That doesn't seems to work...

 self.sck.connect( ( "127.0.0.1", "12345" ) )

 while( 1 ):
      self.sck.send( "test\n" )
      self.sck.send( "" ) # Still trying to flush...
Run Code Online (Sandbox Code Playgroud)

启用/禁用TCP_NODELAY似乎没有任何影响......这是一个错误还是我遗漏了什么?

TIA

Gre*_*ill 8

TCP不提供任何类型的保证"数据包"发送到另一端.您正在尽可能快地发送数据,并且TCP有助于将数据批处理到尽可能多的时间.您的服务器一次接收4096字节的数据,可能是因为它(它在recv()呼叫中)要求的数据.

TCP是一种流协议,因此您必须自己实现某种框架.没有内置的消息边界.


xub*_*tix 6

无法确保发送的数据块的大小。如果要确保所有要发送的数据都已发送,可以关闭连接:

self.sck.close()
Run Code Online (Sandbox Code Playgroud)

另请注意,n = socket.send() 返回实际发送的字节数。如果你确实想发送所有数据,你应该使用

self.sck.sendall()
Run Code Online (Sandbox Code Playgroud)

或循环发送数据:

while data:
    n = self.sck.send(data)    
    data = data[n:]
Run Code Online (Sandbox Code Playgroud)

(但这与 sendall() 大致相同)。如果你想以更大的块接收数据,你可以增加recv()中缓冲区的大小,但这只会使可能的块大小更大。无法保证数据以这些大小到达。

  • 我明白了,但是就我而言,我需要进行“实时”交互......那么我的选择是什么?我的意思是 ie telnet 服务器是如何做到这一点的,只要您按下输入,命令就会直接发送,对于 FTP 客户端也是如此...我想重现类似的内容,就像我需要以 30fps 发送数据一样。 ..让缓冲区停止直到其满,然后发送或添加额外的数据只是为了确保缓冲区被推送对我来说似乎不是一个选择......那么我能做什么? (2认同)

Stu*_*eal 5

我得到一个刷新工作(回到C客户端)的唯一方法是使用:

my_writer_obj = mysock.makefile(mode='w', ...)
my_writer_obj.write('my stuff')
my_writer_obj.flush()
Run Code Online (Sandbox Code Playgroud)

最大的优点是my_writer_obj默认为文本模式,因此不再需要字节转换.

创建一个读者对象并没有那么顺利,但我并不需要那个同花顺.

  • 从Python3套接字页面:现在,有两组动词可用于通信。您可以使用send和recv,也可以将客户端套接字转换为类似文件的野兽并使用读写。后者是Java呈现其套接字的方式。除了警告您需要在套接字上使用flush之外,这里不再讨论。这些是缓冲的“文件”,一个常见的错误是写一些东西,然后阅读以得到答复。如果没有刷新,您可能会永远等待答复,因为请求可能仍在输出缓冲区中。 (2认同)