【问题标题】:Python socket not receiving without sendingPython套接字不接收而不发送
【发布时间】:2017-09-11 05:13:10
【问题描述】:

我从 python 文档中复制了 echo 服务器示例,它工作正常。但是当我编辑代码时,它不会将数据发送回客户端,第二次调用 socket.recv() 方法时不会返回。

import socket

HOST = ''
PORT = 50007 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)

conn, addr = s.accept()
print('Connected by', addr)

while True:
    data = conn.recv(1024)
    if not data: break
conn.sendall(b'ok')
conn.close()

在 python 文档的原始版本中,while 循环略有不同:

while True:
    data = conn.recv(1024)
    if not data: break
    conn.sendall(data)

客户代码:

import socket

HOST = 'localhost'
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall(b'Hello, world')
data = s.recv(1024)
s.close()
print('Received', repr(data))

【问题讨论】:

  • 客户端的源代码在哪里?您是直接与nctelnet 联系吗?
  • 在客户端关闭连接之前接收不会返回。但是客户端在收到东西之前不会关闭连接。
  • 我首先想在客户端收到服务器的 OK 后关闭连接......在我的情况下我该怎么做?
  • 你能解释一下为什么你第二次打电话给recv吗?另外,为什么客户端关闭套接字而不确保它已收到服务器打算发送的所有内容?
  • 对于客户端发送较大数据而1024的缓冲区不够大的情况。

标签: python sockets


【解决方案1】:

TCP 套接字是数据流。在一侧发送呼叫和在另一侧接收呼叫之间没有一对一的关联。根据您实施的协议,存在更高级别的相关性。在原始代码中,规则是服务器将准确发送它收到的内容,直到客户端关闭连接的传入端。然后服务器关闭了套接字。

随着你的改变,规则也改变了。现在服务器继续接收和丢弃数据,直到客户端关闭连接的传入端。然后服务器发送“ok”并关闭套接字。

使用第一条规则的客户端挂起,因为它在关闭套接字之前需要数据。如果它想使用这个新的服务器规则,它必须关闭它的输出端来告诉服务器它完成了,然后它可以得到返回数据。

我已更新客户端和服务器以关闭部分连接,并让客户端执行多次接收以防传入数据碎片化。不太完整的实现似乎适用于小型有效负载,因为您不太可能出现碎片,但在实际生产代码中会严重中断。

服务器

import socket

HOST = ''
PORT = 50007 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1)

conn, addr = s.accept()
print('Connected by', addr)

while True:
    data = conn.recv(1024)
    if not data: break
conn.sendall(b'ok')
conn.shutdown(socket.SHUT_WR)
conn.close()

客户

import socket

HOST = 'localhost'
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall(b'Hello, world')
s.shutdown(socket.SHUT_WR)
data = b''
while True:
    buf = s.recv(1024)
    if not buf:
        break
    data += buf
s.close()
print('Received', repr(data))

【讨论】:

  • 谢谢,这正是我想要的!
【解决方案2】:

接收和发送操作的数量必须匹配,因为它们是阻塞的。这是您的代码的流程图:

Server listen 
Client connect 
Server receive (this waits until a message arrives at the server) [1] 
Client send 'Hello world' (received by [1])
Server receive (because there was data received) [2]
Client receive [3]

因为现在服务器和客户端都被阻塞了,所以没有程序可以继续下去了。

解决方法是删除客户端的接收调用,因为您删除了服务器的发送调用。

【讨论】:

  • 好的,谢谢!有没有办法在收到所有数据后向客户端发送答案?
  • @no0by5:客户端需要告诉服务器它要发送多少数据,以便服务器知道要传递什么值给recv()。现在,服务器只是试图接收“客户端发送的所有内容,直到客户端关闭连接”,如果客户端要停止发送并等待回复而不是关闭连接,这将无法正常工作。
猜你喜欢
  • 2011-08-06
  • 1970-01-01
  • 1970-01-01
  • 2012-01-26
  • 1970-01-01
  • 2017-12-10
  • 2014-11-25
  • 2010-11-14
  • 1970-01-01
相关资源
最近更新 更多