简体   繁体   中英

Handling multiple connections in python with sockets

I have a code which works perfectly for one connection. I have seen two options for multi-client handling but I don't really understand it. Here is the server socket code:

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())

If I have only one connection it works good and last thing I need to add is option for multiple-client handling. What is the shortest and easiest way to do it?

The code only calls accept once. Instead, call accept in a while loop and create a thread for each client connection so they are handled in parallel. Use the following pattern as an example:

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() 

There is also a built-in socket server that simplifies this process. Here's a tested example echo server that echoes back newline-terminated data:

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()

Your code blocks itself.

For instance: client_soc, client_address = listening_sock.accept() Accepts client, then while True: runs forever, so you can work with 1 connection only, because socket.accept() is called once. You should learn some of these to solve your problem: asyncio, threading, multiprocessing. These libraries will help your code to accept and work with clients concurrently. Sockets can use every, but often they are paired with asyncio: https://asyncio.readthedocs.io/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM