Могут ли два разных сокета UDP в системе связывать один и тот же порт? - PullRequest
7 голосов
/ 05 мая 2010

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

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

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

Edit:

TCP socket:

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

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

Ответы [ 2 ]

13 голосов
/ 05 мая 2010

Это связано с разницей между 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, это создаст исключение связывания, поскольку порт предназначен для локальной машины, и сопоставления больше не являются уникальными. Но когда вы принимаете соединение на серверном сокете, удаленный компьютер вступает в игру, чтобы сделать сокет уникальным, как при создании сокета для удаленного компьютера:

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

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

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

1 голос
/ 05 мая 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...