TCP套接字函数recv()阻塞程序

时间:2015-05-06 15:00:12

标签: python sockets tcp

我正在编写一个简单的TCP服务器程序。一切正常,但功能recv()不是。

import socket
import threading

def connectionHandler(sock):
    data="#1111#Welcome on Server!"
    sock.sendall(data.encode('ascii'))
    username = sock.recv(1024)
    password = sock.recv(1024)
    print('{}, {}'.format(username, password))
    conn.close()
HOST = socket.gethostname()
PORT = 8888
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(10)
while True:
    conn, addr = s.accept()
    print('Connected by', addr)
    t = threading.Thread(target=connectionHandler, args=(conn,))
    t.start()
conn.close()

当我评论对recv()的所有电话时,程序运行正常,但是当我想从我的客户端(智能手机上的Android客户端)接收答案时,程序会自行阻止(我认为{{ 1}}正在等待消息)。我知道我必须设置超时,但它并没有解决我的问题。我想先发送消息然后收到一些消息。为什么recv()阻止recv()

Android监听器功能:

sendall()

1 个答案:

答案 0 :(得分:2)

在Python服务器上,您发送:

data="#1111#Welcome on Server!"
sock.sendall(data.encode('ascii'))

在Java客户端上,您可以这样阅读:

inp = in.readLine(); 

readLine继续阅读,直到找到换行符。但是你永远不会发送换行符。所以它一直在阅读。

您还有其他需要解决的问题。

例如,您的Python代码假定TCP套接字是they're actually byte streams时的消息流,因此您的username = sock.recv(1024)可能同时获得用户名和密码,导致下一个recv永久阻止,或者它可能会获得一半的用户名并导致虚假的登录失败,或者您可以想象的任何其他内容。 (当然,Android代码甚至不发送其中任何一个这一事实是一个更大的问题,但我认为你知道这一点,并且还没有编写那些代码。)

这个问题实际上指的是解决此问题的一种方法:如果不允许任何消息包含换行符,则可以使用换行符作为消息的终止符。你已经在Java方面这样做了;您只需要记住在发送时添加\n。在Python方面,套接字上的makefile方法为您提供了一个类似文件的对象,与您在Java中使用的方法非常相似,它具有readline方法,因此您可以执行相同的操作在另一个方向。