背景
我有一个简单的套接字服务器设置,我试图允许同时连接和回显数据。客户端启动多个线程,每个线程都与服务器建立自己的连接。这适用于socket.send()调用,但所有后续调用都会导致“由对等方重置连接”或“断开管道”。请注意,我没有找到切换重置和损坏管道的更改。我在这里寻找解决方案,但恐怕我可能不知道要搜索什么。
我是以错误的方式解决这个问题,还是我在设置中忽略了某些内容?
服务器
import SocketServer
class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
print "{} wrote: {}\n".format(self.client_address[0], self.data)
self.request.send(self.data.upper())
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
客户
import socket
import sys
import threading
import time
HOST, PORT = "localhost", 9999
def create_client():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
cur_thread = threading.current_thread()
sock.connect((HOST, PORT))
for x in range(55):
msg = "{}: {}\n".format(cur_thread.name, str(x))
# Connect to server and send data
print cur_thread.name + ": sending message\n"
sock.send(msg)
# Receive data from the server and shut down
received = sock.recv(2048)
print "RX:" + received
finally:
cur_thread = threading.current_thread()
response = "{}: Closing!\n".format(cur_thread.name)
print response
sock.close()
if __name__ == "__main__":
print "testing single thread"
#create_client()
print "starting threads"
client_1 = threading.Thread(target=create_client)
client_1.daemon = True
client_1.start()
client_2 = threading.Thread(target=create_client)
client_2.daemon = True
client_2.start()
time.sleep(20)
答案 0 :(得分:8)
从handle
返回时,套接字已关闭。使用while循环,仅在handle
时从self.data == ''
返回。当客户端关闭连接时,recv
返回零字节。在测试返回值之前也不要strip()
结果,否则你可能会得到错误的结果。最后,使用ThreadingTCPServer
或服务器一次只能处理一个连接。
示例:
import SocketServer
class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
while True:
self.data = self.request.recv(1024)
if self.data == '':
break
self.data = self.data.strip()
print "{} wrote: {}\n".format(self.client_address[0], self.data)
self.request.send(self.data.upper())
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
server = SocketServer.ThreadingTCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
另请注意,send()
无法保证发送所有字节的消息,因此请使用sendall()
或检查返回值。 recv()
也可能很棘手。 TCP / IP是一种流协议,没有消息边界的概念,因此您需要实现一个协议来检查您是否收到了完整的消息。可以发送10000个字节并接收少于该字节,需要多个接收才能获得整个消息。也可以在一次接收中发送和接收两个,或者甚至发送一个发送和接收另一个发送。对于您的示例,只需缓冲所有接收,直到消息中有\n
可用于简单协议。