Як працює API socket, що приймає функцію ()?


126

API сокета є фактичним стандартом для зв'язку TCP / IP та UDP / IP (тобто мережевий код, як ми це знаємо). Однак одна з його основних функцій accept()- трохи магічна.

Для запозичення напівформального визначення:

accept () використовується на стороні сервера. Він приймає отриману вхідну спробу створити нове TCP-з'єднання з віддаленого клієнта та створює новий сокет, пов'язаний з парою адрес сокета цього з'єднання.

Іншими словами, acceptповертає новий сокет, через який сервер може спілкуватися з нещодавно підключеним клієнтом. Стара розетка (на яку acceptназивались) залишається відкритою, на тому ж порту, слухаючи нові з'єднання.

Як acceptпрацює? Як це реалізується? На цю тему багато плутанини. Багато людей стверджують, що прийняття відкриває новий порт, і ви спілкуєтесь із клієнтом через нього. Але це очевидно не відповідає дійсності, оскільки новий порт не відкритий. Ви насправді можете спілкуватися через один і той же порт з різними клієнтами, але як? Коли декілька потоків дзвонять recvна один і той же порт, як дані знають, куди звернутися?

Я думаю, що це щось уздовж рядків адреси клієнта, пов’язаних з дескриптором сокета, і кожного разу, коли дані надходять через recvнього, він спрямовується на правильний сокет, але я не впевнений.

Було б чудово отримати ґрунтовне пояснення взаємодії цього механізму.


2
тому для кожного запиту клієнта відкривається фірмове НОВЕ з'єднання на розетці на кінці сервера. Сервер повинен бути відкритим на 80 завжди, щоб слухати вхідні дзвінки. Якщо він отримує дзвінок, він негайно створює НОВИЙ сокет з чотирма кортежами, як зазначено нижче, що дозволить встановити TCP-з'єднання між клієнтом і сервером. Чи правильно я розумію?
штурм мозку

1
Це дуже важливе питання , і я недавно був випробуваний на це в інтерв'ю: stackoverflow.com/questions/24871827 / ... Якщо у вас є якісь - які коментарі з цього приводу , будь ласка , напишіть
мозковий штурм

@brainstorm Тільки якщо ви повністю ігноруєте існування HTTP-режиму.
Маркіз Лорн

Відповіді:


140

Ваша плутанина полягає в тому, що ви думаєте, що сокет ідентифікується сервером IP: Порт сервера. Насправді розетки однозначно ідентифікуються квартетом інформації:

Client IP : Client Port і Server IP : Server Port

Тож як IP-сервер і Порт сервера є постійними у всіх прийнятих з'єднаннях, інформація про клієнт - це те, що дозволяє йому відстежувати, куди йде все.

Приклад для уточнення речей:

Скажімо, у нас є сервер 192.168.1.1:80і два клієнта, 10.0.0.1і 10.0.0.2.

10.0.0.1відкриває з'єднання на локальному порту 1234та підключається до сервера. Тепер сервер має один сокет, ідентифікований таким чином:

10.0.0.1:1234 - 192.168.1.1:80  

Тепер 10.0.0.2відкривається з'єднання на локальному порту 5678та підключається до сервера. Тепер сервер має два сокети, визначені таким чином:

10.0.0.1:1234 - 192.168.1.1:80  
10.0.0.2:5678 - 192.168.1.1:80

3
Я не знаю деталей реалізації (які, можливо, варіюються від платформи до платформи), я просто знаю, що концептуально сокети ідентифікуються квартетом інформації, яку я описав.
17 з 26

3
Чи є у вас якісь посилання на це?
qeek

3
Випадкове запитання: Що відбувається, якщо використовується NAT, і два клієнти в одній мережі намагаються використовувати той самий локальний порт під час підключення до сервера? Наприклад, якщо 10.0.0.1 і 10.0.0.2 обидва підключені до маршрутизатора із зовнішнім IP-адресом 192.168.0.1, то сервер в 192.168.1.1 бачить два з'єднання з 192.168.0.1. Що станеться в такому випадку, якщо яким-небудь потоком генератора випадкових чисел як 10.0.0.1, так і 10.0.0.2 обрати один і той же локальний порт?
aroth

4
Підтримка NAT в маршрутизаторі опікується деталями там. Мережевий трафік насправді відбувається через два з'єднання - клієнт до маршрутизатора та маршрутизатор до сервера. Маршрутизатор здійснює вихідні з'єднання на двох різних портах 192.168.0.1:1234 та 192.168.0.1.1 .678. Потім вхідний трафік перенаправляється маршрутизатором до потрібного клієнта.
17 з 26

3
Якщо сокет ідентифікується квартетом, що таке квартет інформації прослуховувальної сокети?
Ерік Чжен

74

Просто для додання відповіді, наданої користувачем "17 з 26"

Розетка насправді складається з 5 кортежів (вихідний ip, порт джерела, ip призначення, порт призначення, протокол). Тут протокол може TCP або UDP або будь-який протокол транспортного рівня. Цей протокол ідентифікується в пакеті з поля 'протокол' в дейтаграмі IP.

Таким чином, можливо, щоб різні сервіси на сервері спілкувалися з одним і тим же клієнтом на абсолютно однакових 4-х кортежах, але різні в протоколі. Наприклад

Apache на стороні сервера, що розмовляє (server1.com:880-client1:1234 на TCP) і World of Warcraft розмовляє (server1.com:880-client1:1234 на UDP)

І клієнт, і сервер будуть обробляти це як поле протоколу в IP-пакеті в обох випадках, навіть якщо всі інші 4 поля однакові.


13

Що мене збентежило, коли я дізнався це, це те, що умови socketта portприпускають, що вони є чимось фізичним, коли насправді вони є лише структурами даних, які ядро ​​використовує для абстрагування деталей мереж.

Таким чином, структури даних реалізуються для того, щоб мати можливість відривати з'єднання від різних клієнтів. Що стосується того, як вони реалізовані, відповідь або а) це не має значення, мета API розеток полягає саме в тому, що реалізація не має значення, або b.) Просто мати вигляд. Крім настійно рекомендованих книг Стівенса, що містять детальний опис однієї реалізації, ознайомтеся з джерелом в Linux або Solaris або в одному з BSD.


Так, більшість термінологій мережі - це просто присвоєння імен певним наборам бітів та рішенням, прийнятим на основі їх значень ("ідентифікатор протоколу", "маршрутизація", "прив'язка", "сокет" тощо). Всі мережеві карти апаратного кошти призначені для прийому є потоком біт. Що з ними відбувається стосовно програм на вашому комп’ютері, вирішує драйвер та ОС. Ми могли б позбутися всієї цієї термінології завтра, якби хотіли, але принцип доставки потоку бітів здається принциповим ...
masterxilo

-1

Як сказав інший хлопець, сокет однозначно ідентифікується 4-канальним пакетом (клієнтський IP, клієнтський порт, сервер IP, серверний порт).

Серверний процес, що працює на сервері IP, підтримує базу даних (тобто мені все одно, яку таблицю / список / дерево / масив / магічну структуру даних він використовує) активних сокетів і слухає на сервері Порт сервера. Коли він отримує повідомлення (через стек TCP / IP сервера), він перевіряє IP-адресу клієнта та порт клієнта щодо бази даних. Якщо IP-адресу клієнта та клієнтський порт знайдено в записі бази даних, повідомлення передається наявному оброблювачу, інакше створюється новий запис бази даних та створюється новий обробник, який обробляє цей сокет.

На початку ARPAnet певні протоколи (FTP для одного) слухали б певний порт для запитів на з'єднання та відповідали з порту передачі обслуговування. Подальша комунікація для цього з'єднання проходитиме через порт передачі. Це було зроблено для покращення продуктивності в одному пакеті: комп’ютери були в кілька днів повільнішими.


Ви можете детальніше розглянути деталь "порт передачі"?
Елі Бендерський

1
Це або опис деякого протоколу перед TCP, або надмірно спрощений. Клієнт, який намагається підключитися до прослуховувальної розетки, надсилає спеціальний пакет для встановлення з'єднання (набір біт SYN). Існує чітка відмінність між пакетом, який створює новий сокет, і тим, хто використовує існуючий сокет.
Джон М

... надсилає спеціальний пакет для встановлення з'єднання (набір бітів SYN). Який (наскільки я розумію) змушує стек протоколів передавати його слухачеві (якщо такий є), тому може бути лише один порт прослуховування на кожну комбінацію адреси / порту / протоколу. Я не впевнений, чи є це в специфікації чи просто у конвенції про реалізацію.
Пітер Вун

1
Другий абзац неправильно описує, що відбувається ні на рівні TCP, ні в серверному процесі. Серверні процеси не потребують підтримання структури даних будь-яких типів сокетів або для перевірки вхідних пар: портів проти чого б то не було. Ось для чого там розетки. FTP використовує окремий порт для даних, не для всіх "подальших комунікацій", і капелюхи, зроблені для спрощення протоколу, а не з міркувань продуктивності. Використання нового порту при цьому ні в якому разі не покращує продуктивність.
Маркіз Лорн

"підтримує базу даних (тобто мені байдуже, яку структуру даних використовує таблиця / список / дерево / масив / магія)" :) Я зазвичай називаю це "Таблицею" (а може бути, "Графіком" або "Деревом рішення" ). "База даних" пропонує мені деяку реалізацію.
masterxilo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.