Python: How can the same socket object serve different clients?
Question: As is mentioned in the documentation: [Python
socket.accept()](https://docs.python.org/3/library/socket.html#socket.socket.accept)

> Accept a connection. The socket must be bound to an address and listening
> for connections. The return value is a pair (conn, address) where conn is a
> new socket object usable to send and receive data on the connection, and
> address is the address bound to the socket on the other end of the
> connection.
>
> The newly created socket is non-inheritable.
>
> Changed in version 3.4: The socket is now non-inheritable.

_server code_

    
    
    >>> from socket import *
    >>> sock = socket(AF_INET, SOCK_STREAM)
    >>> sock.bind(("localhost", 20000))
    >>> sock.getsockname()
    ('127.0.0.1', 20000)
    >>> sock.listen(1)
    >>> while True: 
    ...     conn, address = sock.accept()
    ...     print("Address of client : {0}".format(address))
    ...     print("Address of socket : {0}".format(conn.getsockname()))
    ... 
    Address of client : ('127.0.0.1', 47165)
    Address of socket : ('127.0.0.1', 20000)
    Address of client : ('127.0.0.1', 47166)
    Address of socket : ('127.0.0.1', 20000)
    

_client code_

    
    
    >>> from socket import *
    >>> sclient1 = socket(AF_INET, SOCK_STREAM)
    >>> sclient2 = socket(AF_INET, SOCK_STREAM)
    >>> sclient1.connect(("localhost", 20000))
    >>> sclient2.connect(("localhost", 20000))
    

The address of the new `socket` object that is returned, is always the same as
the original `socket` which was actually accepting connections.

I always thought that the server would create a new `socket` object with a
different random port, but as can be seen above, even for multiple clients,
the address and port of new `conn` object is still the same. How is then the
server able to handle multiple clients?

**EDIT** : I know the above code is blocking. If I use multiple threads to
handle different client connections, I'll have to do send the new socket
object, and client address to my thread function. Therefore, multiple threads
are then handling multiple clients using the same server address and port.

_Threaded server_

    
    
    >>> from socket import *    
    >>> import threading
    >>> def handler(conn, address):
    ...     print("Address of client : {0}".format(address))
    ...     print("Address of socket : {0}".format(conn.getsockname()))
    ... 
    >>> sock = socket(AF_INET, SOCK_STREAM)
    >>> sock.bind(("localhost", 20000))
    >>> sock.listen(1)
    >>> while 1:
    ...     conn, address = sock.accept()
    ...     t = threading.Thread(target=handler, args=[conn, address])
    ...     t.start()
    ... 
    Address of client : ('127.0.0.1', 47169)
    Address of socket : ('127.0.0.1', 20000)
    Address of client : ('127.0.0.1', 47170)
    Address of socket : ('127.0.0.1', 20000)
    


Answer: > I always thought that the server would create a new socket object with a
> different random port

That would require telling the client which _new_ port to use for the
connection. Nicely enough, it is not necessary, see below.

> How is then the server able to handle multiple clients?

The tuple `(server_addr, server_port, client_addr, client_port)` is unique
after a client connects. When a packet comes in, the network stack searches
for open connections matching this tuple and redirects incoming packets to the
relevant socket (/file descriptor).

The _server socket_ (which you perform `accept()` on), is _unconnected_ (it is
_`listen()`ing_), but bound. This means it doesn't have a peer on the other
side (no client address), but it does have a local address (server side).

`accept()` returns a new socket. This one is _bound_ and _connected_. Bound is
the same as above: it has a local address and port. That address is the same
as for the server socket, however the client socket state is different from
the state of the server socket: It is connected. This means that there is a
known peer (with an address) on the other side that we can communicate with.
We also have that peer's address (the _peer address_) and socket. This
information is enough to uniquely identify the connection.

The client socket only accepts data that matches all four of `(server_addr,
server_port, client_addr, client_port)`.

