liveBook · Manning

Network socket

As explained in Grokking Concurrency

A network socket is an operating-system communication endpoint for exchanging data between processes over a network.

Imagine ordering pizza by calling a shop: you need the right address, and someone must be ready to answer. A network socket is an operating-system endpoint that lets a process exchange data with another process over a network. It is a two-way message-passing channel, rather than a file used for communication. section 10.3 section 5.6

A socket uses an IP address and a port. The IP address identifies the host, much like a street address identifies a house. Ports let multiple server applications on that host receive traffic intended for them. A network socket resembles a UNIX domain socket, but carries messages over a network. The network may be local, logical, or connected to the internet. section 10.3

TCP/IP sockets establish a connection before the two processes exchange information, then maintain it during their conversation. To receive clients, a server binds a socket to an IP address and port and listens. Its accept() call waits for a connection; when one arrives, it returns a separate socket for communicating with that client. section 10.3 section 10.4

A pizza-ordering service

A Python server listens at 127.0.0.1:12345, an address on the local computer. A client can connect with Netcat and send 10; the service replies, “Thank you for ordering 10 pizzas!” If the server appears to pause at accept(), it is waiting for a client, not necessarily stuck. section 10.4

# Chapter 10/pizza_server.py
from socket import socket, create_server

BUFFER_SIZE = 1024                                                 #1
ADDRESS = ("127.0.0.1", 12345)                                     #2

class Server:
    def __init__(self) -> None:
        try:
            print(f"Starting up at: {ADDRESS}")
            self.server_socket: socket = create_server(ADDRESS)    #3
        except OSError:
            self.server_socket.close()
            print("\nServer stopped.")

    def accept(self) -> socket:
        conn, client_address = self.server_socket.accept()         #4
        print(f"Connected to {client_address}")
        return conn

    def serve(self, conn: socket) -> None:
        try:
            while True:
                data = conn.recv(BUFFER_SIZE)                      #5
                if not data:                                       #5
                    break                                          #5
                try:
                    order = int(data.decode())
                    response = f"Thank you for ordering {order} pizzas!\n"
                except ValueError:
                    response = "Wrong number of pizzas, please try again\n"
                print(f"Sending message to {conn.getpeername()}")
                conn.send(response.encode())                       #6
        finally:
            print(f"Connection with {conn.getpeername()} has been closed")
            conn.close()                                           #7

    def start(self) -> None:
        print("Server listening for incoming connections")
        try:                                                       #8
            while True:                                            #8
                conn = self.accept()                               #8
                self.serve(conn)                                   #8
        finally:                                                   #8
            self.server_socket.close()                             #8
            print("\nServer stopped.")                             #8

if __name__ == "__main__":
    server = Server()
    server.start()

The Python server listing shows create_server() binding the address, accept() obtaining a client connection, and recv() reading from it. section 10.4

How Grokking Concurrency covers it

How deep it goes
Explains addresses, ports, TCP/IP connections, and server acceptance through a working service without descending into network protocol internals.
Examples
Uses a local Python pizza-ordering server and a Netcat client that sends an order and receives a reply.
What it assumes
Introduces IP addresses and ports through a mailing-address analogy while using basic Python socket code for the service.
What you can do after
Build it from scratch as a Python server that accepts a client connection, receives an order, and responds.
How it connects
Connects network sockets to interprocess communication, UNIX domain sockets, IP addresses, ports, and TCP/IP.

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.