In fig. 15.8 è riportata la sezione principale del codice del nostro client. Il sorgente completo del programma (TCP_daytime.c, che comprende il trattamento delle opzioni ed una funzione per stampare un messaggio di aiuto) è allegato alla guida nella sezione dei codici sorgente e può essere compilato su una qualunque macchina GNU/Linux.
Il programma anzitutto (1–5) include gli header necessari; dopo la dichiarazione delle variabili (9–12) si è omessa tutta la parte relativa al trattamento degli argomenti passati dalla linea di comando (effettuata con le apposite funzioni illustrate in sez. 2.3.2).
Il primo passo (14–18) è creare un socket TCP (quindi di tipo SOCK_STREAM e di famiglia AF_INET). La funzione socket ritorna il descrittore che viene usato per identificare il socket in tutte le chiamate successive. Nel caso la chiamata fallisca si stampa un errore (16) con la funzione perror e si esce (17) con un codice di errore.
Il passo seguente (19–27) è quello di costruire un'apposita struttura sockaddr_in in cui sarà inserito l'indirizzo del server ed il numero della porta del servizio. Il primo passo (20) è inizializzare tutto a zero, per poi inserire il tipo di indirizzo (21) e la porta (22), usando per quest'ultima la funzione htons per convertire il formato dell'intero usato dal computer a quello usato nella rete, infine 23–27 si può utilizzare la funzione inet_pton per convertire l'indirizzo numerico passato dalla linea di comando.
A questo punto (28–32) usando la funzione connect sul socket creato in precedenza (29) si può stabilire la connessione con il server. Per questo si deve utilizzare come secondo argomento la struttura preparata in precedenza con il relativo indirizzo; si noti come, esistendo diversi tipi di socket, si sia dovuto effettuare un cast. Un valore di ritorno della funzione negativo implica il fallimento della connessione, nel qual caso si stampa un errore (30) e si ritorna (31).
Completata con successo la connessione il passo successivo (34–40) è leggere la data dal socket; il protocollo prevede che il server invii sempre una stringa alfanumerica, il formato della stringa non è specificato dallo standard, per cui noi useremo il formato usato dalla funzione ctime, seguito dai caratteri di terminazione \r\n, cioè qualcosa del tipo:
Wed Apr 4 00:53:00 2001\r\n
Come si è già spiegato in sez. 15.3.1 la risposta dal socket potrà arrivare in un unico pacchetto di 26 byte (come avverrà senz'altro nel caso in questione) ma potrebbe anche arrivare in 26 pacchetti di un byte. Per questo nel caso generale non si può mai assumere che tutti i dati arrivino con una singola lettura, pertanto quest'ultima deve essere effettuata in un ciclo in cui si continui a leggere fintanto che la funzione read non ritorni uno zero (che significa che l'altro capo ha chiuso la connessione) o un numero minore di zero (che significa un errore nella connessione).
Si noti come in questo caso la fine dei dati sia specificata dal server che chiude la connessione (anche questo è quanto richiesto dal protocollo); questa è una delle tecniche possibili (è quella usata pure dal protocollo HTTP), ma ce ne possono essere altre, ad esempio FTP marca la conclusione di un blocco di dati con la sequenza ASCII \r\n (carriage return e line feed), mentre il DNS mette la lunghezza in testa ad ogni blocco che trasmette. Il punto essenziale è che TCP non provvede nessuna indicazione che permetta di marcare dei blocchi di dati, per cui se questo è necessario deve provvedere il programma stesso.
Se abilitiamo il servizio daytime17 possiamo verificare il funzionamento del nostro client, avremo allora:
[piccardi@gont sources]$ ./daytime 127.0.0.1
Mon Apr 21 20:46:11 2003