Sei sulla pagina 1di 5

Esercizio protocollo di un

'q' 'l' 'r'

SERVER SERIALE

Un server S di tipo seriale e perenne, facente uso della tecnologia di rete TCP/IP, accetta sul port TCP 2200 i seguenti tre comandi di un carattere: chiudi la connessione con il cliente (BLOCCO_DI_CODICE_1) BLOCCO_DI_CODICE_2 es:(esegui un programma locale) lasciare vuoto BLOCCO_DI_CODICE_3 es:(esegui un programma remoto) lasciare vuoto

Si chiede di scrivere il codice C del server S, completando il codice C mostrato nella pagina successiva. IPOTESI Si pu supporre che non si verifichino errori sulle primitive e che il server T risulti sempre attivo e disponibile ad accettare connessioni.

TRACCIA DI SOLUZIONE ALL'ESERCIZIO Codice del server File server.c

#include <stdio.h> / definizioni std. #include <sys/types.h> / definizioni std. #include <sys/socket.h> / definizioni std. #include <netinet/in.h> / definizioni std. / max num. richieste di conn. pendenti #define MAX_PEND_CONN 5 / port TCP per ascolto richieste cliente #define S_SERVER_PORT 2200 / port TCP per invio comandi server T #define T_SERVER_PORT 2200 #define MAX_LUN_STR 256 / max lunghezza di
SEGUE NELLALTRA PAGINA

di funzioni di I/O / per i socket / per i socket / per i socket / / / / una stringa /

pp. 1 / 5

main ( ) { / programma principale char com; / comando ricevuto dal cliente / tampone di memoria per stringhe/comandi char tampone[MAX_LUN_STR]; int i; / variabile intera ausiliaria / socket per la connessione con il cliente int S_sock_fd, S_new_sock_fd; int T_sock_fd; / socket per la connessione con il server T / punti terminali e loro dimensioni struct sockaddr_in S_server, T_server, client; int S_server_len = sizeof(S_server); int T_server_len = sizeof(T_server); int client_len = sizeof(client); addr_initialize(&S_server, htons(S_SERVER_PORT), INADDR_ANY); S_sock_fd = socket(AF_INET, SOCK_STREAM, 0); bind(S_sock_fd, &S_server, S_server_len); listen(S_sock_fd, MAX_PEND_CONN); while (1) { / ciclo perenne del server accetta e serve i clienti
S_new_sock_fd = accept(S_sock_fd, &client, &client_len);

/ / / / /

/ /

/ /

do { / ciclo di ricevimento dei comandi e loro servizio recv(S_new_sock_fd, &com, 1, 0); / analisi del comando ricevuto dal cliente e relativo servizio switch (com) { case l: { // BLOCCO 2

break; / uscita da switch / } / case / case r: { // BLOCCO 3

break; / uscita da switch / } / case / case q: { close(S_new_sock_fd); break; / uscita da switch / } / case / } / switch / } while (com != q); / do / } / while / } / main / pp. 2 / 5

Esercizio bis protocollo di un


Studiare i blocchi di codice dellesercizio precedente.

SERVER SERIALE

Un di tipo seriale e perenne, facente uso della tecnologia di rete TCP/IP, accetta sul port 2200 i seguenti tre comandi di un carattere: 'q' 'l' 'r' BLOCCO_DI_CODICE_1 es:(chiudi la connessione con il cliente) BLOCCO_DI_CODICE_2 es:(esegui un programma locale) BLOCCO_DI_CODICE_3 es:(esegui un programma remoto)

server S

BLOCCO_DI_CODICE_2 Il comando 'l' seguito immediatamente (cio senza spazi interposti) da una stringa (terminata dal carattere '\0') che codifica il nome di un programma eseguibile posto sullo stesso calcolatore su cui sta girando il server S. Per esempio, sia ls\0, dove s una stringa: il server S esegue il programma locale il cui codice eseguibile nel file di nome s e, quando il programma locale terminato, torna ad accettare comandi dal cliente. BLOCCO_DI_CODICE_3 Il comando 'r' seguito immediatamente (cio senza spazi interposti) da due stringhe (ciascuna terminata dal carattere '\0'), che codificano: lindirizzo IP di un altro calcolatore, su cui attivo un secondo programma il nome di un programma che il server T deve eseguire, sul suo calcolatore.

server T;

Il server S si deve collegare al server T utilizzando lindirizzo IP ricevuto e il port 2200, e inviare al server T il comando 'l' seguito dal nome del programma da eseguire (si noti come il server T sia funzionalmente equivalente al server S). Per esempio, sia rs1\0s2\0, dove s1 e s2 sono stringhe: il server S si collega al server T (il cui indirizzo IP la stringa s1) e gli invia il comando ls2\0. Poi il server S deve chiudere la connessione con il server T, senza aspettare che il server T termini l'esecuzione del comando inviatogli, e deve tornare ad accettare comandi dal cliente. IPOTESI Si pu supporre che non si verifichino errori sulle primitive e che il server T risulti sempre attivo e disponibile ad accettare connessioni. Si ricorda che la funzione: u_long inet_addr (char s) converte un indirizzo IP in forma di stringa C (per esempio "131.175.1.2") in un indirizzo IP in formato interno (di solito un intero a 32 bit, dato come tipo u_long).

pp. 3 / 5

int main(){ while (1) { / ciclo perenne del server accetta e serve i clienti do { / ciclo di ricevimento dei comandi e loro servizio / analisi del comando ricevuto dal cliente e relativo servizio switch (com) { case l: {

/ /

break; / uscita da switch / } / case / case r: {

break; / uscita da switch / } / case / case q: { break; / uscita da switch / } / case / } / switch / } while (com != q); / do / } / while / } / main /

pp. 4 / 5

SOLUZIONE (la parte di codice mancate sopra sia quella dellesericizio precedente) while (1) { / ciclo perenne del server accetta e serve i clienti S_new_sock_fd = accept(S_sock_fd, &client, &client_len); do { / ciclo di ricevimento dei comandi e loro servizio recv(S_new_sock_fd, &com, 1, 0); / analisi del comando ricevuto dal cliente e relativo servizio switch (com) { case l: { i = 0; do recv(S_new_sock_fd, &tampone[i], 1, 0); while (tampone[i++] != '\0'); / do / if (fork()== 0) exec(tampone, (char ) NULL); else wait(void); / if / break; / uscita da switch / } / case / case r: { i = 0; do recv(S_new_sock_fd, &tampone[i], 1, 0); while (tampone[i++] != '\0'); / do / addr_initialize(&T_server, htons(T_SERVER_PORT), inet_addr(tampone)); tampone[0] = 'l'; i = 1; do recv(S_new_sock_fd, &tampone[i], 1, 0); while (tampone[i++] != '\0'); / do / T_sock_fd = socket(AF_INET, SOCK_STREAM, 0); connect(T_sock_fd, &T_server, T_server_len, 0); send(T_sock_fd, tampone, strlen(tampone) + 1, 0); close(T_sock_fd); break; / uscita da switch / } / case / case q: { close(S_new_sock_fd); break; / uscita da switch / } / case / } / switch / } while (com != q); / do / } / while / } / main /

/ /

pp. 5 / 5