我试图确保每次调用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
TCP不提供任何类型的保证"数据包"发送到另一端.您正在尽可能快地发送数据,并且TCP有助于将数据批处理到尽可能多的时间.您的服务器一次接收4096字节的数据,可能是因为它(它在recv()呼叫中)要求的数据.
TCP是一种流协议,因此您必须自己实现某种框架.没有内置的消息边界.
无法确保发送的数据块的大小。如果要确保所有要发送的数据都已发送,可以关闭连接:
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()中缓冲区的大小,但这只会使可能的块大小更大。无法保证数据以这些大小到达。
我得到一个刷新工作(回到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默认为文本模式,因此不再需要字节转换.
创建一个读者对象并没有那么顺利,但我并不需要那个同花顺.