Як сервер дізнається, на який порт клієнта надіслати?


26

Як я розумію, це відбувається, коли клієнт робить запит на з'єднання:

  1. Сервер буде прив’язаний до певного номера порту. Номер порту завжди пов'язаний з процесом прослуховування. Оскільки тільки сервер прослуховує вхідні з'єднання, нам не потрібно зв'язуватись на стороні клієнта
  2. Сервер буде постійно слухати цей номер порту.
  3. Клієнт надішле connect()запит.
  4. Сервер прийме запит, використовуючи accept(). Як тільки сервер приймає клієнтський запит, ядро ​​виділяє для сервера випадковий номер порту для подальшого send()і receive(), оскільки той самий номер порту на сервері не може використовуватися як для надсилання, так і для прослуховування, і попередній порт все ще прослуховування нових з'єднань

Враховуючи все це, як сервер дізнається, який порт отримує клієнт? Я знаю, що клієнт надсилатиме сегменти TCP з портом джерела та портом призначення, тому сервер буде використовувати вихідний порт цього сегмента як порт призначення, але яку функцію викликає сервер, щоб дізнатися про цей порт? Це accept()?


Відповіді:


33

Це частина заголовка TCP (або UDP тощо) в пакеті. Так сервер виявляє, оскільки клієнт це говорить. Це схоже на те, як він дізнається IP-адресу клієнта (яка є частиною заголовка IP).

Наприклад, кожен пакет TCP включає заголовок IP (принаймні, з вихідним IP, IP адресом та протоколом [TCP], принаймні). Потім з'являється заголовок TCP (з вихідним портом і портом призначення, плюс більше).

Коли ядро ​​отримує SYN-пакет (початок TCP-з'єднання) з віддаленим IP 10.11.12.13 (у заголовку IP) та віддаленим портом 12345 (у заголовку TCP), воно знає віддалений IP та порт . Він надсилає назад SYN | ACK. Якщо повертається ACK назад, listenвиклик повертає нову розетку, встановлену для цього з'єднання.

Сокет TCP однозначно ідентифікується чотирма значеннями (віддалений IP, локальний IP, віддалений порт, локальний порт). Ви можете мати кілька підключень / розеток, якщо принаймні один з них відрізняється.

Як правило, локальний порт і локальний IP будуть однаковими для всіх підключень до серверного процесу (наприклад, всі з'єднання з sshd будуть на локальному ip: 22). Якщо один віддалений апарат здійснює декілька з'єднань, кожен з них використовуватиме інший віддалений порт. Так що все, крім віддаленого порту, буде те саме, але це добре - лише один з чотирьох повинен відрізнятися.

Ви можете використовувати, наприклад, wirehsark для перегляду пакету, і він позначить усі дані для вас. Тут виділений вихідний порт (зауважте, що він виділений у декодованому пакеті, а також шістнадцятковий дамп у нижній частині):

Wireshark, що показує пакет TCP SYN


> Дякую за пояснення. Отже, ви мали на меті сказати, що новий дескриптор сокетів сервера (тобто кортеж), отриманий після accept (), матиме дані про порт клієнта та адресу клієнта, і використовуючи цей новий сервер дескрипторів сокета, він надсилає та отримує дані і від client.New дескриптор сокетів матиме новий номер порту сервера, призначений ядром, ip сервером, ip клієнта та портом клієнта. Я прав?
Субі Суреш

@SubiSuresh так, кортеж зберігається всередині ядра, пов'язаного з цим дескриптором файлу.
дероберт

> Дякую derobert. Отже, я роблю висновок, що новий дескриптор сокетів сервера матиме клієнтський порт та адресу клієнта, які сервер отримує від accept (). Моє розуміння, чи не так?
Субі Суреш

@SubiSuresh Так, це правильно. З точки зору програми, вам зазвичай все одно (крім журналу). Ядро гарантує, що дані, які ви write(тощо) переходите в потрібне місце.
дероберт

> дякую за вашу допомогу, і я думаю, що я отримав крапку. ;-)
Субі Суреш

2

"Запит на підключення ( connect()системний виклик клієнтської програми , як правило) викликає тристороннє рукостискання . Перший пакет тривимірного рукостискання (від клієнта до сервера) має встановлений прапор SYN і включає номер порту TCP клієнтської програми ядро призначає йому.

Це можна побачити в статті про пакети Nmap vs Natural SYN . Розшифровка пакету Nmap SYN має фразу "source.60058> dest.22". Декодування "законного пакету SYN" містить у собі фразу "source.35970> dest.80". Два пакети SYN повідомляють віддаленому ядру, що пакети перебувають відповідно від порту TCP 60058 та порту 35970 відповідно.


> Але Брюс, що відбувається ззаду. Але як мій сервер насправді отримує деталі, наприклад, номер порту, як правило, в програмах клієнтських серверів, я ніколи не бачив жодної функції для вибору порту клієнта та адреси клієнта
Субі Суреш

Системний виклик getpeername()повинен робити це у будь-якому відкритому сокеті. accept()Системний виклик , що код сервера повинен використовувати , щоб отримати дескриптор файлу сокета зворотного зв'язку з клієнтом має параметр ( «SOCKADDR» в моїх чоловічих сторінках), що містить IP - адреса потенційного клієнта і TCP номер порту.
Брюс Едігер

> Будь ласка, не заперечуйте, якщо я elloborate. З усіх вхідних даних я зрозумів, що accept () має структуру sockaddr_in, заповнену деталями клієнта, і новий дескриптор розетки сервера повернеться після accept () автоматично матиме клієнтський порт та адресу. Ось чому ми можемо надсилати за допомогою send (новий дескриптор розетки сервера). Я сподіваюся, я до цього питання? Це просто для того, щоб переконатися, що те, що я зрозумів, правильно. Добре?
Субі Суреш

@SubiSuresh - я вважаю, ти написав правду.
Брюс Едігер

1

TCP socket - це потік, орієнтований на потік. Два дескриптори розетки (належать вам та вашому колегу) надійно з'єднані. Тож вам не доведеться турбуватися про порт клієнта - просто напишіть дескриптор сокета!

Крім того, не соромтеся отримувати ім'я користувача (2), якщо ви дійсно хочете це знати (можливо, для ведення журналів).


0

З'єднання визначається кортежем (вихідний IP, вихідний порт, IP-адреса призначення, порт призначення). Відповіді йдуть навпаки.


@vondrand В цей момент я зрозумів фон. Але з якої функції сервер дізнається про номер порту клієнта? З тим, що знає номер клієнтського порту, як він буде відправлений. Так сервер використовує структуру accept () для отримання клієнта порт?
Субі Суреш
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.