2017-04-14 34 views
0

我从python文档复制了echo服务器的例子,它工作正常。但是当我编辑代码时,所以它不会将数据发送回客户端,而socket.recv()方法在第二次调用时不会返回。Python套接字没有收到没有发送

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)) 
+0

哪里的客户端的源代码?你只是直接连接'nc'或'telnet'? – Kevin

+0

直到客户端关闭连接后,接收才会返回。但客户在收到信息之前不会关闭连接。 – tdelaney

+0

我首先想在客户端收到服务器确认后关闭连接......我怎么能在我的情况下做到这一点? – no0by5

回答

2

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

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

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

我已更新客户端和服务器以关闭部分连接,并且还让客户端在传入数据碎片的情况下执行多个recv。不太完整的实现似乎适用于小型有效载荷,因为您不可能获得碎片,但在实际生产代码中可怕地破碎。

服务器

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)) 
+0

谢谢你,那正是我正在寻找的! – no0by5

3

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

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] 

由于服务器和客户端现在被阻止,所以程序无法继续。

解决的办法是删除客户端的接收呼叫,因为您删除了服务器的发送呼叫。

+0

好的,谢谢!有没有办法在收到所有数据后向客户发送答案? – no0by5

+0

@no0by5:客户端需要告诉服务器它将发送多少数据,以便服务器知道传递给'recv()'的值。目前,服务器只是试图接收“客户端发送的所有内容,直到客户端关闭连接为止”,如果客户端将停止发送并等待应答而不是关闭连接,则该功能不起作用。 – Kevin

+0

谢谢,我会试试! – no0by5

相关问题