Как идентифицируются клиенты (клиентские сокеты)? - PullRequest
10 голосов
/ 13 марта 2010

Насколько я понимаю, serverSocket = new ServerSocket(portNumber) мы создаем объект, который потенциально может «прослушивать» указанный порт. С помощью clientSocket = serverSocket.accept() мы заставляем сокет сервера «слушать» его порт и «принимать» соединение от любого клиента, который пытается подключиться к серверу через порт, связанный с сервером. Когда я говорю «клиент пытается подключиться к серверу», я имею в виду, что клиентская программа выполняет «nameSocket = new Socket (serverIP, serverPort)».

Если клиент пытается подключиться к серверу, сервер «принимает» этого клиента (т.е. создает «клиентский сокет», связанный с этим клиентом).

Если новый клиент пытается подключиться к серверу, сервер создает другой клиентский сокет (связанный с новым клиентом). Но как сервер узнает, является ли это «новым» клиентом или «старым», у которого уже есть сокет? Или, другими словами, как идентифицируются клиенты? По их IP? По их IP и порту? Под какими "подписями"?

Что произойдет, если «старый» клиент попытается снова использовать Socket (serverIP, serverIP)? Будет ли сервер создавать второй сокет, связанный с этим клиентом?

Ответы [ 5 ]

23 голосов
/ 13 марта 2010

Сервер прослушивает адрес и порт. Например, IP-адрес вашего сервера 10.0.0.1, и он прослушивает порт 8000.

Ваш IP-адрес клиента - 10.0.0.2, и клиент «подключается» к серверу через порт 8000 10.0.0.1. В TCP-соединении вы указываете порт сервера, к которому хотите подключиться. Ваш клиент фактически получит свой собственный номер порта, но вы не контролируете его, и он будет отличаться для каждого соединения. Клиент выбирает порт server , к которому он хочет подключиться, а не порт client , к которому он подключается.

Например, при первом соединении ваш клиент может получить клиентский порт 12345. Он подключается от 10.0.0.2 порта 12345 к серверу 10.0.0.1 к порту 8000. Ваш сервер может видеть, к какому порту подключается клиент. вызвав getpeername на его стороне соединения.

Когда клиент подключается во второй раз, номер порта будет другим, скажем, порт 12377. Сервер может увидеть это, вызвав getpeername во втором соединении - он увидит другой номер порта на стороне клиента. (getpeername также показывает IP-адрес клиента.)

Кроме того, каждый раз, когда вы вызываете accept на сервере, вы получаете новый сокет. У вас все еще есть исходный сокет прослушивания, и при каждом принятии вы получаете новый сокет. Вызовите getpeername на принятом сокете, чтобы увидеть, с какого клиентского порта идет соединение. Если к вашему серверу подключены два клиента, теперь у вас есть три сокета - исходный сокет прослушивания и сокеты каждого из двух клиентов.

Вы можете иметь много клиентов, подключенных к одному и тому же порту сервера 8000 одновременно. И многие клиенты могут быть подключены с одного и того же клиентского порта (например, порта 12345), но не с одного и того же IP-адреса. С того же IP-адреса клиента, например, 10.0.0.2, каждое клиентское соединение с портом 8000 сервера будет осуществляться с уникального клиентского порта, например, 12345, 12377 и т. Д. Вы можете отличить клиентов по их комбинации IP-адреса и порта.

Один и тот же клиент может также иметь несколько подключений к серверу одновременно, например, одно соединение с клиентского порта 12345 и другое с 12377 одновременно. Под клиентом я имею в виду исходный IP-адрес, а не конкретный программный объект. Вы просто увидите два активных соединения с одинаковым IP-адресом клиента.

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

5 голосов
/ 13 марта 2010

Каждое TCP-соединение имеет в качестве идентификатора четверку (порт src, адрес src, порт dest, адрес dest) .

Всякий раз, когда ваш сервер принимает нового клиента, создается новый Socket, и он независим от любого другого сокета, созданного до сих пор. Идентификация клиентов не затрагивается каким-либо образом.

Вам не нужно думать, что сокеты ассоциируются с "клиентами", они связаны с ip и портом, но между этими двумя понятиями нет прямой корреляции.

Если тот же клиент попытается открыть другой сокет, создав новый, у вас будет два несвязанных сокета (потому что порты наверняка будут другими). Это связано с тем, что клиент не может использовать один и тот же порт для открытия нового соединения, поэтому четверка будет другой, тот же ip клиента, тот же ip сервера, тот же порт сервера, но другой порт клиента.

РЕДАКТИРОВАТЬ на свои вопросы:

  1. клиенты не указывают порт, потому что он выбирается случайным образом из свободных (> 1024, если я не ошибаюсь) из базовой операционной системы
  2. соединение не может быть открыто с клиента, использующего тот же порт, операционная система не позволит вам сделать это (на самом деле вы вообще не указываете порт) и в любом случае сообщит, что порт уже привязан к сокету, поэтому эта проблема не может возникнуть.
  3. всякий раз, когда сервер получает новый запрос на подключение, он считается новым, потому что также, если ip - это тот же порт, он наверняка будет другим (в случае повторной отправки старого пакета или подобных предупреждений, я думаю, что запрос будет отклонен)

Кстати, все эти ситуации четко объяснены в TCP RFC здесь .

0 голосов
/ 13 марта 2010

Сокет идентифицируется как:

(Локальный IP, Локальный порт, Удаленный IP, Удаленный порт, протокол IP (UDP / TCP / SCTP / и т. Д.)

И это информация, которую ОС использует для сопоставления пакетов / данных с правильным дескриптором / дескриптором файла вашей программы. Для некоторых типов сокетов (например, неподключенный сокет UDP) удаленный порт / удаленный IP-адрес могут быть подстановочными знаками.

0 голосов
/ 13 марта 2010

Я думаю, что вопрос здесь в том, почему вас волнует, новый клиент или старый. Что нового и старого? Например, веб-браузер может подключаться к веб-серверу для запроса веб-страницы. Это создаст соединение, поэтому serverSocket.accept() вернет новый Socket. Затем соединение закрывается веб-браузером.

Через пару минут после окончания нажмите на ссылку на веб-странице и браузер запросит новую страницу на сервере. Это создаст соединение, поэтому serverSocket.accept() вернет новый Socket.

Теперь веб-серверу не важно, новый это или старый клиент. Это просто необходимо для сервера запрашиваемой страницы. Если сервер do заботится о том, что «клиент» уже запрашивал страницу в прошлом, он должен сделать это, используя некоторую информацию в протоколе, используемом в сокете. Проверить http://en.wikipedia.org/wiki/OSI_model В этом случае ServerSocket и Socket ack на транспортном уровне. На вопрос «действительно ли этот клиент уже запросил страницу на сервере» следует ответить информацией о сеансе или даже прикладном уровне.

В примере веб-браузера / сервера протокол http (который является приложением) хранит информацию о том, кто этот браузер, в параметрах запроса (браузер передает информацию куки-файлов с каждым запросом). Затем http-сервер может установить / прочитать информацию cookie, чтобы знать, подключен ли ранее браузер, и в конечном итоге поддерживать сеанс на стороне сервера для этого браузера.

Итак, вернемся к вашему вопросу: зачем вам новый или старый клиент?

0 голосов
/ 13 марта 2010

По определению, это не вопрос, связанный с Java, а вообще о работе сети, поскольку Sockets и SeverSockets применяются к любому языку программирования с поддержкой сети.

Сокет ограничен локальным портом. Клиент откроет соединение с сервером (с помощью операционной системы / драйверов / адаптеров / оборудования / линии /.../ line / оборудования / адаптеров / драйверов / серверной ОС). Это «соединение» осуществляется с помощью протокола, который называется IP (Интернет-протокол), когда вы подключены к Интернету. Когда вы используете «Сокеты», он будет использовать другой протокол, который является TCP / IP-протоколом.

Интернет-протокол будет идентифицировать узлы в сети по двум причинам: их IP-адрес и их порт. Протокол TCP / IP будет отправлять сообщения с использованием IP-адреса и проверять правильность получения сообщений.

Теперь; ответить на ваш вопрос: все зависит! Это зависит от ваших драйверов, ваших адаптеров, вашего оборудования, вашей линии. Когда вы подключаетесь к локальной машине, вы не получите дальше, чем адаптер. Аппаратное обеспечение не является обязательным, поскольку данные фактически не передаются по линии. (Хотя часто вам требуется оборудование, прежде чем вы сможете приобрести адаптер.)

По определению, интернет-протокол определяет соединение как пару узлов (таким образом, четыре вещи: два IP-адреса и два порта). Кроме того, Интернет-протокол определяет, что один узел может одновременно использовать только один порт для установления соединения с другим узлом (примечание: это относится только к клиенту, а не к серверу).

Чтобы ответить на ваш второй вопрос: если есть два сокета: «новый» и «старый». Поскольку по интернет-протоколу соединение представляет собой пару узлов, и узлы могут одновременно использовать только один порт для подключения, порты «новый» и «старый» должны быть разными. И поскольку это отличается, «новый» клиент может отличаться от «старого», поскольку номер порта отличается.

...