How to receive multiple socket requests on one server?

Asked

Viewed 1,969 times

6

Hello! I’m doing a server/ client schema program in Python in which I wanted to have only one server and several clients.

Imagine having 3 clients each make a request to the server via socket connection, how is it that:

  • 1: The server could accept more than one socket connection at the same time?

  • 2: The server would perform the tasks (had thought of a database to store the requests and serve as cache)

Thank you!

  • 4

    Welcome to Stackoverflow in English. A good practice to start a healthy discussion is to read the Guide to How to Ask. Start by following these recommendations, especially knowing what types of questions to ask, how to create a minimal example that is complete and verifiable, and even what to do when someone answers you.

  • When you give a Listen on an IP/Port, each new connection creates a new socket. Just go storing these sockets in a list whenever you have a new connection (without blocking) and then loop around the list and collecting the data of each one. Finally, it is good to release the CPU before closing the main loop. By doing non-blocking, you will be managing multiple connections at the same time. The secret is only to take an action when in any of the data captures contain a complete command to be answered. For a more objective answer, it is better to divide doubt into separate questions.

  • @Bacco Thanks for the explanation, there is some site where I could see an example of code to better understand?

  • I don’t know if this helps: https://pymotw.com/2/socket/tcp.html (I just looked over it, it’s something a little simpler than what I said, but maybe it serves as a basis). I don’t normally use Python on a day-to-day basis (but socket is similar in most languages).

1 answer

6


The answer to your first point is "yes", the server can accept and process more than one connection we have is to prepare it for that.

In this example the server can handle a single connection, but by grabbing it we can implement support for multiple connections, we will have to implement threads, where each connection on the server is a thread/processo "independent".

Below is a simple example of a chat server, commented where I think it should be explained:

Server:

import socket, threading

def run(conn):
    while True:
        data = conn.recv(1024) # receber informacao
        if not data: # se o cliente tiver desligado
            conns.remove(conn)
            break
        for c in conns: # enviar mensagem para todos os outros clientes
            if c is not conn: # excepto para o que a enviou 
                c.send('{}: {}'.format(conn.getpeername(), data.decode()).encode('utf-8'))

conns = set() # armazenar conxoes aqui
host, port = ('', 9999)
with socket.socket() as sock: # ligacao TCP
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # reutilizar endereco logo a seguir a fechar o servidor
    sock.bind((host, port))
    sock.listen(5) # servidor ativo
    print('Server started at {}:{}\n'.format(host, port))
    while True:
        conn, addr = sock.accept() # esperar que alguem se conect
        conn.send('WELCOME {}'.format(addr).encode())
        conns.add(conn) # adicionar conexao ao nosso set de coneccoes
        threading.Thread(target=run, args=(conn,)).start() # esta coneccao vai ser independente das outra a partir de agora, vamos correr a thread na funcao run

Client:

import socket, threading, sys, select

with socket.socket() as s:
    s.connect(('', 9999))
    while True:
        io_list = [sys.stdin, s]
        ready_to_read,ready_to_write,in_error = select.select(io_list , [], [])
        for io in ready_to_read:
            if io is s: # se tivermos recebido mensagem
                resp = s.recv(1024)
                if not resp:
                    print('server shutdown')
                    sys.exit()
                print('{}'.format(resp.decode()))
            else:
                msg = sys.stdin.readline() # vamos enviar mensagem
                s.send(msg.encode())
                sys.stdout.flush()

As for your point 2 also gives, although I don’t quite understand what you want to store in the database.

If you want to save the connections you can for example (in this example I will store in a file), add this below the last line (threading.Thread(...) of the server example I put on top:

...
with open('conns.txt', 'a') as f:
    f.write('{}\n'.format(':'.join(addr)))
  • It helped a lot! Thanks for the explanation and the provided code examples!

  • From @Hiperbolt, thank goodness

  • Just one additional question, the function Sock.Accept() returns two arguments, in this case Conn and addr. Conn corresponds to what exactly? (I’m just checking that I’m getting it all)

  • It does not return two, it returns a tuple, ex: (connection, ('213.32.12.2', 4324)), we do the unpacking, in which connection is the connection itself, it is with it that your server will work, to send messages, close etc... for example instead of conn, addr = sock.accept() , you could just dados_conn = sock.accept() in which dados_conn[0] would be your connection and dados_conn[1] is the address of the

  • Got it, thanks again

  • Dispõe @Hiperbolt

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.