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