为什么此套接字连接只允许1个发送和接收? [英] Why does this socket connection only allow 1 send and receive?

查看:287
本文介绍了为什么此套接字连接只允许1个发送和接收?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景

我有一个简单的套接字服务器设置,试图允许同时连接并回显数据。客户端启动几个线程,每个线程都与服务器建立自己的连接。这对于s​​ocket.send()调用工作正常,但是所有后续调用都会导致对等方重置连接或断开的管道。请注意,我还没有找到切换重置和断开管道的更改。我已经在这里找到了解决方案,但恐怕我可能不知道要搜索什么。

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?

服务器

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)


推荐答案

句柄返回时,套接字为关闭。仅当 self.data ==’时,才使用while循环并从 handle 返回。客户端关闭连接时, recv 返回零字节。另外,在测试返回值之后,否则不要 strip()结果,否则您可能会得到错误的关闭。最后,使用 ThreadingTCPServer 或服务器一次只能处理一个连接。

When you return from handle the socket is closed. Use a while loop and return from handle only when self.data == ''. recv returns zero bytes when the client closes the connection. Also don't strip() the result until after testing the return value or you could get a false close. Finally, use ThreadingTCPServer or the server can only handle one connection at a time.

示例:

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 对于简单协议即可。

Also note the send() is not guaranteed to send all bytes of message, so use sendall() 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.

这篇关于为什么此套接字连接只允许1个发送和接收?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆