Home > Software engineering >  how do i switch between connected clients with asyncio sockets
how do i switch between connected clients with asyncio sockets

Time:12-12

I am trying to make a socket server that's able to have multiple clients connected using the asyncio sockets and is able to easily switch between which client it communicates while still having all the clients connected. I thought there would be some type of FD of the clients like there is in sockets, but I looked through the docs and did not find anything, or I missed it.

Here is my server code:

import socket
import asyncio


host = "localhost"

port = 9998

list_of_auths = ['desktop-llpeu0p\\tomiss', 'desktop-llpeu0p\\tomisss',
                 'desktop-llpeu0p\\tomissss', 'desktop-llpeu0p\\tomisssss']

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('socket initiated.')
confirmed = 'CONFIRMED'
deny = 'denied'
#(so i dont forget) to get recv in async do: var = (await reader.read(4096)).decode('utf-8') if -1 then it will read all
#(so i dont forget) to write sendall do: writer.write(var.encode('utf-8')) should be used with await writer.drain()

async def handle_client(reader, writer):
    idrecv = (await reader.read(255)).decode('utf-8')
    if idrecv in list_of_auths:
        writer.write(confirmed.encode('utf-8'))
    else:
        writer.write(deny.encode('utf-8'))
        writer.close()
    request = None
    while request != 'quit':
        print("second checkpoint")

    writer.close()

async def run_server():
    print("first checkpoint")
    server = await asyncio.start_server(handle_client, host, port)
    async with server:
        await server.serve_forever()
asyncio.run(run_server())

This code allows multiple clients to connect at once; However, it only lets me communicate with the last one that connected.

CodePudding user response:

I would suggest to implement it like so:

class SocketHandler(asyncio.Protocol):
    def __init__(self):
        asyncio.Protocol.__init__(self)
        self.transport = None
        self.peername = None
        # your other code

    def connection_made(self, transport):
        """ incoming connection """
        global ALL_CONNECTIONS
        self.transport = transport
        self.peername = transport.get_extra_info('peername')
        ALL_CONNECTIONS.append(self)
        # your other code

    def connection_lost(self, exception):
        self.close()
        # your other code

    def data_received(self, data):
        # your code handling incoming data
    

    def close(self):
        try:
            self.transport.close()
        except AttributeError:
            pass


# global list to store all connections
ALL_CONNECTIONS = []

def send_to_all(message):
    """ sending a message to all connected clients """
    global ALL_CONNECTIONS
    for sh in ALL_CONNECTIONS:
        # here you can also check sh.peername to know which client it is
        if sh.transport is not None:
            sh.transport.write(message)


port = 5060
loop = asyncio.get_event_loop()
coro = loop.create_server(SocketHandler, '', port)
server = loop.run_until_complete(coro)
loop.run_forever()

This way, each connection to the server is represented by an instance of SocketHandler. Whenever you process some data inside this instance, you know which client connection it is.

  • Related