0

Given the server code:

import socket

HOST = 'localhost'
PORT = 65200

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    while True:
        c, addr = s.accept()
        with c:
            client_addr = c.getsockname()[0]
            client_port = c.getsockname()[1]
            print('Connected to client address: {} port: {}'.format(client_addr, client_port))

And given the client code:

import socket

connections = {}

SRC_HOST = 'localhost'
SRC_PORT = 65300

# Create 5 connections
for i in range(5):
    connections[i] = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    connections[i].bind((HOST, SRC_PORT + i))

DEST_HOST = 'localhost'
DEST_PORT = 65200

# For each connection, send one message
for s in connections.keys():
    connections[s].connect((DEST_HOST, DEST_PORT))
    connections[s].sendall(b'Hello world!')

# Close active connections
for s in connections.keys():
    connections[s].close()

In the output of the server code, why does the port of socket object c remain 65200 for each connected client?

Connected to client address: 127.0.0.1 port: 65200
Connected to client address: 127.0.0.1 port: 65200
Connected to client address: 127.0.0.1 port: 65200
Connected to client address: 127.0.0.1 port: 65200
Connected to client address: 127.0.0.1 port: 65200

Per Python docs on sockets, socket.accept() shall return (c, addr) where c is a new socket object for each new connection retrieved from the listen queue.

Am I wrong in assuming a new socket object requires a unique port? If so, how would the server code differentiate in between the 5 different connected clients if the port is 65200 for all of them?

In other words, what if I wanted to only send client (localhost, 65302) something in response and not the other connected clients?

doofus
  • 124
  • 1
  • 5
  • 2
    You are indeed wrong in your assumption. See: https://stackoverflow.com/questions/11129212/tcp-can-two-different-sockets-share-a-port/11129607#11129607 – Jeremy Friesner Dec 26 '21 at 00:38
  • @JeremyFriesner yes, good answer, so I understand that (local_address, local_port, remote_address, remote_port) is the unique identifier for a connection. SO THEREFORE, can I communicate with each unique client only via the unique connection object returned by socket.accept(), or is there another way? – doofus Dec 26 '21 at 00:44
  • the socket returned by `accept()` is the only way to use that particular TCP connection. You could always create a second TCP connection, or send/receive UDP packets, or carrier pigeons, or anything else in addition, of course. – Jeremy Friesner Dec 26 '21 at 00:48
  • @JeremyFriesner Why create a second TCP or UDP connection? – doofus Dec 26 '21 at 01:42
  • you asked if there was another way; so I listed some other ways – Jeremy Friesner Dec 26 '21 at 03:45

1 Answers1

0

https://docs.python.org/3/library/socket.html

socket.getsockname() Return the socket’s own address.

So you are reading the server address. Every transport layer connection is a 5 tuple (prot, source_addr, sorce_port, destination_addr, destination_port) where the overall combination has to be unique. if one of the five differs it is another identifieable connection and therefore legal to exist in paralell. You achieve this by incrementing SRC_PORT by i in your code.