Два других UDP могут снабдить сокетом в системе, связывают тот же порт?

У меня есть приложение, которое использует соединение UDP, теперь когда я пытаюсь запустить приложение несколько раз его бросок меня исключение

java.net.BindException: Address already in use: Cannot bind

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

Править:

TCP socket:

Socket clientSocket= new Socket(ipAddress, 8000);
Socket clientSocket1= new Socket(ipAddress, 8000);

Если я создаю сокет TCP как вышеупомянутый с тем же портом, он не бросает ошибки. но если я делаю это с Сокетом UDP это бросающий меня исключение, почему?

7
задан swift 5 May 2010 в 10:56
поделиться

2 ответа

Вы уверены, что приложение TCP действительно выполняет привязку с ненулевым номером порта? Это не должно работать и для TCP. Назначение номеров портов - определить, к какому запущенному экземпляру приложения направлять трафик; если бы два приложения связали два сокета с одним и тем же номером порта, такая маршрутизация стала бы невозможной, поэтому это ошибка.

1
ответ дан 6 December 2019 в 15:19
поделиться

Это связано с различием между TCP и UDP. Когда вы создаете TCP-сокет, вы создаете синхронное клиентское соединение с портом на другой машине, а когда вы подключаетесь к адресу, вы фактически получаете локальный порт на сокете. Итак, в вашем примере кода два созданных сокета могут иметь вид

clientSocket = localhost:2649 <-> ipAddress:8000
clientSocket1 = localhost:2650 <-> ipAddress:8000

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

Для UDP это не так (я предполагаю, что вы используете DatagramSocket). Поскольку UDP является асинхронным (в отличие от синхронного, как TCP), для получения данных вы не создаете привязку к другой конкретной машине, поэтому, например, если вы попробуете

DatagramSocket udp1 = new DatagramSocket(8000); // = localhost:8000 <-> ?
DatagramSocket udp2 = new DatagramSocket(8000); // = localhost:8000 <-> ?

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

Другой способ думать об этом, когда вы создаете сокет UDP, это похоже на создание сокета сервера TCP. Когда вы создаете сокет TCP-сервера, он ожидает подключения от некоторой машины, но эта машина неизвестна, и когда вы создаете сокет TCP-сервера, порт, который вы указываете, является локальным портом:

ServerSocket ss1 = new ServerSocket(8000); // = localhost:8000 <-> ?
ServerSocket ss2 = new ServerSocket(8000); // = localhost:8000 <-> ?

Опять же, как и UDP, это создаст bind исключение, потому что порт предназначен для локальной машины, и сопоставления больше не уникальны.Но когда вы принимаете соединение с серверным сокетом, удаленная машина вступает в игру, чтобы сделать сокет уникальным, точно так же, как когда вы создаете сокет для удаленной машины:

Socket s1 = ss1.accept();// localhost:8000 <-> remoteIp1:12345
Socket s2 = ss1.accept();// localhost:8000 <-> remoteIp2:54321

Обратите внимание, что хотя локальный адрес такой же, удаленные адреса для сокетов разные, и, следовательно, общее отображение (localip: port <-> remoteip: port) теперь уникально.

В каком-то смысле вы можете думать о сокете UDP как о сокете сервера TCP, и именно поэтому вы должны привязать его к уникальному порту.

13
ответ дан 6 December 2019 в 15:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: