3

I'm building a python server that basically has a bunch of ports listening for connections. when a connection is made, the port spits out a message, closes the connection and , resets (ie waits for the next connection).

desired function:

create TCP socket for each port in portlist (this is dynamically populated via arguments)

listen for connection

when a connection made, send message, and disconnect

continue to listen

I have a feeling that my answer may ly in multi threading, but I'm not sure...My code so far:

  for port in portlist:
    ds = ("0.0.0.0", port)

    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server.bind(ds)
    server.listen(1)
    while 1:
            connection, address = server.accept()
            message="message\n"
            connection.send(message)
            connection.close()
Lexicon
  • 2,467
  • 7
  • 33
  • 41
  • Currently, your code listens on the first socket, then keeps looping to accept clients there. You should move the `while` loop outside the `for` loop. The tricky thing is not listening on many ports, but accepting and servicing client connections from many ports: for that you can either use the `select` module's `select` or `epoll` functions to specify the ports to monitor and loop over the ports with activity reported, or threads. – Tony Delroy Mar 18 '14 at 00:32
  • Related [question here](http://stackoverflow.com/questions/10810249/python-socket-multiple-clients) - the answer mentioning SocketServer seems a very easy way to handle this. – Tony Delroy Mar 18 '14 at 01:14

1 Answers1

9

There is single-threaded approach (on the listening side anyway - actually handling the connections may still require multiple threads).

You should open all of your sockets up-front, and put them in a list.

Then, you should select on all of them, which will return when any one of them is ready to be accepted on.

Something like this (totally untested):

servers = [] 

for port in portlist:
    ds = ("0.0.0.0", port)

    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server.bind(ds)
    server.listen(1)

    servers.append(server)

while True:
    # Wait for any of the listening servers to get a client
    # connection attempt
    readable,_,_ = select.select(servers, [], [])
    ready_server = readable[0]

    connection, address = ready_server.accept()

    # Might want to spawn thread here to handle connection,
    # if it is long-lived
Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
  • It doens't seem to like the select.select(servers, None,None) TypeError: arguments 1-3 must be sequences – Lexicon Mar 18 '14 at 00:49
  • @Lexicon Changed them to empty lists (`[]`) – Jonathon Reinhart Mar 18 '14 at 03:23
  • How could i handle message once the connection is made? (ie message part of my code) – Lexicon Mar 18 '14 at 23:05
  • @Lexicon Once you make the connection, you use the **connection** object to receive data. For the given TCP socket ( SOCK_STREAM => TCP ), you do `data = connection.recv(bufSize)`. bufSize can be any number of bytes, say 1024. – GiriB Mar 14 '16 at 14:27
  • Above code will not work. `select.select()` returns _three_ _lists_ _of_ _objects_ that are ready. The socket object that you require is contained in the first list. To get the socket object you do `ready_server = select.select(servers, [], [])[0][0]` . – GiriB Mar 14 '16 at 14:37
  • @GiriB Thanks. Like I said I never tested it. I've updated the code. – Jonathon Reinhart Mar 14 '16 at 15:17