Alma Mater Studiorum - Universita' di Bologna
Sede di Cesena
II Facolta' di Ingegneria
Reti di Calcolatori
Esercitazione 5
Implementazione del TFTP
tramite RPC
Copyright © 2006-2013 by D. Romagnoli & C. Salati
1
Servizio di file transfer TFTP in C con RPC (su TCP)
• Questa esercitazione richiede l’implementazione di un servizio di file
transfer.
• Il protocollo applicativo utilizzato per fornire questo servizio e’
derivato dal protocollo TFTP.
• In questo caso pero’ il protocollo applicativo e’ realizzato
appoggiandosi all’ASE RPC del Layer di Applicazione.
 ASE RPC = Sun RPC version 2.
 N.B.: l’ASE RPC si appoggia a sua volta al Layer di
Presentazione (XDR) e si interfaccia, in modo nascosto
all’utente, con il Layer di Trasporto.
• Come Servizio di Trasporto si usera’ quello fornito dal protocollo
TCP, e quindi si ignoreranno i problemi legati all’affidabilita’ delle
comunicazioni.
• Assumeremo quindi che le nostre RPC realizzino la semantica
exactly-once senza alcun impegno aggiuntivo da parte del SW
utente per aumentare la robustezza delle comunicazioni.
2
Servizio di file transfer TFTP in C con RPC (su TCP)
• Il linguaggio di programmazione da utilizzare e’ il C.
• Il ruolo di chiamante e’ svolto dal client di file transfer, quello di
chiamato dal server (sequenziale) di file transfer, indipendentemente
dalla direzione di trasferimento dei file (che puo’ cambiare all’interno di
una stessa sessione).
• Bisognera’ quindi definire delle procedure remote che realizzino il
trasferimento secondo le modalita’ previste da TFTP.
• N.B.: utilizzando l’RPC in forma confermata/sincrona la finestra di
trasmissione e’ automaticamente di dimensione 1.
• L’invocazione/ritorno delle singole procedure e i relativi parametri di
ingresso e uscita sostituiranno l’invio esplicito di PDU.
• Ovviamente procedure e relativi parametri devono essere definiti in
modo opportuno.
• Per la definizione del protocollo TFTP vedi esercitazioni 3 e 4.
• N.B.: il protocollo TFTP su RPC non e’ definito completamente solo
dalla definizione dell’interfaccia RPC: bisogna anche definire il
comportamento di ciascuna procedura e quale e’ la sequenza legittima
3
delle procedure che il lato client puo’/deve chiamare sul lato server.
PDU del protocollo TFTP: mappa di byte
read-request
(RRQ)
write-request
(WRQ)
data
(DAT)
Acknowledgment
(ACK)
error
(ERR)
opcode
string
EOS
string
EOS
01
filename
0
mode
0
2 bytes
n bytes
1 byte
n bytes
1 byte
opcode
string
EOS
string
EOS
02
filename
0
mode
0
2 bytes
n bytes
1 byte
n bytes
1 byte
opcode
03
block#
data
2 bytes
2 bytes
n bytes, 0 <= n <= 512
opcode
04
block#
2 bytes
2 bytes
opcode
string
EOS
05
errcode
errstring
0
2 bytes
2 bytes
n bytes
1 byte
4
Come non definire il protocollo
• In XDR avevamo definito il PDU come
union TftpMsg switch (OpType opType) {
case RRQ:
RrqAndWrqMsg rrqMsg;
case WRQ:
RrqAndWrqMsg wrqMsg;
case DAT:
DatMsg
datMsg;
case ACK:
AckMsg
ackMsg;
case ERR:
ErrMsg
errMsg;
}; /* tipo XDR per generico PDU tra client e server */
• Per cui potremmo definire una interfaccia (programma in terminologia
RPC Sun) contenente una unica procedura che ha un parametro di
tipo TftpMsg sia in ingresso che in uscita.
program TFTP_PROG {
version TFTP_VERS {
TftpMsg TFTP_PROC(TftpMsg)
} = 1;
} = 0x20000001;

= 1;
Ma questo (limitarsi a utilizzare RPC solo per fare viaggiare dei
PDU che sarebbero interpretati come nell’esercitazione 4!) e’
proprio quello che non bisogna fare!
5
Come definire il protocollo
• Bisogna sfruttare appieno le possibilita’ offerte da RPC.
• Che cosa si vuole che una procedura faccia non lo dice tanto un
parametro di ingresso (o una sua parte) quanto il nome della
procedura.
• Tante operazioni diverse, tante procedure diverse, ciascuna con
parametri specifici, adatti ad essa.
• Decidere quante e quali procedure definire e’ parte essenziale
dell’esercitazione.
• Esempio:
• Ci deve essere una procedura specifica per inviare un blocco di
byte durante il trasferimento del file da client a server.
• Come parametro di ingresso questa procedura prevedera’ di
avere un blocco di byte (ed eventualmente un sequence number).
• Come parametro di ritorno questa procedura prevedera’ di avere
un valore che indica se il trasferimento/scrittura del blocco e’
avvenuto con successo (con eventualmente il sequence number)
o con errore (con il motivo dell’errore).
6
Come definire le procedure
• Ci sono due operazioni di trasferimento file (a livello di applicazione
utente):
• “get” per l’operazione di download di un file da server a client.
• “put” per l’operazione di upload di un file da client a server.
Per ciascuna di queste operazioni dovra’ essere definita una
procedura RPC capace di darle inizio (e una procedura locale nella
protocol entity TFTP client per eseguire tutta l’operazione).
• Essendoci due direzioni di trasferimento ci devono essere due
funzioni RPC:
• una per trasferire dei byte da client a server,
• una per trasferire dei byte da server a client.
 N.B.: anche l’operazione di trasferimento di byte da server a
client deve essere attivata dal client!
• Il client dovra’ avere a disposizione anche una funzione che gli
consenta di segnalare un errore verso il server.
• Il server dovra’ utilizzare il valore di ritorno anche per informare il
client di eventuali situazioni di errore.
7
Servizio applicativo TFTP vs. protocol entity TFTP
• Come nel caso dell’esercitazione 3, quello che si chiede di implementare e’
• sia il protocollo applicativo (di Layer 7) TFTP, lati client e server,
• che due moduli, client e server, di applicazioni utente TFTP.
• I due diversi layer dovrebbero essere mantenuti il piu’ possibile separati.
• In questo caso, pero’, le protocol entity TFTP dovranno essere implementate
utilizzando il supporto RPC (avendo cioe’ definito tramite RPC le interazioni tra
le due protocol entity TFTP).
• La struttura delle due applicazioni client e server deve quindi essere:
User Application
RPC based
TFTP Protocol Entity
RPC Middleware
Presentation
Layer
TSAP
Transport Layer
• I Layer di Trasporto e di Presentazione
non e’ che non ci siano, ma sono
nascosti alla protocol entity TFTP e
all’applicazione utente dall’infrastruttura
RPC.
• La protocol entity TFTP sara’ composta:
• Lato client da due procedure, get()
e put(), che utilizzano le RPC del
protocollo.
• Lato server dalla implementazione
delle RPC del protocollo.
8
Specifiche per il client
1. Le specifiche per l’applicazione utente lato client sono
sostanzialmente le stesse utilizzate per le esercitazioni 3 e 4.
2. Ovviamente in questo caso, a differenza che nelle esercitazioni 3 e 4,
il client recuperera’ dalla stringa di lancio solo l’indirizzo IP:
 La porta del servizio RPC-TFTP sara’ scoperta e collegata tramite
chiamata a clnt_create(), e conseguente interazione con il
Port Mapper locale alla macchina server.
 L’esecuzione dell’operazione clnt_create()marchera’ anche
l’inizio della sessione di trasferimento file dal punto di vista
dell’applicazione client.
3. Notare che, per come e’ stata definita l’applicazione client, questa
mettera’ in esecuzione una unica operazione di file transfer per volta.
4. L’applicazione client gestisce una nozione di sessione legata alla
connessione TCP con il server, ma questa nozione e’ invisibile per
l’applicazione server che non ha visibilita’ dello stato del Layer di
Trasporto.
 L’applicazione client termina, dal suo punto di vista, la sessione di
trasferimento file tramite chiamata della funzione
9
clnt_destroy().
Specifiche per il server
.1
1. Il lato server deve contenere la definizione delle procedure remote
che implementano il protocollo TFTP.
2. Come gestire i problemi di concorrenza tra eventuali richieste da parte
di diversi client?
 N.B.: lo skeleton server RPC garantisce la sequenzialita’ di
esecuzione delle singole RPC, ma chiamate provenienti da
diversi client possono inframmischiarsi.
• Sostanzialmente si deve realizzare un server sequenziale.
• Per fare questo si devono rifiutare nuove richieste di trasferimento
file una volta che ne sia in corso uno.
Il server deve pero’ gestire anche una nozione di sessione
analoga a quella definita nell’esercitazione 4.
• Una sessione di file transfer viene considerata chiusa (in modo
normale) dal server se, esaurito il trasferimento di un file, passa
un tempo “abbastanza” lungo (dimensione definita staticamente)
senza che il client richieda il trasferimento di un altro file.
 Il server dovra’ quindi mantenere annotato quando e’
10
terminato l’ultimo trasferimento file.
Specifiche per il server
.2
1. Il protocollo TFTP deve essere esteso per gestire esplicitamente la
nozione di sessione tra client e server:
• Ogni richiesta di operazione del client deve trasportare un ID di
sessione che consenta al server di verificare se quella richiesta e’
relativa alla sessione correntemente attiva.
• Il client marchera’ la prima richiesta di una sessione (una richiesta
di inizio upload o download) con ID=0.
• Quando il server accetta di iniziare una sessione con un client gli
assegna un ID univoco di sessione 0. Questo ID e’ ritornato al
client nella risposta di tutte le operazioni, e non solo della prima.
• Tutte le successive richieste del client relative alla stessa sessione
devono essere marcate con quell’ID.
• Il server rifiutera’ l’esecuzione di operazioni marcate con un ID
diverso da quello della sessione corrente.
2. Su indicazione di errore da parte del client il server interrompe il
trasferimento in corso e la sessione e si mette in attesa di una nuova
11
richiesta di inizio trasferimento/sessione da parte di un client.
Specifiche per il server
.3
1. Anche nel caso sia lui a generare una risposta di errore per il client,
il server dovra’ considerare terminato il trasferimento in corso e la
sessione corrente.
2. Il server deve considerare abortito un trasferimento file anche se per
troppo tempo (dimensione definita staticamente) non ha ricevuto dal
client attivo in quel momento chiamate di procedure che lo facessero
progredire nel trasferimento.
 Nel caso di abort di un trasferimento il server considera abortita
anche la sessione di cui esso fa parte.
 Il server dovra’ quindi mantenere annotato quando e’ avvenuta
l’ultima operazione del trasferimento in corso.
3. Il controllo di esaurimento timeout deve essere effettuato all’inizio
dell’esecuzione di ogni operazione e determina quello che e’ lo stato
corrente del server.
4. All’interno di una sessione un client non puo’ chiedere l’inizio di un
trasferimento se non ha gia’ terminato il trasferimento precedente:
se lo fa, cio’ e’ considerato un errore di protocollo e porta all’abort 12
del trasferimento gia’ in corso e alla terminazione della sessione.
Specifiche per il server
.4
• Quando il server riceve una chiamata di attivazione di un trasferimento
deve quindi verificare il suo stato e rispondere di conseguenza:
1. Se in quel momento non e’ attiva nessuna sessione e questa e’ la
prima richiesta di una nuova sessione (il suo ID e’ =0), accetta la
richiesta, attiva una nuova sessione e da’ il via al trasferimento.
2. Se in quel momento non e’ attiva nessuna sessione e questa non
e’ la prima richiesta di una nuova sessione (il suo ID e’ 0), rifiuta
la richiesta.
3. Se in quel momento e’ attiva una sessione e questa e’ la prima
richiesta di una nuova sessione (il suo ID e’ =0), rifiuta la richiesta.
4. Se in quel momento e’ attiva una sessione e questa richiesta e’
relativa ad una sessione diversa da quella corrente, rifiuta la
richiesta.
5. Se in quel momento e’ attiva una sessione, non e’ attivo nessun
trasferimento e questa richiesta e’ relativa alla sessione corrente,
accetta la richiesta e da’ il via al trasferimento.
13
Specifiche per il server
.5
• Quando il server riceve una chiamata di attivazione di un trasferimento
deve quindi verificare il suo stato e rispondere di conseguenza:
1. Se in quel momento e’ attivo un trasferimento e questa richiesta e’
relativa alla sessione corrente, questo e’ un errore di protocollo.
2. Se in quel momento e’ attivo un trasferimento, e questa richiesta
non e’ la prima richiesta di una nuova sessione (il suo ID e’ 0) ed
e’ relativa ad una sessione diversa da quella corrente, rifiuta la
richiesta.
3. Se in quel momento e’ attivo un trasferimento e questa e’ la prima
richiesta di una nuova sessione (il suo ID e’ =0)
• Se e’ passato troppo tempo dall’ultima operazione relativa al
trasferimento in corso, lo abortisce e abortisce la sessione
corrente e accetta la richiesta: da’ il via ad una nuova sessione
e ad un nuovo trasferimento.
• Se non e’ passato abbastanza tempo dall’ultima operazione
relativa al trasferimento in corso, rifiuta la nuova richiesta di
14
inizio trasferimento.
Specifiche per il server
.6
• Quando e’ in corso un trasferimento file il server deve verificare
l’eventuale spirare del timeout di trasferimento per ogni operazione
richiesta dal client correntemente attivo (cioe’ le cui richieste sono
marcate con un ID uguale a quello della sessione in corso).
• Quando e’ in corso un trasferimento file qualunque richiesta da parte di
un cliente diverso da quello correntemente attivo che non sia di inizio
di un trasferimento costituisce una violazione di protocollo.
• E’ ovvio che l’unico tipo di richiesta che puo’ essere legittimamente
marcato con ID=0 e’ quello di inizio di trasferimento file (upload o
download).
• Il server si puo’ trovare in 3 stati:
1. Nessuna sessione attiva
2. Sessione attiva, nessun trasferimento in corso
3. Sessione attiva, trasferimento in corso
• Il server dovrebbe evitare di compiere sul file in corso di trasferimento
operazioni inutili e ridondanti, come apertura, posizionamento e
chiusura per ogni blocco trasferito.
15
 Ci si deve basare sul fatto che si opera sequenzialmente.
Acquisizione dell’istante corrente
• Si e’ visto che molte operazioni del server dipendono dall’intervallo di tempo
che intercorre tra la ricezione di una chiamata di RPC e quella successiva.
• Per misurare questo intervallo di tempo si puo’ utilizzare la system call
gettimeofday() (vedi http://linux.die.net/man/2/gettimeofday):
#include <sys/time.h>
int gettimeofday(struct timeval *tv,
struct timezone *tz);
The function gettimeofday() can get the time as well as a timezone.
The tv argument is a struct timeval (as specified in sys/time.h):
struct timeval { time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */ };
and gives the number of seconds and microseconds since the Epoch (1970-0101 00:00:00 +0000 (UTC)).
The tz argument is a struct timezone:
struct timezone { int tz_minuteswest;
int tz_dsttime; };
If either tv or tz is NULL, the corresponding structure is not returned.
The use of the timezone structure is obsolete: the tz argument should be
specified as NULL.
16
Diagnostici e tracciamenti
• E’ opportuno prevedere l’abilitazione/disabilitazione di diversi livelli di
tracciamento (e.g. procedura remota attivata, parametri di ingresso e
uscita):
 cio’, lato client, puo’ essere fatto facilmente passando un
opportuno parametro nella stringa di lancio.
• La cosa si applica pero’ sia lato client che lato server.
• Lato server la cosa e’ particolarmente significativa per poter
controllare la correttezza della gestione della concorrenza delle
interazioni con i client.
 Dovrebbero essere verificate tutte le condizioni di terminazione di
un trasferimento e di una sessione, sia di successo che di errore.
 Dovrebbe essere verificata la gestione, da parte del server, di
richieste concorrenti di diversi client.
• Lato server l’introduzione di parametri nella stringa di attivazione puo’
sembrare non immediata:
 In realta’ si tratta solo di introdurre qualche semplice modifica nel
17
testo dello skeleton generato da rpcgen.
Generazione del codice eseguibile
.1
• Per compilare la sintassi astratta dare il comando (si assume che la
sintassi astratta sia contenuta nel file tftp.x):
rpcgen –C tftp.x
che produce 4 file:
• tftp.h
che deve essere incluso nei file sorgente del vostro
programma, sia lato client che lato server.
• tftp_xdr.c
che deve essere compilato e linkato sia al programma client
che a quello server.
• tftp_clnt.c
che deve essere compilato e linkato al programma client.
• tftp_svc.c
che deve essere compilato e linkato al programma server.
18
Generazione del codice eseguibile
.2
• Per la compilazione del client:
gcc –g client.c tftp_xdr.c tftp_clnt.c –o client
• Per la compilazione del server:
gcc –g server.c tftp_xdr.c tftp_svc.c–o server
• Si e’ fatta l’ipotesi che i file tftp.x, client.c e server.c siano tutti nella
stessa directory.
• L’output della compilazione/link saranno i 2 eseguibili client e
server.
19
Scarica

server - Dipartimento di matematica e informatica