TCP套接字函数recv()阻塞程序
TCP socket function recv() blocking program
我正在编写一个简单的 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 客户端)接收答案时,程序自身阻塞(我认为 recv()
正在等待消息)。我知道我必须设置超时,但这并不能解决我的问题。我想先发送消息,然后再接收一些东西。为什么 recv()
阻止 sendall()
?
Android 侦听器函数:
public String listener(Socket x) throws IOException{
try {
Log.d("Listener","Started");
String inp;
BufferedReader in = new BufferedReader(new InputStreamReader(x.getInputStream()));
inp = in.readLine();
Log.d("Listener","Ended");
return inp;
} catch (UnknownHostException e1) {
e1.printStackTrace();
return "ERROR";
} catch (IOException e1) {
e1.printStackTrace();
return "ERROR";
}
}`
在 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 代码甚至不发送它们中的任何一个是一个更大的问题,但我假设您知道这一点并且还没有编写该代码。)
这个问题实际上指出了解决这个问题的一种方法:如果允许 none 的邮件包含换行符,您可以只使用换行符作为邮件的终止符。您已经在 Java 方面这样做了;你只需要记得在发送时添加一个\n
。在 Python 方面,套接字上的 makefile
方法为您提供了一个类似文件的对象,与您在 Java 中所做的非常相似,它有一个 readline
方法, 所以你可以在另一个方向做同样的事情。
我正在编写一个简单的 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 客户端)接收答案时,程序自身阻塞(我认为 recv()
正在等待消息)。我知道我必须设置超时,但这并不能解决我的问题。我想先发送消息,然后再接收一些东西。为什么 recv()
阻止 sendall()
?
Android 侦听器函数:
public String listener(Socket x) throws IOException{
try {
Log.d("Listener","Started");
String inp;
BufferedReader in = new BufferedReader(new InputStreamReader(x.getInputStream()));
inp = in.readLine();
Log.d("Listener","Ended");
return inp;
} catch (UnknownHostException e1) {
e1.printStackTrace();
return "ERROR";
} catch (IOException e1) {
e1.printStackTrace();
return "ERROR";
}
}`
在 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 代码甚至不发送它们中的任何一个是一个更大的问题,但我假设您知道这一点并且还没有编写该代码。)
这个问题实际上指出了解决这个问题的一种方法:如果允许 none 的邮件包含换行符,您可以只使用换行符作为邮件的终止符。您已经在 Java 方面这样做了;你只需要记得在发送时添加一个\n
。在 Python 方面,套接字上的 makefile
方法为您提供了一个类似文件的对象,与您在 Java 中所做的非常相似,它有一个 readline
方法, 所以你可以在另一个方向做同样的事情。