S - серверна програма: скажімо, це сервер HTTP, тому він використовуватиме відомий номер порту для HTTP , який дорівнює 80. Я запускаю його на хості з IP-адресою 10.0.0.4
, тому він буде слухати з'єднання на 10.0.0.4:80
(тому що саме там кожен очікує, що знайде його).
Всередині S я збираюся створити сокет і прив’язати його до цієї адреси: тепер ОС знає, що з'єднання, що надходять, 10.0.0.4:80
повинні бути спрямовані до мого S процесу через цей конкретний сокет.
вихідний показник netstat, коли сокет пов'язаний:
$ netstat --tcp -lan
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
NB. місцева адреса - це всі нулі, оскільки S байдуже, як її клієнти досягають
Після того, як S пов'язаний з цим сокетом, він прийматиме з'єднання - щоразу, коли новий клієнт підключається, accept
повертає новий сокет, характерний для цього клієнта
netstat вихід після прийому з'єднання:
$ netstat --tcp -lan
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 0 10.0.0.4:80 10.0.0.5:55715 ESTABLISHED
10.0.0.4:80
являє S кінець з'єднання і пов'язаний з поверненим сокетомaccept
10.0.0.5:55715
є кінцевим з'єднанням клієнта і асоціюється з сокетом, який клієнт передав для з'єднання . Порт клієнта не використовується ні для чого, крім маршрутизації пакетів на цьому TCP-з'єднанні до потрібного процесу: він призначається випадковим чином ядром клієнта з діапазону ефемерних портів.
Тепер S може радісно приймати більше клієнтських з'єднань ... кожен отримає свій власний сокет, кожен сокет буде асоційований з унікальним TCP-з'єднанням, і кожне з'єднання матиме унікальну віддалену адресу. S буде відслідковувати стан клієнта (якщо такий є), асоціюючи його з сокетом.
Отже, приблизно:
- IP-адреса призначена для маршрутизації між хостами в мережі
- порт призначений для маршрутизації до правильного сокета на хості
- Я ледь не сказав правильний процес , але насправді можливо мати декілька (як правило, дочірніх) процесів, які приймають все в одному сокеті ...
- однак, кожен раз, коли один із одночасних
accept
дзвінків повертається, він робить це лише в одному процесі, розетка кожного вхідного з'єднання є унікальною для одного примірника сервера
- socket - це об'єкт, який процес використовує для розмови з ОС про певне з'єднання, подібно до дескриптора файлу
- як згадується в коментарях, існує багато інших застосувань для сокетів, які взагалі не використовують порти: наприклад, socketpair створює пару розеток, з'єднаних разом, які взагалі не мають схеми адресації - єдиний спосіб використовувати цю трубу - це процес, який викликав
socketpair
, будучи дитиною цього процесу і успадковуючи його, або явно передаючи одну з розеток цього процесу