Как несколько клиентов одновременно подключаются к одному порту, скажем 80, на сервере? [дубликат]



этот вопрос уже есть ответ здесь:

Я понимаю основы работы портов. Однако я не понимаю, как несколько клиентов могут одновременно подключаться к порту 80. Я знаю, что каждый клиент имеет уникальный (для своей машины) порт. Отвечает ли сервер от доступного порта клиенту и просто заявляет, что ответ пришел из 80? Как это работает?

224   5  

5 ответов:

во-первых, "порт" - это просто число. Все" соединение с портом "действительно представляет собой пакет, который имеет этот номер, указанный в поле заголовка" порт назначения".

теперь есть два ответа на ваш вопрос, один для протоколов с сохранением состояния и один для протоколов без сохранения состояния.

для протокола без состояния (т. е. UDP) нет проблем, потому что" соединения " не существуют - несколько человек могут отправлять пакеты на один и тот же порт, и их пакеты будут поступать какая бы ни была последовательность. Никто никогда не находится в" Связном " состоянии.

для протокола с отслеживанием состояния (например, TCP) соединение идентифицируется 4-кортежем, состоящим из портов источника и назначения, а также IP-адресов источника и назначения. Таким образом, если две разные машины подключаются к одному и тому же порту на третьей машине, есть два разных соединения, потому что исходные IP-адреса отличаются. Если одна и та же машина (или две за NAT или иным образом используют один и тот же IP-адрес) подключается дважды к одному удаленному устройству в конце концов, соединения различаются по порту источника (который обычно является случайным портом с высоким номером).

просто, если я дважды подключаюсь к одному и тому же веб-серверу с моего клиента, два соединения будут иметь разные исходные порты с моей точки зрения и порты назначения с веб-сервера. поэтому нет никакой двусмысленности, хотя оба соединения имеют одинаковые исходные и целевые IP-адреса.

порты-это способ мультиплекс IP-адреса так что различные приложения могут прослушивать одну и ту же пару IP-адрес/протокол. Если приложение не определяет свой собственный протокол более высокого уровня, нет никакого способа мультиплексировать порт. Если два соединения, использующие один и тот же протокол, одновременно имеют идентичные IP-адреса источника и назначения и идентичные порты источника и назначения, они должны быть одним и тем же соединением.

важно:

мне жаль говорить, что ответ от "Borealid" неточен и несколько неверен - во-первых, нет никакого отношения к статичности или безгражданству, чтобы ответить на этот вопрос, и самое главное определение кортежа для сокета неверно.

сначала запомните ниже два правила:

  1. первичный ключ сокета: сокет идентифицируется {SRC-IP, SRC-PORT, DEST-IP, DEST-PORT, PROTOCOL} а не {SRC-IP, SRC-PORT, DEST-IP, DEST-PORT} - протокол важная часть определения сокета.

  2. OS Process & Socket mapping: процесс может быть связан с (может открывать/может прослушивать) несколько сокетов, которые могут быть очевидны для многих читателей.

Пример 1: два клиента, подключенных к одному порту сервера означает:socket1 {SRC-A, 100, DEST-X,80, TCP} и socket2{SRC-B, 100, DEST-X,80, TCP}. Это означает, что хост A подключается к порту 80 сервера X, а другой хост B также подключается к тому же серверу X к тому же порту 80. Теперь, как сервер обработка этих двух сокетов зависит от того, является ли сервер однопоточным или многопоточным (я объясню это позже). Важно то, что один сервер может слушать несколько сокетов одновременно.

чтобы ответить на первоначальный вопрос поста:

независимо от протоколов с состоянием или без состояния, два клиента могут подключаться к одному и тому же порту сервера, потому что для каждого клиента мы можем назначить другой сокет (поскольку IP-адрес клиента определенно будет отличаться). Тот же клиент может также иметь два сокета, подключенных к одному и тому же порту сервера - так как такие сокеты отличаются SRC-PORT. Со всей справедливостью, "Бореалид" по существу упомянул тот же самый правильный ответ, но ссылка на состояние-менее/полное была отчасти ненужной/запутанной.

чтобы ответить на вторую часть вопроса о том, как сервер знает, какой сокет ответить. Сначала поймите, что для одного серверного процесса, который прослушивает один и тот же порт, может быть более одного сокета (может быть от одного клиента или от разных клиентов). Теперь, пока сервер знает, какой запрос связан с каким сокетом, он всегда может ответить соответствующему клиенту, используя тот же сокет. Таким образом, сервер никогда не должен открывать другой порт в своем собственном узле, чем исходный, на котором клиент изначально пытался связать подключиться. Если какой-либо сервер выделяет разные порты сервера после привязки сокета, то, на мой взгляд, сервер тратит свой ресурс, и ему должен быть нужен клиент связать снова подключитесь к новому назначенному порту.

еще немного для полноты картины:

Пример 2: это очень интересный вопрос, который может два разных процесса сервера прослушивать один и тот же порт. Если вы не рассматриваете протокол как один из параметров, определяющих сокет, то ответ-нет. Изначально это так, потому что мы можем сказать, что в таком случае для одного клиента, пытающегося подключиться к серверу-порту, не будет никакого механизм, чтобы упомянуть, какой из двух процессов прослушивания клиент намерен. Это та же самая тема, утвержденная правилом (2). Однако это неправильный ответ, потому что "протокол" также является частью определения сокета. Таким образом, два процесса в одном узле может слушать тот же порт, только если они используют другой протокол. Например, два несвязанных клиента (скажем, один использует TCP, а другой использует UDP) могут связать подключение и связь с тем же узлом сервера и с тем же портом, но они должно обслуживаться двумя разными серверными процессами.

типы серверов - один и несколько:

когда серверные процессы прослушивают порт, что означает, что несколько сокетов могут одновременно подключаться и взаимодействовать с одним и тем же серверным процессом. Если сервер использует только один дочерний процесс для обслуживания всех сокетов, то сервер называется однопроцессным / потоковым, и если сервер использует много подпроцессов для обслуживания каждого сокета одним подпроцессом, то сервер называется многопроцессным / потоковым сервером. Обратите внимание, что независимо от типа сервера сервер может/должен всегда использовать один и тот же исходный сокет для ответа (нет необходимости выделять другой сервер-порт).

предложил - книги и остальные два тома, если можно.

примечание о родительском / дочернем процессе (в ответ на запрос/комментарий 'Ioan Alexandru Cucu')

везде, где я упомянул какую-либо концепцию в отношении двух процессов скажем, A и B, считают, что они не связаны родительскими дочерними отношениями. ОС (особенно UNIX) по дизайну позволяют дочернему процессу наследовать все файловые дескрипторы (FD) от родителей. Таким образом, все сокеты (в UNIX, как ОС, также являются частью FD), которые слушают процесс A, могут прослушиваться многими другими процессами A1, A2,.. пока они связаны отношением "родитель-потомок" с A. Но независимый процесс B (т. е. не имеющий отношения "родитель-потомок" к A) не может прослушивать один и тот же сокет. Кроме того, также обратите внимание, что это правило запрета двух независимых процессов для прослушивания одного и того же сокета лежит на ОС (или ее сетевых библиотеках), и на сегодняшний день оно соблюдается большинством ОС. однако можно создать собственную ОС, которая может очень хорошо нарушить эти ограничения.

TCP / HTTP прослушивание портов: как многие пользователи могут использовать один и тот же порт

Итак, что происходит, когда сервер прослушивает входящие соединения на TCP-порт? Например, скажем, у вас есть веб-сервер на порту 80. Предположим, что ваш компьютер имеет общедоступный IP-адрес 24.14.181.229, а человек, который пытается подключиться к вам, имеет IP-адрес 10.1.2.3. Этот человек может подключиться к вам, открыв TCP-сокет до 24.14.181.229:80. Достаточно просто.

интуитивно (и ошибочно), большинство людей предполагают, что это выглядит примерно так:

    Local Computer    | Remote Computer
    --------------------------------
    <local_ip>:80     | <foreign_ip>:80

    ^^ not actually what happens, but this is the conceptual model a lot of people have in mind.

это интуитивно, потому что с точки зрения клиента, он имеет IP-адрес и подключается к серверу по IP:порт. Поскольку клиент подключается к порту 80, то его порт тоже должен быть 80? Это разумная вещь, чтобы думать, но на самом деле не происходит. Если бы это было правильно, мы могли бы обслуживать только одного пользователя на иностранный IP-адрес. После того, как удаленный компьютер подключается, то он будет Хог порт 80 подключение к порту 80, и никто не мог подключиться.

три вещи должны быть поняты:

1.) На сервере, процесс слушать на порт. Как только он получает соединение, он передает его другому потоку. Связь никогда не засоряет порт прослушивания.

2.) Соединения однозначно определяется ОС по следующей 5-кортеж (местного IP, локальный-порт, удаленный IP-адресов, удаленный порт, протокол). Если какой-либо элемент в кортеже другое, тогда это совершенно самостоятельное соединение.

3.) Когда клиент подключается к серверу, он выбирает случайный, неиспользуемый порт источника высокого порядка. Таким образом, один клиент может иметь до ~64k подключений к серверу для одного и того же порта назначения.

Итак, это действительно то, что создается, когда клиент подключается к серверу:

    Local Computer   | Remote Computer           | Role
    -----------------------------------------------------------
    0.0.0.0:80       | <none>                    | LISTENING
    127.0.0.1:80     | 10.1.2.3:<random_port>    | ESTABLISHED

глядя на то, что на самом деле происходит

во-первых, давайте использовать netstat, чтобы увидеть что происходит на этом компьютере. Мы будем использовать порт 500 вместо 80 (потому что вся куча вещей происходит на порту 80, поскольку это общий порт, но функционально это не имеет значения).

    netstat -atnp | grep -i ":500 "

как и ожидалось, выход пуст. Теперь давайте запустим веб-сервер:

    sudo python3 -m http.server 500

теперь, вот результат запуска netstat снова:

    Proto Recv-Q Send-Q Local Address           Foreign Address         State  
    tcp        0      0 0.0.0.0:500             0.0.0.0:*               LISTEN      - 

Итак, теперь есть один процесс, который активно слушает (состояние: слушать) на порту 500. Местный житель адрес 0.0.0.0, который является кодом для "прослушивания для всех". Простая ошибка заключается в прослушивании адреса 127.0.0.1, который будет принимать только соединения с текущего компьютера. Таким образом, это не соединение, это просто означает, что процесс запросил привязку() к порту IP, и этот процесс отвечает за обработку всех подключений к этому порту. Это намекает на ограничение, что может быть только один процесс на компьютер, прослушивающий порт (есть способы обойти это с помощью мультиплексирования, но это гораздо более сложная тема). Если веб-сервер прослушивает порт 80, он не может совместно использовать этот порт с другими веб-серверами.

Итак, теперь давайте подключим пользователя к нашей машине:

    quicknet -m tcp -t localhost:500 -p Test payload.

это простой скрипт (https://github.com/grokit/dcore/tree/master/apps/quicknet), который открывает TCP-сокет, отправляет полезную нагрузку ("тестовая полезная нагрузка."в данном случае), ждет несколько секунд и отключается. Выполнение netstat снова, пока это происходит отображает следующее:

    Proto Recv-Q Send-Q Local Address           Foreign Address         State  
    tcp        0      0 0.0.0.0:500             0.0.0.0:*               LISTEN      -
    tcp        0      0 192.168.1.10:500        192.168.1.13:54240      ESTABLISHED -

если вы подключитесь к другому клиенту и снова выполните netstat, вы увидите следующее:

    Proto Recv-Q Send-Q Local Address           Foreign Address         State  
    tcp        0      0 0.0.0.0:500             0.0.0.0:*               LISTEN      -
    tcp        0      0 192.168.1.10:500        192.168.1.13:26813      ESTABLISHED -

... то есть, клиент использовал другой случайный порт для подключения. Таким образом, никогда не бывает путаницы между IP-адресами.

обычно для каждого подключающегося клиента сервер разветвляет дочерний процесс, который взаимодействует с клиентом (TCP). Родительский сервер передает дочернему процессу установленный сокет,который взаимодействует с клиентом.

когда вы отправляете данные в сокет с вашего дочернего сервера, стек TCP в ОС создает пакет, возвращающийся к клиенту, и устанавливает "от порта" до 80.

несколько клиентов могут подключаться к одному порту (скажем, 80) на сервере, потому что на стороне сервера, после создания гнездо и обязательные (установка локального IP и порта)слушать вызывается в сокете, который сообщает ОС принимать входящие соединения.

когда клиент пытается подключиться к серверу на порт 80, то принимать вызов вызывается на сокете сервера. Это создает новый сокет для клиента, пытающегося подключиться и аналогично новые сокеты будут созданы для последующих клиентов, использующих тот же порт 80.

слова, выделенные курсивом, являются системными вызовами.

Ref

http://www.scs.stanford.edu/07wi-cs244b/refs/net2.pdf

    Ничего не найдено.

Добавить ответ:
Отменить.