In general, network services follow the traditional client/server model. One computer acts as a server to provide a certain service and another computer represents the client side which makes use of this service. In order to communicate over the network a network socket comes into play, mostly only referred to as a socket. This kind of socket communication can even be used internally in a computer for inter-process communication (IPC).
This article explains how to write a simple client/server application that communicates via network socket using the Python programming language. For simplicity, our example server only outputs the received data to stdout. The idea behind the client/server application is a sensor in a weather station, which collects temperature data over time and sends the collected data to a server application, where the data gets processed further.
What is a Socket?
A network socket is an endpoint of a two-way communication link between two programs or processes - client and server in our case - which are running on the network. This can be on the same computer as well as on different systems which are connected via the network.
Both parties communicate with each other by writing to or reading from the network socket. The technical equivalent in reality is a telephone communication between two participants. The network socket represents the corresponding number of the telephone line, or a contract in case of cell phones.
In order to make use of the socket functionality, only the Python socket module is necessary. In the example code shown below the Python time module is imported as well in order to simulate the weather station and to simplify time calculations.
In this case both the client and the server run on the same computer. A socket has a corresponding port number, which is 23456 in our case. If desired, you may choose a different port number from the unrestricted number range between 1024 and 65535.
Having loaded the additional Python
socket module an Internet streaming socket is created using the
socket.socket class with the two parameters
socket.SOCK_STREAM. The retrieval of the hostname, the fully qualified domain name, and the IP address is done by the methods
gethostbyname(), respectively. Next, the socket is bound to the IP address and the port number 23456 with the help of the
With the help of the
listen() method the server listens for incoming connections on the specified port. In the while loop the server waits for incoming requests and accepts them using the
accept() method. The data submitted by the client is read via
recv() method as chunks of 64 bytes, and simply output to stdout. Finally, the current connection is closed if no further data is sent from the client.
# load additional Python module import socket # create TCP/IP socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # retrieve local hostname local_hostname = socket.gethostname() # get fully qualified hostname local_fqdn = socket.getfqdn() # get the according IP address ip_address = socket.gethostbyname(local_hostname) # output hostname, domain name and IP address print ("working on %s (%s) with %s" % (local_hostname, local_fqdn, ip_address)) # bind the socket to the port 23456 server_address = (ip_address, 23456) print ('starting up on %s port %s' % server_address) sock.bind(server_address) # listen for incoming connections (server mode) with one connection at a time sock.listen(1) while True: # wait for a connection print ('waiting for a connection') connection, client_address = sock.accept() try: # show who connected to us print ('connection from', client_address) # receive the data in small chunks and print it while True: data = connection.recv(64) if data: # output received data print ("Data: %s" % data) else: # no more data -- quit the loop print ("no more data.") break finally: # Clean up the connection connection.close()
Now we will have a look at the client side. The Python code is mostly similar to the server side, except for the usage of the socket - the client uses the
connect() method, instead. In a
for loop the temperature data is sent to the server using the
sendall() method. The call of the
time.sleep(2) method pauses the client for two seconds before it sends another temperature reading. After all the temperature data is sent from the list the connection is finally closed using the
# load additional Python modules import socket import time # create TCP/IP socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # retrieve local hostname local_hostname = socket.gethostname() # get fully qualified hostname local_fqdn = socket.getfqdn() # get the according IP address ip_address = socket.gethostbyname(local_hostname) # bind the socket to the port 23456, and connect server_address = (ip_address, 23456) sock.connect(server_address) print ("connecting to %s (%s) with %s" % (local_hostname, local_fqdn, ip_address)) # define example data to be sent to the server temperature_data = ["15", "22", "21", "26", "25", "19"] for entry in temperature_data: print ("data: %s" % entry) new_data = str("temperature: %s\n" % entry).encode("utf-8") sock.sendall(new_data) # wait for two seconds time.sleep(2) # close connection sock.close()
Running the Server and Client
To run both the server and the client program, open two terminal windows and issue the following commands - one per terminal window and in the following order:
$ python3 echo-server.py
$ python3 echo-client.py
The two figures below show the corresponding output of the example program:
Writing Python programs that use IPC with sockets is rather simple. The example given above can certainly be extended to handle soemthing more complex. For further information and additional methods you may have a look at some great Python socket programming resources available.