Ha a che fare con la differenza tra TCP e UDP. Quando si crea un socket TCP, si crea una connessione client sincrona alla porta su un altro computer e, quando ci si connette a un indirizzo, si ottiene anche una porta locale sul socket. Quindi nel tuo codice di esempio le due prese creati potrebbe essere
clientSocket = localhost:2649 <-> ipAddress:8000
clientSocket1 = localhost:2650 <-> ipAddress:8000
Nota che, mentre essi indirizzo remoto è lo stesso, l'indirizzo locale è dotato di porte diverse, motivo per cui questo è permesso. Quindi qui le macchine remote locali possono inviare i dati in modo affidabile avanti e indietro usando le porte stabilite.
Per UDP questo non è il caso (presumo che si stia utilizzando DatagramSocket). Poiché UDP è asincrona (anziché sincrono come TCP), per ricevere dati non si sta creando un legame con un'altra macchina specifico, così per esempio se si dovesse provare
DatagramSocket udp1 = new DatagramSocket(8000); // = localhost:8000 <-> ?
DatagramSocket udp2 = new DatagramSocket(8000); // = localhost:8000 <-> ?
presa UDP non sa dove la i dati provengono da così non può esserci una mappatura univoca come TCP, anche a differenza di TCP, la porta specificata è la porta della macchina, non una porta macchina remota.
Un altro modo di pensarci quando si crea un socket UDP è come creare un socket del server TCP. Quando si crea un socket server TCP è in attesa di una connessione a venire da una macchina, ma quella macchina è sconosciuto e quando si crea un socket server TCP la porta specificata è una porta locale:
ServerSocket ss1 = new ServerSocket(8000); // = localhost:8000 <-> ?
ServerSocket ss2 = new ServerSocket(8000); // = localhost:8000 <-> ?
Anche in questo caso, come UDP questo creerà un'eccezione di binding perché la porta è per la macchina locale e le mappature non sono più univoci.Ma quando si accetta una connessione su un socket server macchina remota entra in gioco per rendere il socket unico, proprio come quando si crea un socket a un computer remoto:
Socket s1 = ss1.accept();// localhost:8000 <-> remoteIp1:12345
Socket s2 = ss1.accept();// localhost:8000 <-> remoteIp2:54321
Nota che, anche se l'indirizzo locale è lo stesso , gli indirizzi remoti per i socket sono diversi e quindi il mapping totale (localip: porta < -> remoteip: port) è ora univoco.
Quindi in un certo modo si può pensare a un socket UDP come un socket di un server TCP ed è per questo che è necessario associarlo a una porta univoca.
quindi, vuoi dire che non possiamo creare due socket udp con la stessa porta? – swift