Python Sockets, Advanced Chat Box
<p>I want to create a server that <strong>handles</strong> a lot of clients at the same time (<strong>handles</strong>: receiving data from clients and sending data to all clients at the same time!!!)</p>

<p>Actually i'm trying to create a chat box. The program will work like this:</p>

<p>1) There's going to be a server which handles the clients. </p>

<p>2) More than one clients can join the server.</p>

<p>3) Clients send messages (Strings) to the server.</p>

<p>4) The server receive's the message from a client and then it send's it to all 
the clients except the one he got it from.</p>

<p>And this is how the clients will communicate each other. No private messages available. When someone hits the enter all the clients will see the message on their screen.</p>

<p>The client module is easy to make, because the client communicates only with one socket (The Server).</p>

<p>The server module from the other hand is really complicated, i don't know how to do it (I also know about threads).</p>

<p>This is my atempt:</p>

<pre><code>import socket, threading


class Server:

def __init__(self, ip = "", port = 5050):

    '''Server Constructor. If __init__ return None, then you can use
       self.error to print the specified error message.'''

    #Error message.
    self.error  = ""

    #Creating a socket object.
    self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    #Trying to bind it.
    try:
        self.server.bind( (ip, port) )
        pass


    #Failed, because socket has been shuted down.
    except OSError :
        self.error = "The server socket has been shuted down."
        return None

    #Failed, because socket has been forcibly reseted.
    except ConnectionResetError:
         self.error = "The server socket has been forcibly reseted."
         return None


    #Start Listening.
    self.server.listen()


    #_____Other Variables_____#

    #A flag to know when to shut down thread loops.
    self.running = True

    #Store clients here.
    self.clients = []

    #_____Other Variables_____#


    #Start accepting clients.
    thread = threading.thread(target = self.acceptClients)
    thread.start()

    #Start handling the client.
    self.clientHandler()





#Accept Clients.
def acceptClients(self):

    while self.running:
        self.clients.append( self.server.accept() )

    #Close the server.
    self.server.close()




#Handle clients.
def clientHandler(self):

    while self.running:

        for client in self.clients:

            sock = client[0]
            addr = client[1]

            #Receive at most 1 mb of data.
            #The problem is that recv will block the loop!!!
            data = sock.recv(1024 ** 2)
</code></pre>

<p>As you can see, i accept clients using a thread so the server.accept() won't block the program. And then i store the clients into a list.</p>

<p>But the problem is on the <strong>clientHandler</strong>. How am i going to recv from all
clients at the same time? The first recv will block the loop!!!</p>

<p>I also tried to start new threads (clientHandlers) for every new client
but the problem was the synchronization.</p>

<p>And what about the send? The server must send data to all the clients, so the clientHandler is not yet finished. But if i mix the methods <strong>recv</strong> and <strong>send</strong> then the problem become's more complicated. </p>

<p>So what is the proper and best way to do this?
I'd like to give me an example too.</p>

<p>Multithreading is great when the different clients are independant of each other: you write your code as if only one client existed and you start a thread for each client.</p>

<p>But here, what comes from one client must be send to the others. One thread per client will certainly lead to a synchronization nightmare. So let's call <code>select</code> to the rescue! <code>select.select</code> allows to poll a list of sockets and returns as soon as one is ready. Here you can just build a list containing the listening socket and all the accepted ones (that part is initially empty...):</p>

<ul>
<li>when the listening socket is ready for read, accept a new socket and add it to the list</li>
<li>when another socket is ready for read, read some data from it. If you read 0 bytes, its peer has been shut down or closed: close it and remove it from the list</li>
<li>if you have read something from one accepted socket, loop on the list, skipping the listening socket and the one from which you have read and send data to any other one</li>
</ul>

<p>Code could be (more or less):</p>

<pre><code>    main = socket.socket()  # create the listening socket
    main.bind((addr, port))
    main.listen(5)
    socks = [main]   # initialize the list and optionaly count the accepted sockets

    count = 0
    while True:
        r, w, x = select.select(socks, [], socks)
        if main in r:     # a new client
            s, addr = main.accept()
            if count == mx:  # reject (optionaly) if max number of clients reached
                s.close()
            else:
                socks.append(s) # appends the new socket to the list
        elif len(r) &gt; 0:
            data = r[0].recv(1024)  # an accepted socket is ready: read
            if len(data) == 0:      # nothing to read: close it
                r[0].close()
                socks.remove(r[0])
            else:
                for s in socks[1:]:  # send the data to any other socket
                    if s != r[0]:
                        s.send(data)
        elif main in x:  # close if exceptional condition met (optional)
            break
        elif len(x) &gt; 0:
            x[0].close()
            socks.remove(x[0])
    # if the loop ends, close everything
    for s in socks[1:]:
        s.close()
    main.close()
</code></pre>

<p>You will certainly need to implement a mechanism to ask the server to stop, and to test all that but it should be a starting place</p>

python multithreading sockets