Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python tcp套接字-为什么sendall消息仅在close()之后发送_Python_Networking_Tcp_Blocking_Recv - Fatal编程技术网

python tcp套接字-为什么sendall消息仅在close()之后发送

python tcp套接字-为什么sendall消息仅在close()之后发送,python,networking,tcp,blocking,recv,Python,Networking,Tcp,Blocking,Recv,我正在尝试编写perl TCP server/python TCP client,现在我有了这样的代码: 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(messag

我正在尝试编写perl TCP server/python TCP client,现在我有了这样的代码:

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()之后收到消息。服务器的工作方式类似于echo服务器,在收到消息后向客户端发送数据。这会导致死锁,服务器永远得不到消息,客户端永远得不到响应。有什么问题吗?在
close()
过程中会发生什么,该消息会传到服务器?

我想冒险猜测这是由于服务器的实现。有许多方法可以编写echo服务器:

  • 在循环(或异步回调)中接收字节,直到EOF;在接收字节时(每次循环迭代),在不进行任何处理或缓冲的情况下对其进行回显;当发现EOF(入站流关闭)时,关闭出站流
  • 一次读取行(假设它是文本协议),即查找CR/LF/EOF;找到行时,返回行-找到EOF时(入站流关闭),关闭出站流
  • 读给一个EOF;然后返回所有内容并关闭出站流
如果echo服务器使用第一种方法,它将按照预期工作-因此我们可以对此打折

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

如果是第三种方法,那么请再说一遍——除非关闭出站流,否则它将死锁

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

  • 使echo服务器响应原始数据,而不是行
  • 添加行尾标记
  • 在客户端关闭出站流,即客户端到服务器流(许多网络API允许您分别关闭出站流和入站流)

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

    我冒险猜测这是由于服务器的实现。有许多方法可以编写echo服务器:

    • 在循环(或异步回调)中接收字节,直到EOF;在接收字节时(每次循环迭代),在不进行任何处理或缓冲的情况下对其进行回显;当发现EOF(入站流关闭)时,关闭出站流
    • 一次读取行(假设它是文本协议),即查找CR/LF/EOF;找到行时,返回行-找到EOF时(入站流关闭),关闭出站流
    • 读给一个EOF;然后返回所有内容并关闭出站流
    如果echo服务器使用第一种方法,它将按照预期工作-因此我们可以对此打折

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

    如果是第三种方法,那么请再说一遍——除非关闭出站流,否则它将死锁

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

  • 使echo服务器响应原始数据,而不是行
  • 添加行尾标记
  • 在客户端关闭出站流,即客户端到服务器流(许多网络API允许您分别关闭出站流和入站流)

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

    您告诉它recv 1024字节,但只发送了4个。@stark:发送和接收是链接的,但操作是不同的。@user1040813:您绝对确定在调用
    .close()
    之前不会发送数据吗?您是否与Wireshark等公司进行了核实?可能接收端正在缓冲等待线路端的数据,并在看到连接已关闭且不需要更多数据时取消该缓冲。这是很常见的。@LightnessRacesinOrbit我倾向于同意这是有责任的,但这取决于几个因素。。。我怀疑,很大程度上取决于服务器是如何编写的——这是我们看不到的。我们也许能够做出有根据的猜测,虽然是的,“问题”在于缓冲。关闭期间缓冲区被刷新,这就是为什么关闭后我收到消息。您告诉它recv 1024字节,但您只发送了4个。@stark:发送和接收是链接的,但操作不同。@user1040813:您绝对确定在调用
    .close()
    之前不会发送数据吗?您是否与Wireshark等公司进行了核实?可能接收端正在缓冲等待线路端的数据,并在看到连接已关闭且不需要更多数据时取消该缓冲。这是很常见的。@LightnessRacesinOrbit我倾向于同意这是有责任的,但这取决于几个因素。。。我怀疑,很大程度上取决于服务器是如何编写的——这是我们看不到的。我们也许能够做出有根据的猜测,虽然是的,“问题”在于缓冲。在关闭过程中,缓冲区被刷新,这就是为什么关闭后我会收到消息。