Python unix socket example

Create Named Unix Sockets With Python

System administrators often use inter-process communication without even knowing. Undoubtedly, this knowledge is crucial when working on and diagnosing issues with software that uses Unix sockets. In addition, knowing how to create named Unix sockets can help configure and optimize network settings.

In this tutorial, we’ll look at Unix sockets and how they work. We’ll also learn how to create named Unix sockets using the socket module of the Python programming language.

2. Sockets

Sockets are a mechanism for inter-process communication (IPC) on the same machine or over a network. In essence, a socket is an endpoint for sending and receiving data, identified by an IP address and a port number. Two main types of sockets are Unix sockets and network sockets.

Unix sockets are a type of socket that allows processes running on the same Unix-based system to exchange data. These sockets use the file system as their address space. This indicates that they are linked to a file path. A process creates a socket file in the file system to communicate with another process over a Unix socket. The other process then opens that file to establish the channel.

In short, the sender and receiver create and bind to a Unix socket, and then establish a connection by calling the connect() and accept() functions. After that, they exchange data through the socket by using standard read() and write() functions.

Furthermore, Unix sockets provide fast and efficient data transfers between processes. They don’t have the overhead of network topology. In addition, only processes running on the same machine can access them, making them secure.

3. Create Unix Socket Server

Initially, we’ll set up the Unix server socket and then explain the code.

3.1. Server Code

The first socket is the server, it accepts incoming connections from clients:

import socket import os # Set the path for the Unix socket socket_path = '/tmp/my_socket' # remove the socket file if it already exists try: os.unlink(socket_path) except OSError: if os.path.exists(socket_path): raise # Create the Unix socket server server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) # Bind the socket to the path server.bind(socket_path) # Listen for incoming connections server.listen(1) # accept connections print('Server is listening for incoming connections. ') connection, client_address = server.accept() try: print('Connection from', str(connection).split(", ")[0][-4:]) # receive data from the client while True: data = connection.recv(1024) if not data: break print('Received data:', data.decode()) # Send a response back to the client response = 'Hello from the server!' connection.sendall(response.encode()) finally: # close the connection connection.close() # remove the socket file os.unlink(socket_path)

Now, let’s clarify the server code, line by line.

3.2. Understanding the Server Code

The first two lines of the code import the necessary socket and os modules:

Читайте также:  Php цикл массива foreach

The socket module provides a networking interface, while os enables access to functions of the operating system. The latter includes file I/O and process management.

Next, the code sets the path for the Unix socket. The socket_path variable holds the path for the Unix socket. The code also tries to remove the socket file if it already exists. If the file can’t be removed, the code raises an OSError:

# Set the path for the Unix socket socket_path = '/tmp/my_socket' # remove the socket file if it already exists try: os.unlink(socket_path) except OSError: if os.path.exists(socket_path): raise 

The script creates a Unix socket server using the socket() function provided by the socket module. It takes the address family as the first parameter, which is set to AF_UNIX for Unix domain sockets, and the socket type as the second parameter, which is set to SOCK_STREAM for a TCP socket. The bind() method is called to bind the socket to the path after creating the server:

# Create the Unix socket server server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) # Bind the socket to the path server.bind(socket_path) 

Then the script calls the listen() method to listen for incoming connections. The parameter we pass to listen() is the maximum number of clients. The server waits for incoming connections using accept(). The accept() method blocks until a client connects, at which point it returns a connection object and the address of the client:

# Listen for incoming connections server.listen(1) # accept connections print('Server is listening for incoming connections. ') connection, client_address = server.accept() 

Once a connection is made, the server receives data from the client using the recv() method. In this case, the argument to recv() is the maximum amount of data we can receive. If we get data, we print it to the console. Finally, the server sends a response back to the client using the sendall() method:

try: print('Connection from', client_address) # receive data from the client while True: data = connection.recv(1024) if not data: break print('Received data:', data.decode()) # Send a response back to the client response = 'Hello from the server!' connection.sendall(response.encode())

At this point, we can close the connection with the close() method. Moreover, we remove the socket file using the os.unlink() method to to clean up any leftover resources:

finally: # close the connection connection.close() # remove the socket file os.unlink(socket_path)

Now, we have our server script ready.

Читайте также:  Java system resource as file

4. Create Unix Socket Client

Now, we’ll also set up the Unix client socket and explain the code similarly.

4.1. Client Code

On the other end, we set up a client:

import socket import os # Set the path for the Unix socket socket_path = '/tmp/my_socket' # Create the Unix socket client client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) # Connect to the server client.connect(socket_path) # Send a message to the server message = 'Hello from the client!' client.sendall(message.encode()) # Receive a response from the server response = client.recv(1024) print(f'Received response: ') # Close the connection client.close() 

In short, this code creates a Unix socket client that can send and receive data to and from a Unix socket server.

4.2. Understanding the Client Code

The first two lines import the necessary modules (socket and os):

The socket_path variable sets the path of the Unix socket that the client will connect to. This should match the path used by the Unix socket server, otherwise, the client won’t be able to connect. We create the client with the socket() method. In it, we specify the AF_UNIX family of protocols and the SOCK_STREAM socket type:

# Set the path for the Unix socket socket_path = '/tmp/my_socket' # Create the Unix socket client client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) 

After creating the client, we connect to the Unix socket server with connect(). The method takes the socket_path as its argument. After connecting to the server, the client sends a message to it using the sendall() method. The client encodes the message before sending it:

# Connect to the server client.connect(socket_path) # Send a message to the server message = 'Hello from the client!' client.sendall(message.encode()) 

Next, the client waits to receive a response from the server. The code uses the recv() method to wait for incoming data and stores the response in the response variable. After that, it prints the response to the console using the decode() method, which converts the bytes received to a string:

# Receive a response from the server response = client.recv(1024) print(f'Received response: ')

Finally, the script closes the connection using the close() method:

# Close the connection client.close()

We have our client script ready.

5. Testing the Setup

Notably, we need to run both scripts on the same machine for the Unix socket to work properly. To make the connection, we first need to run the server and then the client script:

$ python server.py Server is listening for incoming connections. 

Afterward, we run the client script on another terminal:

$ python client.py Received response: Hello from the server!

Let’s check the terminal that’s running the server script:

$ python server.py Server is listening for incoming connections. Connection from fd=4 Received data: Hello from the client! 

We’ve successfully set up Unix sockets for both the server and the client.

Читайте также:  Php and cgi bin

6. Conclusion

In this article, we’ve learned about Unix sockets and how they work. We’ve also looked at how to create named Unix sockets by setting up a server and client using the socket Python module.

Источник

jmhobbs / client.py

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

# -*- coding: utf-8 -*-
import socket
import os
print ( «Connecting. » )
if os . path . exists ( «/tmp/python_unix_sockets_example» ):
client = socket . socket ( socket . AF_UNIX , socket . SOCK_DGRAM )
client . connect ( «/tmp/python_unix_sockets_example» )
print ( «Ready.» )
print ( «Ctrl-C to quit.» )
print ( «Sending ‘DONE’ shuts down the server and quits.» )
while True :
try :
x = input ( «> » )
if «» != x :
print ( «SEND:» , x )
client . send ( x . encode ( ‘utf-8’ ))
if «DONE» == x :
print ( «Shutting down.» )
break
except KeyboardInterrupt as k :
print ( «Shutting down.» )
client . close ()
break
else :
print ( «Couldn’t Connect!» )
print ( «Done» )

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

# -*- coding: utf-8 -*-
import socket
import os
if os . path . exists ( «/tmp/python_unix_sockets_example» ):
os . remove ( «/tmp/python_unix_sockets_example» )
print ( «Opening socket. » )
server = socket . socket ( socket . AF_UNIX , socket . SOCK_DGRAM )
server . bind ( «/tmp/python_unix_sockets_example» )
print ( «Listening. » )
while True :
datagram = server . recv ( 1024 )
if not datagram :
break
else :
print ( «-» * 20 )
print ( datagram . decode ( ‘utf-8’ ))
if «DONE» == datagram . decode ( ‘utf-8’ ):
break
print ( «-» * 20 )
print ( «Shutting down. » )
server . close ()
os . remove ( «/tmp/python_unix_sockets_example» )
print ( «Done» )
jmhobbs@Cordelia:~/Desktop/p3 ✪ python3 server.py Opening socket. Listening. -------------------- Hello World! -------------------- DONE -------------------- Shutting down. Done jmhobbs@Cordelia:~/Desktop/p3 ✪ 
jmhobbs@Cordelia:~/Desktop/p3 ✪ python3 client.py Connecting. Ready. Ctrl-C to quit. Sending 'DONE' shuts down the server and quits. > Hello World! SEND: Hello World! > DONE SEND: DONE Shutting down. jmhobbs@Cordelia:~/Desktop/p3 ✪ 

Источник

Оцените статью