liveBook · Manning

Unix socket

As explained in Grokking Concurrency

A UNIX domain socket is a socket endpoint for bidirectional communication between tasks on the same operating system.

Imagine mailing a message to another program on the same computer. A UNIX domain socket is the connected endpoint that lets one thread write data while another reads it, creating two-way, FIFO communication. section 5.3

Both sides first establish a connection; afterward, the sender writes to its socket’s output stream and the receiver reads from the other socket’s input stream. This supports message-passing IPC without using network sockets. section 5.3

A local mailbox

A Python sender creates an AF_UNIX, SOCK_STREAM socket, connects to ./mailbox, and sends “Hello”, a space, and “world!”. A receiver reads those messages as they arrive. section 5.3

# Chapter 5/sockets.py
import socket
import os.path
import time
from threading import Thread, current_thread

SOCK_FILE = "./mailbox"                                                     #1
BUFFER_SIZE = 1024                                                          #2

class Sender(Thread):
    def run(self) -> None:
        self.name = "Sender"
        client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)          #3
        client.connect(SOCK_FILE)                                           #4
 
        messages = ["Hello", " ", "world!"]
        for msg in messages:                                                #5
            print(f"{current_thread().name}: Send: '{msg}'")                #5
            client.sendall(str.encode(msg))                                 #5
 
        client.close()
 
class Receiver(Thread):
    def run(self) -> None:
        self.name = "Receiver"
        server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)          #6
        server.bind(SOCK_FILE)                                              #7
        server.listen()                                                     #7
 
        print(f"{current_thread().name}: Listening to incoming messages...")
        conn, addr = server.accept()                                        #8
 
        while True:                                                         #9
            data = conn.recv(BUFFER_SIZE)                                   #9
            if not data:                                                    #9
                break                                                       #9
            message = data.decode()                                         #9
            print(f"{current_thread().name}: Received: '{message}'")        #9
 
        server.close()
 
def main() -> None:
    if os.path.exists(SOCK_FILE):
        os.remove(SOCK_FILE)
 
    receiver = Receiver()
    receiver.start()
    time.sleep(1)
    sender = Sender()
    sender.start()
 
    for thread in [receiver, sender]:
        thread.join()
 
    os.remove(SOCK_FILE)
 
if __name__ == "__main__":
    main()

Inspect the Python socket listing to see the local socket path, socket type, connection step, and repeated sends. section 5.3

How Grokking Concurrency covers it

How deep it goes
Defines socket endpoints, connection setup, FIFO exchange, and Python usage, while deferring network sockets.
Examples
Demonstrates a Python sender and receiver exchanging “Hello”, a space, and “world!” through ./mailbox.
What it assumes
Builds from the idea of sending a message between entities and introduces socket terminology through that analogy.
What you can do after
Apply it via Python’s socket API to connect local endpoints and send or receive messages.
How it connects
Connects message-passing IPC with message queues and network sockets.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Grokking Concurrency. The section links point to the parts of the book it draws on.