Basic Socket Programming in Python
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.
Example
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.
The Server
Having loaded the additional Python socket
module an Internet streaming socket is created using the socket.socket
class with the two parameters socket.AF_INET
and socket.SOCK_STREAM
. The retrieval of the hostname, the fully qualified domain name, and the IP address is done by the methods gethostname()
, getfqdn()
, and gethostbyname()
, respectively. Next, the socket is bound to the IP address and the port number 23456 with the help of the bind()
method.
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()
The Client
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 close()
method.
# 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: %sn" % 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
and
$ python3 echo-client.py
The two figures below show the corresponding output of the example program:
_Figure 1_
_Figure 2_
Conclusion
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.