gpt4 book ai didi

python tcp socket - 为什么sendall消息只在close()之后发送

转载 作者:可可西里 更新时间:2023-11-01 02:37:27 24 4
gpt4 key购买 nike

我正在尝试编写 perl TCP 服务器/python TCP 客户端,我现在有这样的代码:

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ("127.0.0.1", 9000)
sock.connect(server_address)

try:
message = unicode('Test')
sock.sendall(message)
data = sock.recv(1024)
print data
finally:
sock.close()

而且我注意到,我的 TCP 服务器(用 perl 编写)不是在 sendall(message) 之后,而是在 close() 之后收到消息。服务器就像一个回显服务器,在收到消息后将数据发送给客户端。这会导致死锁,服务器永远不会收到消息,客户端永远不会收到响应。可能是什么问题? close() 期间会发生什么,该消息到达服务器?

最佳答案

我敢猜测这是由于服务器的实现造成的。有多种编写回显服务器的方法:

  • 在循环(或异步回调)中接收字节,直到 EOF;当接收到字节时(每次循环迭代),在不进行任何处理或缓冲的情况下回显它们;当发现 EOF(入站流关闭)时,关闭出站流
  • 一次读取(假设它是一个文本协议(protocol)),即寻找 CR/LF/EOF;当找到一行时,返回该行 - 当找到 EOF 时(入站流关闭),关闭出站流
  • 阅读到EOF;然后返回所有内容并关闭出站流

如果回显服务器使用第一种方法,它会按预期工作 - 所以我们可以打折扣。

对于第二种方法,您正在发送文本但没有 CR/LF,并且您没有关闭从客户端到服务器 (EOF) 的流,因此服务器永远不会回复此请求。所以是的,它会陷入僵局。

如果是第三种方法,则再次 - 除非您关闭出站流,它将死锁

从您的回答来看,添加 \n 似乎可以“修复”它。由此,我得出结论,您的 echo-server 是基于线路的。所以有两个解决方案,第三个适用于任何场景:

  1. 使回显服务器响应原始数据,而不是线路
  2. 添加行尾标记
  3. 关闭客户端的出站流,即客户端到服务器的流(许多网络 API 允许您分别关闭出站和入站流)

另外:确保 Nagle 被禁用(通常称为 NO_DELAY)——这将防止字节在客户端等待一段时间,等待组合成一个合适大小的数据包(这适用于 1 和 2,但不适用于 3;具有启用 Nagle 会增加延迟,但通常不会导致死锁

关于python tcp socket - 为什么sendall消息只在close()之后发送,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12997562/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com