Code a simple socket server in Python

12 Flares Filament.io 12 Flares ×

Python sockets

In a previous tutorial we learnt how to do basic socket programming in python. The tutorial explained how to code a socket server and client in python using low level socket api. Check out that tutorial if you are not through on the basics of socket programming in python.

To recap, sockets are virtual endpoints of a communication channel that takes place between 2 programs or processes on the same or different machines. This is more simply called network communication and sockets are the fundamental things behind network applications. For example when you open google.com in your browser, your browser creates a socket and connects to google.com server. There is a socket on google.com server also that accepts the connection and sends your browser the webpage that you see.

Socket Servers in python

In this post we shall learn how to write a simple socket server in python. This has already been covered in the previous tutorial. In this post we shall learn few more things about programming server sockets like handling multiple connections with the select method.

So lets take a look at a simple python server first. The things to do are, create a socket, bind it to a port and then accept connections on the socket.

1. Create socket with socket.socket function
2. Bind socket to address+port with socket.bind function
3. Put the socket in listening mode with socket.listen function
3. Accept connection with socket.accept function

Now lets code it up.

'''
	Simple socket server using threads
'''

import socket
import sys

HOST = ''	# Symbolic name, meaning all available interfaces
PORT = 8888	# Arbitrary non-privileged port

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created'

#Bind socket to local host and port
try:
	s.bind((HOST, PORT))
except socket.error as msg:
	print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
	sys.exit()
	
print 'Socket bind complete'

#Start listening on socket
s.listen(10)
print 'Socket now listening'

#now keep talking with the client
while 1:
    #wait to accept a connection - blocking call
	conn, addr = s.accept()
	print 'Connected with ' + addr[0] + ':' + str(addr[1])
	
s.close()
 

The accept function is called in a loop to keep accepting connections from multiple clients.

Run it from the terminal.

$ python server.py
Socket created
Socket bind complete
Socket now listening






The output says that the socket was created, binded and then put into listening mode. At this point try to connect to this server from another terminal using the telnet command.

$ telnet localhost 8888

The telnet command should connect to the server right away and the server terminal would show this.

$ python server.py
Socket created
Socket bind complete
Socket now listening
Connected with 127.0.0.1:47758

So now our socket client (telnet) is connected to the socket server program.

Telnet (socket client) =========> Socket server

Handle socket clients with threads

The socket server shown above does not do much apart from accepting an incoming connection. Now its time to add some functionality to the socket server so that it can interact with the connected clients.

'''
	Simple socket server using threads
'''

import socket
import sys
from thread import *

HOST = ''	# Symbolic name meaning all available interfaces
PORT = 8888	# Arbitrary non-privileged port

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created'

#Bind socket to local host and port
try:
	s.bind((HOST, PORT))
except socket.error as msg:
	print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
	sys.exit()
	
print 'Socket bind complete'

#Start listening on socket
s.listen(10)
print 'Socket now listening'

#Function for handling connections. This will be used to create threads
def clientthread(conn):
	#Sending message to connected client
	conn.send('Welcome to the server. Type something and hit enter\n') #send only takes string
	
	#infinite loop so that function do not terminate and thread do not end.
	while True:
		
		#Receiving from client
		data = conn.recv(1024)
		reply = 'OK...' + data
		if not data: 
			break
	
		conn.sendall(reply)
	
	#came out of loop
	conn.close()

#now keep talking with the client
while 1:
    #wait to accept a connection - blocking call
	conn, addr = s.accept()
	print 'Connected with ' + addr[0] + ':' + str(addr[1])
	
	#start new thread takes 1st argument as a function name to be run, second is the tuple of arguments to the function.
	start_new_thread(clientthread ,(conn,))

s.close()

Run the above server program and connect once again with a telnet from another terminal. This time if you type some message, the socket server will send it back with OK prefixed.

$ telnet localhost 8888
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Welcome to the server. Type something and hit enter
hello
OK...hello
how are you
OK...how are you

The socket server can handle multiple clients simultaneously by allotting a separate thread to each.

Handle socket clients with select function

Threads appear the most natural way of handling multiple socket connections and clients. However there are other techniques of doing this. Polling is one such technique. In polling, the socket api will continuously check a bunch of sockets for some activity or event. And if an event occurs in one or multiple sockets, the function returns to the application the list of sockets on which the events occurred.

Such a kind of polling is achieved with the select function. The syntax of the select function is as follows

read_sockets,write_sockets,error_sockets = select(read_fds , write_fds, except_fds [, timeout]);

The select function takes 3 different sets/arrays of sockets. If any of the socket in the first set is readable or any socket in the second set is writable, or any socket in the third set has an error, then the function returns all those sockets. Next the application can handle the sockets returned and do the necessary tasks.

# Socket server in python using select function

import socket, select
 
if __name__ == "__main__":
     
	CONNECTION_LIST = []	# list of socket clients
	RECV_BUFFER = 4096 # Advisable to keep it as an exponent of 2
	PORT = 5000
		
	server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	# this has no effect, why ?
	server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
	server_socket.bind(("0.0.0.0", PORT))
	server_socket.listen(10)

	# Add server socket to the list of readable connections
	CONNECTION_LIST.append(server_socket)

	print "Chat server started on port " + str(PORT)

	while 1:
		# Get the list sockets which are ready to be read through select
		read_sockets,write_sockets,error_sockets = select.select(CONNECTION_LIST,[],[])

		for sock in read_sockets:
			
			#New connection
			if sock == server_socket:
				# Handle the case in which there is a new connection recieved through server_socket
				sockfd, addr = server_socket.accept()
				CONNECTION_LIST.append(sockfd)
				print "Client (%s, %s) connected" % addr
				
			#Some incoming message from a client
			else:
				# Data recieved from client, process it
				try:
					#In Windows, sometimes when a TCP program closes abruptly,
					# a "Connection reset by peer" exception will be thrown
					data = sock.recv(RECV_BUFFER)
					# echo back the client message
					if data:
						sock.send('OK ... ' + data)
				
				# client disconnected, so remove from socket list
				except:
					broadcast_data(sock, "Client (%s, %s) is offline" % addr)
					print "Client (%s, %s) is offline" % addr
					sock.close()
					CONNECTION_LIST.remove(sock)
					continue
		
	server_socket.close()

The select function is given the list of connected sockets CONNECTION_LIST. The 2nd and 3rd parameters are kept empty since we do not need to check any sockets to be writable or having errors.

Output

$ python server.py 
Chat server started on port 5000
Client (127.0.0.1, 55221) connected
Last Updated On : 3rd August 2013

Subscribe to get updates delivered to your inbox

About Silver Moon

Php developer, blogger and Linux enthusiast. He can be reached at m00n.silv3r@gmail.com. Or find him on

  • alva

    Thats you. I landed in this page and solved my problem. Great tutorial, thanks!

  • http://www.binarytides.com/ Silver Moon

    tutorial on coding chat server and client can be found here
    http://www.binarytides.com/code-chat-application-server-client-sockets-python/

  • test

    Traceback (most recent call last):

    File “./test.py”, line 48, in

    broadcast_data(sock, “Client %s: %s is offline” % addr)

    NameError: name ‘broadcast_data’ is not defined

  • Edwardo

    Hi, How I can disconnect a client? I close (with the “x” gui button) but It does not broadcast the except error… Also, I want to made a quit from the client, like hitting q for quit. I made in line 43 if data != ‘q’ then send otherwise close. Why it does not work?

  • anu nivas

    Sorry, I had wrongly named my file as select.py.
    Thank you

  • anu nivas

    At line 24 I get the error, in
    read_sockets,write_sockets,error_sockets = select(CONNECTION_LIST,[],[])
    TypeError: ‘module’ object is not callable
    Could you please assist?

12 Flares Twitter 7 Facebook 0 Google+ 4 LinkedIn 0 StumbleUpon 0 Pin It Share 1 Filament.io 12 Flares ×