giovedì 28 aprile 2016

Socket UDP

lei scrive che nel caso di UDP il server e il client eseguono le STESSE operazioni di TCP, tranne che per il send e il receive (quindi solo l'application layer cambia). Giustamente, essendo connectionless, nel send dovrò includere anche l'indirizzo TCP del destinatario, e nel receive riceverò anche l'indirizzo TCP del mittente. Non mi è chiaro tuttavia qualche particolare:
  1. se faccio da server con UDP, nell'application layer non uso mai di fatto il socket, nè per inviare nè per ricevere (in particolare per ricevere mi sembra di aver capito che passo come parametro la porta su cui sono in ascolto). Quindi che senso ha creare il socket, fare il bind e il listen se poi scrivo {msg,TCP-addr}=receive(port num)?
  2. se faccio da client valgono le stesse considerazioni di prima: che senso ha creare il socket se poi non lo uso per inviare/ricevere? Inoltre mi turba il connect(..): non abbiamo detto che siamo connectionless? Per concludere, visto che per ricevere devo sapere su che porta ricevere (come prima, sempre se ho capito bene), quando faccio {msg,TCP-addr}=receive(port) sul client, devo quindi sapere che porta mi è stata assegnata dal sistema operativo?
Effettivamente la slide 70 è ambigua. Dice "identico a quanto visto" ma è una descrizione superficiale.

E' "identico" in prima approssimazione, nel senso che è tutto identico a parte il fatto (non secondario) che non si crea una connessione: il server crea un socket, ci associa un port number ed attende richieste; quando riceve una request, risponde a chi ha inviato la request; il client invia request al server ed attende response.

Inoltre, la slide 71 è una semplificazione della realtà. I dubbi che espone ai punti 1 e 2 sono legittimi, perché discendono dalla slide 71 ma non si verificano nella realtà. Spiego più sotto quanto accade nella realtà, precisando che ai fini degli esami basta quanto è descritto nelle slide 70 e 71. La faccenda è infatti un pò intricata, eccessivamente intricata per i nostri fini.

Noi abbiamo detto che un socket è una estremità di tubo. Abbiamo anche accennato che nella realtà i socket sono complicati da usare anche perché sono generali, sono cioè utilizzabili con più protocolli. In particolare, i socket veri si usano anche con UDP. I socket sono cioè un generico "endpoint di comunicazione". Qualsiasi protocollo di comunicazione voglia usare un applicativo, lo deve fare attraverso i socket.

Quando un applicativo crea un socket, specifica con quale protocollo lo vuole usare.

Il server esegue s:=socket("voglio UDP"), bind(s, port-number) e poi una variante di receive(s) che torna due risultati: il messaggio ricevuto e l'indirizzo UDP del mittente (coppia IP-address, port-number; dico indirizzo UDP perché i numeri di porta UDP sono nello stesso intervallo dei numeri di porta TCP ma sono entità diverse, slide 72); poi risponde con una variante di send(s,msg) che ha un argomento in più rispetto a quella che abbiamo visto: l'indirizzo UDP del destinatario; tale indirizzo sarà quello da cui ha ricevuto il messaggio precedente;

Il client esegue s:=socket("voglio UDP"), poi la stessa variante di send(s,msg) vista sopra, in cui come indirizzo UDP del destinatario specificherà il server; poi esegue la stessa variante di receive(s) vista sopra, verificando che la risposta sia arrivata effettivamente dal server (altrimenti la scarta ed esegue nuovamente receive).

Se qualcuno vuole farsi venire il mal di testa, qui sotto c'è la descrizione di send e receive su Linux. Potrete toccare con mano che la realtà ha spessissimo molti dettagli che sono inutili o dannosi da un punto di vista didattico (http://bartoli-alberto.blogspot.it/2015/03/come-organizzo-lo-studio-di-internet.html).