为什么这个套接字连接只允许 1 次发送和接收?
背景
我有一个简单的套接字服务器设置,我试图允许同时连接并回显数据。客户端启动多个线程,每个线程都与服务器建立自己的连接。这对于 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)
Background
I have a simple socket server setup that I am trying to allow simultaneous connections to and echo back the data. The client side launches several threads each making its own connection to the server. This works fine for the socket.send() call, but all subsequent calls cause either a "Connection reset by peer" or a "Broken pipe". Note that I have not found the change that toggles the reset and broken pipe. I have looked here on SO for a solution, but I'm afraid I may not know what to search for.
Am I going about this in the wrong manner, or am I overlooking something in my setup?
Server
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()
Client
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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
当您从
handle
返回时,套接字将关闭。仅当self.data == ''
时才使用 while 循环并从handle
返回。当客户端关闭连接时,recv
返回零字节。另外,在测试返回值之前不要strip()
结果,否则可能会出现错误关闭。最后,使用 ThreadingTCPServer ,否则服务器一次只能处理一个连接。示例:
另请注意
send()
不能保证发送消息的所有字节,因此请使用sendall()
或检查返回值。recv()
也可能很棘手。 TCP/IP 是一种流式协议,没有消息边界的概念,因此您需要实现一个协议来检查您是否收到了完整的消息。发送 10000 字节而接收的字节数可能少于该字节数,需要多次接收才能获取整个消息。也可以在一次接收中进行两次发送和接收,甚至一次发送的全部和另一次发送的一部分。对于您的示例,只需缓冲所有接收直到消息中存在\n
就可以完成简单的协议。When you return from
handle
the socket is closed. Use a while loop and return fromhandle
only whenself.data == ''
.recv
returns zero bytes when the client closes the connection. Also don'tstrip()
the result until after testing the return value or you could get a false close. Finally, useThreadingTCPServer
or the server can only handle one connection at a time.Example:
Also note the
send()
is not guaranteed to send all bytes of message, so usesendall()
or check the return value.recv()
can also be tricky. TCP/IP is a streaming protocol and has no concept of message boundaries, so it is up to you to implement a protocol to check that you have received a complete message. It is possible to send 10000 bytes and receive less than that, requiring multiple receives to get the whole message. It is also possible to make two sends and receive both in one receive, or even all of one send and part of another. For your example simply buffering all receives until there is a\n
in the message would do for a simple protocol.