In che modo il server scopre a quale porta client inviare?


26

A quanto ho capito, questo è ciò che accade quando un client effettua una richiesta di connessione:

  1. Il server sarà associato a un determinato numero di porta. Il numero di porta è sempre associato a un processo di ascolto. Poiché solo il server è in attesa di connessioni in entrata, non è necessario eseguire il bind sul lato client
  2. Il server continuerà ad ascoltare su quel numero di porta.
  3. Il cliente invierà una connect()richiesta.
  4. Il server accetterà la richiesta utilizzando accept(). Non appena il server accetta la richiesta del client, il kernel alloca ulteriormente un numero di porta casuale per il server send()e receive(), poiché lo stesso numero di porta sul server non può essere utilizzato per l'invio e l'ascolto, e la porta precedente è ancora ascoltando nuove connessioni

Alla luce di tutto ciò, come fa il server a scoprire su quale porta sta ricevendo il client? So che il client invierà segmenti TCP con una porta di origine e una porta di destinazione, quindi il server utilizzerà la porta di origine di quel segmento come porta di destinazione, ma quale funzione chiama il server per scoprire quella porta? È vero accept()?


Risposte:


33

Fa parte dell'intestazione TCP (o UDP, ecc.), Nel pacchetto. Quindi il server lo scopre perché lo dice il client. Questo è simile a come trova l'indirizzo IP del client (che fa parte dell'intestazione IP).

Ad esempio, ogni pacchetto TCP include un'intestazione IP (almeno con IP di origine, IP di destinazione e protocollo [TCP]). Quindi c'è un'intestazione TCP (con porta di origine e di destinazione, più altro).

Quando il kernel riceve un pacchetto SYN (l'inizio di una connessione TCP) con un IP remoto del 10.11.12.13 (nell'intestazione IP) e una porta remota di 12345 (nell'intestazione TCP), allora conosce l'IP remoto e la porta . Restituisce un SYN | ACK. Se viene restituito un ACK, la listenchiamata restituisce un nuovo socket, impostato per quella connessione.

Un socket TCP è identificato in modo univoco dai quattro valori (IP remoto, IP locale, porta remota, porta locale). Puoi avere più connessioni / socket, purché almeno una di queste differisca.

In genere, la porta locale e l'IP locale saranno gli stessi per tutte le connessioni a un processo del server (ad es. Tutte le connessioni a sshd saranno su local-ip: 22). Se una macchina remota effettua più connessioni, ognuna utilizzerà una porta remota diversa. Quindi tutto tranne la porta remota sarà la stessa, ma va bene, solo una delle quattro deve essere diversa.

Puoi usare, ad esempio, wirehsark per vedere il pacchetto e etichetterà tutti i dati per te. Ecco la porta di origine evidenziata (notare che è evidenziata nel pacchetto decodificato, così come il dump esadecimale nella parte inferiore):

Wireshark mostra un pacchetto TCP SYN


> Grazie per la spiegazione. Quindi intendevi dire che il nuovo descrittore del socket del server (ovvero la tupla) ottenuto dopo aver accettato () avrà i dettagli della porta e dell'indirizzo del client e l'utilizzo del nuovo server descrittore del socket invia e riceve i dati a e dal client. Il nuovo descrittore del file socket avrà un nuovo numero di porta del server assegnato dal kernel, dall'ip del server, dall'ip del client e dalla porta del client.
Subi Suresh,

@SubiSuresh sì, la tupla è memorizzata nel kernel, associata a quel descrittore di file.
derobert,

> Grazie derobert. Quindi sto concludendo che il nuovo descrittore del socket del server avrà la porta del client e l'indirizzo del client, che il server ottiene dall'accettare (). La mia comprensione va bene, vero?
Subi Suresh,

@SubiSuresh Sì, è corretto. Dal punto di vista dell'applicazione, di solito non ti interessa (tranne per la registrazione). Il kernel si assicura che i dati che tu write(ecc.) Vadano nel posto giusto.
derobert,

> grazie per il vostro aiuto e penso di aver capito il punto. ;-)
Subi Suresh

2

La "richiesta di connessione (la connect()chiamata di sistema del programma client , in genere) provoca un handshake a tre vie . Il primo pacchetto dell'handshake a 3 vie (dal client al server) ha il flag SYN impostato e include il numero di porta TCP del programma client il kernel gli assegna.

Puoi vederlo in un articolo sui pacchetti Nmap vs Natural SYN . La decodifica del pacchetto Nmap SYN ha la frase "source.60058> dest.22". La decodifica del "pacchetto SYN legittimo" contiene la frase "source.35970> dest.80". I due pacchetti SYN indicano al kernel remoto che i pacchetti provengono rispettivamente dalla porta TCP 60058 e dalla porta 35970.


> Ma Bruce sta accadendo nel back-end, ma in che modo il mio server sta effettivamente recuperando i dettagli come il numero di porta perché normalmente nei programmi del server client, non ho mai visto alcuna funzione per recuperare la porta e l'indirizzo del client
Subi Suresh

La chiamata di sistema getpeername()dovrebbe consentire di farlo su qualsiasi socket aperto. La accept()chiamata di sistema che il codice server deve utilizzare per ottenere un descrittore di file socket per comunicare con il client ha un parametro ("sockaddr" nelle mie pagine man) che contiene l'indirizzo IP e il numero di porta TCP del potenziale cliente.
Bruce Ediger

> Per favore, non preoccuparti se elloborate. Da tutti gli input che ho capito ho capito che accetta () sta avendo la struttura sockaddr_in piena di dettagli del client e il nuovo descrittore del socket del server restituito dopo che accetta () avrà automaticamente la porta e l'indirizzo del client. Ecco perché siamo in grado di inviare utilizzando send (nuovo descrittore di socket del server). Spero di essere all'altezza? Questo è solo per assicurarmi che ciò che ho capito sia giusto.
Subi Suresh,

@SubiSuresh - Credo che tu abbia scritto la verità.
Bruce Ediger

1

Il socket TCP è un socket orientato al flusso. I due descrittori di socket (posseduti da te e dal tuo peer) sono collegati in modo affidabile. Quindi non devi preoccuparti della porta del client: basta scrivere il descrittore del socket!

Inoltre, sentiti libero di getockname (2) se vuoi davvero saperlo (forse per la registrazione).


0

La connessione è definita da una tupla (IP di origine, porta di origine, IP di destinazione, porta di destinazione). Le risposte vanno al contrario.


@vondrand Quel punto ho capito von. Ma da quale funzione il server viene a conoscenza del numero di porta del client? Senza conoscere il numero di porta del client come invierà. Quindi il server utilizza la struttura in accept () per recuperare il client porto?
Subi Suresh
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.