Send_fds() function of socket module in Python

Overview:

  • The function socket.send_fds(), sends file descriptors from one process to another using Unix Domain Sockets - the internals of which are detailed here.

  • Using the socket interface, any two machines that talk TCP/IP can communicate with each other.

  • Unix Domain Protocol uses the same socket interface used for network communication while communicating to a process running in the same machine.

  • Since the Unix domain protocol communicates between two processes in the same machine, traversing the TCP/IP suite at both ends of the communication is avoided which reduces the latency significantly.

  • In Unix, file descriptors can be be passed between two processes using Unix Domain Sockets.

  • When file descriptors are passed through Unix Domain Sockets, Unix recreates the descriptors sent to the other process through kernel. It takes care of the corner cases like closing the handle from the client process before the server receiving it.

  • The socket.sendmsg() is the basic function that takes care of sending all kind information between two sockets, be it TCP/IP or Unix Domain Protocol. The socket.recvmsg() function does the receiving work on client and server sockets.

  • The socket.send_fds() uses socket.sendmsg() to send file descriptors from one Unix domain socket to another.

Example - Client sending file descriptors through a Unix domain socket:

# Example Python program that uses domain
# sockets and the socket module function
# send_fds() to send multiple file
# descriptors to another process.
import socket
import os

# Create a UNIX Domain socket
sender = socket.socket(socket.AF_UNIX)

# Connect the socket to the server
path = "/Users/ex/sender_fd"
sender.connect(path)

# Obtain two file descriptors both in read only mode
fd1 = os.open("./news1.txt", os.O_RDONLY)
fd2 = os.open("./news2.txt", os.O_RDONLY)

# Append the descriptors to a list 
desList = []
desList.append(fd1)
desList.append(fd2)

# Send the list of file descriptors to the server
msg     = "hi" 
msgb    = bytes(msg, 'ascii')
socket.send_fds(sender, [msgb], desList, 2, None)

# Receive data from the Unix Domain Socket
while(True):
    data = sender.recv(1024)
    if(data!=b''):
        print("Server Response:")
        print(data)
    else:    
        print("Connection closed by server")
        break

sender.close()

Output:

Server Response:

b'Great...have read all the news'

Connection closed by server

Example - Server receiving file descriptors through a Unix domain socket:

# Example Python program that creates 
# a server using an Unix Domain Socket  
# and receives File Descriptors from other
# processes connecting to this server through 
# the function socket.receive_fds()  
import socket
import os

# Create a Unix Domain socket
domainServer = socket.socket(socket.AF_UNIX)

# Bind the socket to a path
path = "/Users/ex/sender_fd"
os.unlink(path)
domainServer.bind(path)

# Enter into listening mode
domainServer.listen()  
print("Unix domain socket waiting for client connections...")

# Start accepting connections
while(True):
    sock, addr = domainServer.accept()

    # Read file descriptors from a connection
    while(True):
        tup = socket.recv_fds(sock, 1024, 2)
        fdList = tup[1]

 

        # Read from each file descriptor
        # and print the contents
        for fd in fdList:
            print(os.read(fd, 8))

        sock.send("Great...have read all the news".encode())
        sock.close()
        break

Output:

Unix domain socket waiting for client connections...

b'news1'

b'news2'

 


Copyright 2024 © pythontic.com