【问题标题】:Handling multiple connections in python with sockets使用套接字处理python中的多个连接
【发布时间】:2020-05-20 10:54:52
【问题描述】:

我有一个代码可以完美地用于一个连接。我已经看到了多客户端处理的两种选择,但我并不真正理解它。 这是服务器套接字代码:

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as listening_sock:
    listening_sock.bind(('', port))
    listening_sock.listen()
    client_soc, client_address = listening_sock.accept()
    client_soc.sendall('200#Welcome to my server!'.encode())
    print(f'Address {client_soc.getsockname()[0]} connected with port {client_soc.getsockname()[1]}')
    while True:
        # get message
        msg = client_soc.recv(1024).decode()
        # receive log print:
        print(f'"{msg}" sent from {client_soc.getsockname()[0]}')
        if 'Quit' in msg:
            client_soc.sendall('200#Thanks for using my server!'.encode())
            client_soc.close()
        elif '0' < msg.split('#')[0] <= '9':  # one of the valid actions
            answer = call_action(msg.split('#')[0], db, msg.split('#')[1])  # the answer for given parameter
            client_soc.sendall("200#".encode() + answer.encode())

如果我只有一个连接,它工作得很好,最后我需要添加的是多客户端处理选项。最短和最简单的方法是什么?

【问题讨论】:

    标签: python sockets networking connection


    【解决方案1】:

    代码只调用一次accept。相反,在 while 循环中调用 accept 并为每个客户端连接创建一个线程,以便并行处理它们。以以下模式为例:

    import socket
    import threading
    
    # Thread to handle each "client_soc" connection
    def handler(client_soc):
        ...
        client_soc.close()
    
    with socket.socket() as listening_sock:
        listening_sock.bind(('', 8000))
        listening_sock.listen()
        while True:
            client_soc, client_address = listening_sock.accept()
            # Send each "client_soc" connection as a parameter to a thread.
            threading.Thread(target=handler,args=(client_soc,), daemon=True).start() 
    

    还有一个内置的套接字服务器可以简化这个过程。这是一个经过测试的示例回显服务器,它回显换行符终止的数据:

    from socketserver import ThreadingTCPServer,StreamRequestHandler
    
    class echohandler(StreamRequestHandler):
        def handle(self):
            print(f'Connected: {self.client_address[0]}:{self.client_address[1]}')
            while True:
                # get message
                msg = self.rfile.readline()
                if not msg:
                    print(f'Disconnected: {self.client_address[0]}:{self.client_address[1]}')
                    break # exits handler, framework closes socket
                print(f'Received: {msg}')
                self.wfile.write(msg)
                self.wfile.flush()
    
    server = ThreadingTCPServer(('',8000),echohandler)
    server.serve_forever()
    

    【讨论】:

      【解决方案2】:

      您的代码会自行阻塞。

      例如:client_soc, client_address = listening_sock.accept() 接受客户端,然后 while True: 永远运行,因此您只能使用 1 个连接,因为 socket.accept() 被调用一次。您应该学习其中的一些来解决您的问题:异步、线程、多处理。这些库将帮助您的代码同时接受和使用客户端。套接字可以使用every,但通常与asyncio配对:https://asyncio.readthedocs.io/

      【讨论】:

      • 我应该创建一个与单个套接字一起工作的函数并多次使用它还是类似的东西?
      • 是的,你可以这样做 def handle_client(): your code for client # after accept import threading threading.Thread(target=handle_client, args=(client_soc,)).start() 那将运行新线程,但是要学习的东西太多了,您应该在 youtube 上观看有关这些主题的视频或阅读文档。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-07
      • 1970-01-01
      • 1970-01-01
      • 2021-09-10
      • 1970-01-01
      相关资源
      最近更新 更多