Simple TCP server written in Python, using socket and select
Saturday, 7. February 2009, 04:20:00
Introduction
I'm supposing you know Python somewhat well, and know how TCP/IP works. No need to be an expert, but a good understanding of how it works helps a lot. For testing, a telnet or netcat client is handy.
Before writing the code below, I read these pages:
-
Socket Programming in Python - Shows how to write a very basic UDP server with Python sockets.
-
socket - Low-level networking interface - The example in Python official documentation shows how to write a very basic TCP server.
-
select - Waiting for I/O completion
How it works
At first, the server will create a socket object to bind itself to a port on local machine, accepting connections from any IP. This socket can only be used to listen for new connections; no data is sent or received through this socket.
Then the server enters an infinite loop, using select() to wait for I/O.
When a new connection is received, the .accept() method will return a new socket object that is specific for this new connection. This new socket can be used for sending and receiving data, while the old listening socket is kept intact. This new socket is added to a list of currently open sockets.
When data is received from an open socket, the data is read using .recv() and then printed to the server terminal. If .recv() returns no data (empty string), it means that the connection was closed (unfortunately, this is not described at Python documentation, but it is described at recv(2) man page).
No exception handling is done. Actually, right now I don't even know if this code can generate exceptions. (information regarding this is very appreciated)
The code
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket, select
# List of socket objects that are currently open
open_sockets = []
# AF_INET means IPv4.
# SOCK_STREAM means a TCP connection.
# SOCK_DGRAM would mean an UDP "connection".
listening_socket = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
# The parameter is (host, port).
# The host, when empty or when 0.0.0.0, means to accept connections for
# all IP addresses of current machine. Otherwise, the socket will bind
# itself only to one IP.
# The port must greater than 1023 if you plan running this script as a
# normal user. Ports below 1024 require root privileges.
listening_socket.bind( ("", 1234) )
# The parameter defines how many new connections can wait in queue.
# Note that this is NOT the number of open connections (which has no limit).
# Read listen(2) man page for more information.
listening_socket.listen(5)
while True:
# Waits for I/O being available for reading from any socket object.
rlist, wlist, xlist = select.select( [listening_socket] + open_sockets, [], [] )
for i in rlist:
if i is listening_socket:
new_socket, addr = listening_socket.accept()
open_sockets.append(new_socket)
else:
data = i.recv(1024)
if data == "":
open_sockets.remove(i)
print "Connection closed"
else:
print repr(data)
Testing
You can write a Python client to test this server, you can just use netcat. Run the following command at your shell:
nc 127.0.0.1 1234Then type something and press Enter. To close the netcat, press Ctrl-C.
Try opening multiple simultaneous connections, and also from different hosts, just to see that things actually work, even with such simple code.
And that's all, folks! I hope this code is useful for someone else, as it shows how select() and sockets can be combined. Have fun!








Aadil # 11. February 2009, 16:36
Anonymous # 19. August 2009, 11:07
I'm new to phython and currently working with asp.net.
Can i use this code to open a socket at the client side of my web application keep the port open until he shuts the window. Can we categorize phython into a client server architecture?
If phython can be used to open a socket and we can keep communicating to it from any remote location or an asp.net application then it would be a great thing as it will improve the performance of the server by keeping the number of requests to be low cause all the current asp.net chat applications need to post back to the server every 2 seconds to check whether there is any message for him or not.
if there is some solution or you couldn't get what am i saying please mail me at koolraj@gmail.com
Denilson Figueiredo de Sá # 20. August 2009, 00:06
If you are working with web applications (that should run inside a web browser), you should (I mean... you MUST) stick to JavaScript for the client-side.
Thus, by your description it seems you want this:
http://en.wikipedia.org/wiki/Comet_(programming)
Sorry, I can't help you more than this.
Anonymous # 20. August 2009, 10:01
Thanks for letting me know.