How to Code a simple Socket Server in Python

By | January 13, 2023

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
About Silver Moon

A Tech Enthusiast, Blogger, Linux Fan and a Software Developer. Writes about Computer hardware, Linux and Open Source software and coding in Python, Php and Javascript. He can be reached at [email protected].

27 Comments

How to Code a simple Socket Server in Python
  1. N.sh

    Hi i need your help ,anyone
    im dealing with project who needs to work via wifi in the next config’
    server(rpi3) vs 5 clinents(rpi zero w)
    each of the rpz is obstacle that connects to some sensors like accelmetor and ultrasoinc..and needs to retrive info to the server when he is being trigerred ,i saw that the most of impl’ are based on parallel and i want to see i there is a recomendation for using seq’ implementation ?
    i really like for some help
    thnx a lot

  2. Sarthak

    If we want to send the address in a different way, is it possible? Something like “{address}:{port}/test.mjpg”. I wish to add the ‘/test.mjpg’ along the IP address and PORT number. Any suggestions?

  3. shenbagaraman

    import socket
    import time
    import select

    sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    sock.bind((‘192.168.161.31’,20001))
    sock.listen(1)
    sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    clientsocket,addr = sock.accept()
    def square(X):
    return X*X
    def add(a,b):
    return a+b
    #task = ‘sqrt of 16 is,.math.sqrt’
    try:
    while true:
    #square = 10
    #for i in range(1,100):
    #square = square + 10
    clientsocket.sendall(square(X))
    time.sleep(10)

    the above code is correct? and i need to pass function server to client

  4. graket

    So every time I press a key, it will say
    “ok…..
    *I press h*
    OkH… OkI….
    and it doesnt even show up on the server either

  5. Manish

    If i want to keep my socket open forever weather there is client connection or not what should i Do? i want to do my listener socket keep up and listen on port 35520 and insert received values in mysql database. what should i do?

  6. Yogeesh Seralathan

    Polling is a nice little hack of handling multiple clients. But is it faster than multithreading.? I assume polling will use fewer resources than multithreading.

  7. Sagar kumar

    Thanks for tutorial. I haven’t tried it yet but I want to ask one thing. Will it work for images like On android app, I want to send image to python script at backend server and server process it and rply me back to the app.???

  8. ted

    Great tutorial, very helpful, thank you very much. One question, if the pipe was broken due to network connection, how could a client reconnect to the server? Thanks in advance.

  9. hypixus

    PERFECT tutorial for me. Only things i needed were transforming it to python 3.X and adding Polish letters support, but that was easy with this.

    def strToBytes(strToConvert):

    return str.encode(strToConvert, ‘UTF-8’)
    def bytesToStr(dataToConvert):
    return str(dataToConvert, ‘UTF-8’)

    In every place bugs of TypeError were replaced with these functions – everything was fine.

  10. sly

    This is my second post of the day which should also serve as the answer to my previous question. I found the event handling APIs, asyncore.loop and asyncore.dispatcher. Thank you though

  11. sly

    Your programs often used the “while true,,” loop to listen to client request(s). Isn’t there an event driven check like ~ Server Socket.Listen is ready before Socket.Accept. I think loop is resource intensive. Please advise !

  12. sly

    Your programs often used the “while true,,” loop to listen to client request(s). Isn’t there an event driven check like ~ Server Socket.Listen is ready before Socket.Accept. I think loop is resource intensive. Please advise !

  13. Balaji

    Hi, I need a help on python programming by creating Server connectivity. Any one kindly suggest me on the following is feasible . Server1 and Server2 will have the single socket connection and the connection should always active. Now the Server1 listen to Client 1 and get the messages and forward to Server 2 by using the available connection and get the response and send it back to the client.

  14. BabyCakes

    Hi Silver Moon, thanks for the tutorials. What’s going on with the broadcast_data function? There is no such function provided in your code.

  15. 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

    1. Steve N

      it can be written as :

      def broadcast(connected):

      while connected:
      data = connected.recv(BUFFER_SIZE)

      if data:
      data = str(connected.getpeername()) + ‘says –>’ + data
      for c in client_list:
      if c is not connected:
      c.sendall(data)
      else:
      client_index = client_list.index(connected)
      print ‘Client’ + str(connected.getpeername()) + ‘ has left the chat.’
      client_list.pop(client_index)
      print ‘The are ‘ + str(len(client_list)) + ‘ remaining clients’

      break

  16. 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?

  17. 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?

Leave a Reply

Your email address will not be published. Required fields are marked *