1

In my attempts to learn networking in Python, I have created a simple server-client program. The server creates a socket, and checks for connections, then sends a message to all connected entities. Like so,

import socket,os
ip=''
port=242
sock = socket.socket()
sock.bind((ip,port))
sock.listen(5)
clients=[]
while True:
    clients.append(sock.accept())
    os.system('cls')
    print 'connected to: '
    for client in clients:
        print client[1]
    message=raw_input('> ')
    for client in clients:
        try:
            client[0].send(message)
        except:
            clients.remove(client)

The program however appears to stop, until it receives a connection. This is somewhat of a predicament if I wish to implement the chatting element of a chat. I understand that I can place the socket.accept() outside of the loop, however I intend to have multiple clients (hence the .append()). I have provided my client code in case that has any affect.

import socket
port=int(raw_input('enter the socket adress: '))
sock=socket.socket()
sock.connect(('localhost',port))
connected=True
while connected:
    data=sock.recv(1024)
    if data=='#exit':
        connected=False
    else:
        print data

Please when writing responses, take into account that I am very much a beginner in regard to this (If that is not obvious from the format of my program... :'[ )

Notice: I am trying to avoid the select() method, because I do not yet understand it.

  • You say you are trying to avoid select(), if you can't wrap your head around that, multi-threading will truly challenge you. It's gotta be one or the other if you wish to do the directed multi-cast you seek. – msw Dec 30 '15 at 03:59

1 Answers1

2

For a server to receive and manage multiple client connections there are two common approaches (and likely other, less common ones that I will not describe).

The multi-threaded approach

In this approach your application has two threads. If you haven't done much work with threads it very roughly means that your application runs two programs at the same time and they share data.

Loop One (Accept Thread):

  • Wait for a new connection (e.g. call accept())
  • Add new connection to list

Loop Two (Input Thread):

  • Wait for user input (e.g. call raw-input())
  • Send the input to each connection in the connection list

In this case it doesn't matter that accept blocks (waits) until a new connection arrives because that is all that thread does. Keep in mind that the list of connections is shared by both loops and this is something to handle with care. Googling for python and threads will give you a wealth of information to start.

The non-blocking loop approach

In this approach, there is a single thread that loops through and checks various things in each iteration of the loop. For example, the loop would look like:

  • Do I have any new connections waiting?
  • If so, handle them, if not then continue on (don't wait for a connection)
  • Do I have any user input?
  • If so, handle it, if not then continue on (don't wait for user input)

The select() mechanism is pretty similar to what I just described but it does have some waiting. The loop is more similar to:

  • Wait until something interesting happens
  • Was that something interesting a new connection? If so, accept it.
  • Was that something interesting new user input? If so, send it.

Tradeoffs

The two approaches can be summarized as "two simple loops running at the same time" or "one complicated loop but nothing else running at the same time".

The multi-threaded approach keeps the code for each thread separate but has to deal with concerns like what happens if the two loops try and access the list of connections at the same time. The single-threaded approach doesn't have to worry about that problem but is a bit more complicated as a result.

Both approaches present interesting learning opportunities.

Pace
  • 41,875
  • 13
  • 113
  • 156