How to Do Socket Programming in Python

This article provides a brief tutorial on how to code sockets in Python. Socket programming can be a bit confusing at first, but, fortunately for us, Python makes it really easy.

I assume that you already have a basic understanding of Python. You can download the code for this tutorial from this GitHub repository.

Before plunging into implementation, let’s review a bit of theory first to acquire basic notions about sockets.

What are sockets?

Sockets are at the basis of network communication between computers. Every time you request a webpage , a socket is opened and used for transferring information from the server to the client. For example, when you type http://www.facebook.com, your web browser opens a socket, which connects to the Facebook server and sends it an HTTP request to fetch the content of the Facebook homepage.Once the socket receives the data, the browser shows you the content. To be a bit more formal, we can define a socket as a software endpoint that establishes bidirectional communication between a server and a client.

When talking about sockets, we usually refer to sockets in an Internet Protocol (IP) network. These sockets typically use TCP (Transmission Control Protocol) as the protocol for handling 1-to-1 connections, between two nodes in a network. There are also UDP (User Datagram Protocol) sockets, which can be easily implemented in Python. However,  for this tutorial we’ll focus on TCP sockets only.

Sockets are associated with a socket address, which consists of an IP address and a port number. By using the same port number, a server and a client sockets can easily communicate. The process of association of a socket with a socket address is called binding.

Client and server sockets

There are both client and server sockets. Client sockets are used to send requests to the server and to receive the server’s response. As the name suggests, server sockets typically serve resources to a network of client sockets.

In order to serve more than one client at a time, the server socket should be multi-threaded. With this architecture, the server creates a thread for each connection it establishes from a client. Simply speaking, a thread is a sequence of instructions that can run independently of any other threads.

Now that we know a bit of the theory behind sockets, let’s begin implementing them in Python!

Coding a client socket

:To create a functioning client socket which is able to send/receive data to/from a server, we’ll follow the steps below:

  1. Create a socket
  2. Connect to a server
  3. Send data
  4. Receive data

Create a socket

We start out creating a socket. Luckily, doing this in Python is as simple as invoking the socket function from the socket module.

# a simple client socket
import socket

# define socket address
TCP_IP = '127.0.0.1'  # ip of the server we want to connect to
TCP_PORT = 5000  # port used for communicating with the server

# create socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "Socket created successfully."

The two arguments we pass to the socket function identify the family type and the socket type:

  • socket.AF_INET specifies that the socket we’ve created will communicate using addresses of the type IPv4.
  • socket.SOCK_STREAM tells the socket function that we want to use the TCP protocol to handle connections.

Now you’ve created a socket. The next step is to connect to a server to establish a communication. For this purpose, we’ll use the server  socket that we’ll develop next, that will run on localhost (127.0.0.1).

Connect to a server

Connecting to a server is very simple. You just need to pass the socket address (server ip and port) to the connect function.

# a simple client socket
import socket

# define socket address
TCP_IP = '127.0.0.1'  # ip of the server we want to connect to
TCP_PORT = 5000  # port used for communicating with the server

# create socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "Socket created successfully."

# connect to server
s.connect((TCP_IP, TCP_PORT))
print "Established connection with the server." 

Send data

Now, it’s time to send some data over to the server. To do this, we use the send function. This function takes as argument the message we’d like to send.

# a simple client socket
import socket

# define socket address
TCP_IP = '127.0.0.1'  # ip of the server we want to connect to
TCP_PORT = 5000  # port used for communicating with the server

# create socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "Socket created successfully."

# connect to server
s.connect((TCP_IP, TCP_PORT))
print "Established connection with the server." 

message = "I've been sent from the client!"
# send message to the server
s.send(message) 
print "Message sent to server."

Receive data

Up until now, we’ve created a socket, opened a connection with the server and sent a request. Assuming the remote server has sent a reply, we now need to receive and read the data.

To do this, we simply use the recv function which returns a string representing the data received. We have to pass a value to recv which specifies the maximum amount of data that can be received at once, i.e., the buffer size.

# a simple client socket
import socket

# define socket address
TCP_IP = '127.0.0.1'  # ip of the server we want to connect to
TCP_PORT = 5000  # port used for communicating with the server
BUFFER_SIZE = 1024  # buffer size used when receiving data

# create socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "Socket created successfully."

# connect to server
s.connect((TCP_IP, TCP_PORT))
print "Established connection with the server." 

message = "I've been sent from the client!"
# send message to the server
s.send(message) 
print "Message sent to server."

# receive data from server
data = s.recv(BUFFER_SIZE)
print "Here's the message received from the server:"
print data

Client socket: Recap

The role of a client socket is to fetch information from a server. To implement a client socket in Python we’ve followed four steps:

  1. Instantiate a socket
  2. Establish connection between client socket and server
  3. Send a data request
  4. Receive the reply from the server

Now that we have a functioning client socket, the next step is to create a server that can send data back to our client program when asked to.

Coding a server socket

The role of a server socket is to wait and listen for incoming connections and to distribute resources to clients. To code a server socket we’ll follow these steps:

  1. Create a socket
  2. Bind socket to an address
  3. Listen for connections
  4. Handle connections
  5. Read client request and reply

We won’t go through point no. 1, as we already covered how to open a socket in the case of a client.

Bind socket to an address

After you create a socket, you should bind it to an address and to a port using the bind function.

# a simple server socket
import socket

# define socket address
TCP_IP = '0.0.0.0'  # consider all possible incoming IPs 
TCP_PORT = 5000  # port used for communicating with the client
BUFFER_SIZE = 1024  # buffer size used when receiving data

# create socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "Socket created successfully."

# bind socket
s.bind((TCP_IP, TCP_PORT))

By binding a socket to a given port, we ensure that all the incoming data transferred through that specific port reaches the server.

A common error when doing socket programming is to use two different ports for the client and the server. If this happens, the two programs won’t establish a connection. As a tip, in case your client-server application doesn’t seem to communicate, check if the ports they use are the same. This can save you some debugging time.

Listen for connections

After binding the socket to an address, it’s time for the server to start listening for incoming connections. To put the socket in listening mode, we use the listen function. This function takes an int argument called backlog, which specifies the maximum number of  connections that are kept waiting if the application is already busy.

# a simple server socket
import socket

# define socket address
TCP_IP = '0.0.0.0'  # consider all possible incoming IPs 
TCP_PORT = 5000  # port used for communicating with the client
BUFFER_SIZE = 1024  # buffer size used when receiving data

# create socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "Socket created successfully."

# bind socket
s.bind((TCP_IP, TCP_PORT))

# start listening
s.listen(20)
print "Waiting for a connection..."

Handle connections

Once launched, the live server should be able to establish a connection with a client programme while running at any time. To achieve this, we put the server in an infinite loop. At each iteration, we look for incoming connections. If there is one, we accept the connection with the accept function.

# a simple server socket
import socket

# define socket address
TCP_IP = '0.0.0.0'  # consider all possible incoming IPs 
TCP_PORT = 5000  # port used for communicating with the client
BUFFER_SIZE = 1024  # buffer size used when receiving data

# create socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "Socket created successfully."

# bind socket
s.bind((TCP_IP, TCP_PORT))

# start listening
s.listen(20)
print "Waiting for a connection..."

# wait for connection
while True:
    # accept connection 
    conn, addr = s.accept()
    print "Connected with " + addr[0] + " " +str(addr[1])

Read client request and reply

Having a server that is able to connect with a client program but not doing anything else is pretty useless. Indeed, the next step is to read the incoming request and to send back to the client a reply.

# a simple server socket
import socket

# define socket address
TCP_IP = '0.0.0.0'  # consider all possible incoming IPs 
TCP_PORT = 5000  # port used for communicating with the client
BUFFER_SIZE = 1024  # buffer size used when receiving data

# create socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "Socket created successfully."

# bind socket
s.bind((TCP_IP, TCP_PORT))

# start listening
s.listen(20)
print "Waiting for a connection..."

# wait for connection
while True:
    # accept connection 
    conn, addr = s.accept()
    print "Connected with " + addr[0] + " " + str(addr[1])
 
    # get message from client
    message = conn.recv(BUFFER_SIZE)
    # check that there is a message   
    if not message:
        break
 
    # put some logic here, if needed
 
    server_message = "I'm the message from the server..."
    # send message to client
    conn.send(server_message)

s.close()

When the program exits from the loop, the socket is shut down with the close function.

Congrats! We’ve just finished creating our first server socket. It wasn’t that difficult after all.

Server socket: Recap

A server socket is used to provide client programs with the data they request. The implementation of a server socket passes through the following steps:

  1. Open a socket
  2. Bind socket to an ip and a port
  3. Put socket to listen
  4. Accept incoming connections
  5. Read client messages and send data

Putting all together

Now that we have developed both a client and a server sockets, it’s time to let them communicate. I assume you have a client.py and a server.py files for the client and server sockets respectively.

Run the server socket from the terminal first.
$ python server.py

Once launched, the server program will wait, listening from incoming connections.

Then, open another terminal and launch client.py.

$ python client.py

The client programme will connect to the server, send a message and receive data from the server. If you’ve followed this guide step by step, the terminal from where you’ve opened the client programme should look similar to the image below.

Conclusion

In this article, I’ve presented the basics of socket programming in Python. If you’ve followed along, by now you should be able to easily create client and server sockets.

As the next step, try to experiment with what you’ve learned so far by adding more features to the simple programs presented here. Remember to check out the Python documentation on sockets, if you require more in-depth information.

15 thoughts on “How to Do Socket Programming in Python

  1. Excellent website. Plenty of useful information here.
    I am sending it to a few pals ans additionally sharing in delicious.
    And of course, thanks in your sweat!

    Like

  2. My coder is trying to persuade me to move to .net
    from PHP. I have always disliked the idea because of the expenses.
    But he’s tryiong none the less. I’ve been using Movable-type on several websites for about a year and
    am anxious about switching to another platform. I have heard good things about blogengine.net.
    Is there a way I can transfer all my wordpress posts into it?
    Any kind of help would be really appreciated!

    Like

  3. We are a bunch of volunteers and starting a new scheme in our
    community. Your site offered us with valuable info to work on. You have done a formidable process and our entire
    group will likely be grateful to you.

    Like

  4. Thanks for a marvelous posting! I quite enjoyed reading
    it, you can be a great author.I will make sure to bookmark your blog and may come back from now on.
    I want to encourage you to definitely continue your great writing, have a nice afternoon!

    Like

Leave a comment