1
Capitolo 2
BitTorrent Protocol v. 1.0
2.1 - Introduzione
BitTorrent [12] è un protocollo peer-to-peer di file sharing, progettato in Python da Brahm Cohen nel 2002 con lo scopo di facilitare la diffusione di file di grosse dimensioni attraverso reti inaffidabili.
Con il termine BitTorrent si identifica una rete P2P per la diffusione di un file, le specifiche del protocollo e un’applicazione client che ne fa uso.
Il protocollo BitTorrent prevede l’organizzazione di una overlay network per ogni file che si vuole diffondere.
La distribuzione di file di grosse dimensioni comporta due problemi fondamentali:
• tutto l’onere del trasferimento del file risiede sulla macchina che lo possiede;
• la maggioranza delle linee degli utenti dei sistemi P2P sono linee asimmetriche (più banda dedicata al download che all’upload), quindi anche nel caso di due utenti con la stessa connessione essi, anche volendo cooperare, non potranno mai scaricare sfruttando tutta la loro banda di download disponibile perché l’uplink del loro partner risulterà essere il bottleneck della rete;
L’idea principale alla base del protocollo BitTorrent è quella di redistribuire il carico dell’upload su tutti i computer che concorrono alla diffusione del file (Multi-source download).
Tale obiettivo è raggiunto dividendo l’intero file in sottoparti, che, dopo essere state scaricate da un utente, cominceranno ad essere fornite agli altri alleggerendo di fatto il carico del possessore dell’intero file e permettendo, così, un maggiore sfruttamento della banda di download.
2
Figura 2.1: Multi-source download
2.2 - Convenzioni
Affinché la successiva trattazione risulti il più possibile chiara si introducono alcune definizioni:
• peer vs client: i peers sono utenti che scambiano dati tramite il protocollo
BitTorrent; il client è, invece, il programma in esecuzione sulla macchina dell’utente che implementa il protocollo. Esso opera insieme al sistema operativo e gestisce le interazioni tra il tracker e i peers;
3 • piece vs block: il piece è una porzione del file da scaricare tipicamente della
dimensione di 256 kB, descritta nel metainfo file, e che può essere verificata tramite funzioni hash SHA1; il block, invece, è una sottoparte del piece della dimensione, in genere, di 16 kB. Uno o più blocchi formano un intero piece che verrà successivamente verificato. Tale ulteriore divisione viene fatta per diminuire i tempi di attesa tra due invii successivi;
• seeder o seed: peer che possiede tutte le parti di un file;
• leecher: peer che possiede qualche o nessuna parte di un file e che cerca di
completarlo;
• tracker: entità intermedia che informa il client dei peers connessi all’overlay
network interessata;
• swarm: insieme di tutti i peers, compreso il client, che sono interessati al
determinato file;
• ottimo paretiano: è una condizione che si realizza quando l’allocazione delle
risorse è tale che non è possibile migliorare la condizione di un soggetto senza peggiorare quella di un altro;
• bencode: è un modo di specificare e organizzare i dati in maniera coincisa. Tale
codifica supporta stringhe di byte, interi, liste e dizionari;
• torrent o Metainfo file: file contente tutte le informazioni relative al contenuto
che si intende condividere. Al suo interno sono specificati i seguenti campi nel formato bencode:
• info: dizionario che descrive i file del torrent. Vi sono due possibili
formati, uno nel caso di un single-file torrent e uno nel caso di multi-file torrent. I campi comuni ad entrambe le modalità sono:
piece length (dimensione in byte di ogni piece), pieces ( stringhe
contenenti i valori hash SHA1 di ogni piece) e private ( intero che permette di stabilire se il client ottiene la lista dei peers solamente attraverso il tracker specificato nel metainfo file o anche attraverso altre modalità);
4 • announce-list: (opzionale) estensione della specifica originale usata
per implementare una lista di tracker di backup;
• creation date: (opzionale) istante di creazione del torrent; • comment: (opzionale) commenti dell’autore in formato testo; • created by: (opzionale) nome e versione del programma utilizzato
per la creazione del file .torrent;
2.3 - Principio di funzionamento
In figura 2.3 è illustrato il principio di funzionamento del protocollo BitTorrent che andremo ad analizzare in dettaglio distinguendo quattro fasi principali:
5
2.3.1 – Fase Iniziale
Il primo passo che si deve compiere se si è interessati a scaricare un determinato file, tramite l’applicazione BitTorrent, è quello di ottenere da un webserver il relativo file con estensione .torrent detto Metainfo file. Successivamente si passa all’esecuzione di questo file avviando il client BitTorrent.
2.3.2 – Comunicazione con il tracker
In secondo luogo verrà contattato il tracker indicato all’interno del torrent. Il tracker fornisce un servizio HTTP/HTTPS che risponde ad una richiesta HTTP GET.
Il tracker è usato per gestire la partecipazione degli utenti nel torrent (noti come peers). Esso memorizza statistiche riguardanti il torrent ma il suo compito principale è quello di permettere ai peers di “trovarsi” reciprocamente e di iniziare la comunicazione. I peers non hanno nessuna informazione riguardo gli altri partecipanti finché non ricevono una risposta dal tracker. Quando un peer contatta il tracker esso comunica quali piece del file possiede (fase di registrazione). In questo modo quando i peer interrogano il tracker esso restituisce una lista, ordinata in maniera random, di peers che stanno partecipando al torrent e che possiedono il piece richiesto.
6
La richiesta include delle metriche che aiutano il tracker a mantenere delle statistiche generali sul torrent. Le risposte includono una lista di peers che permette al client di partecipare alla condivisione del file.
Nelle richieste al tracker da parte dei clients vengono forniti, fra gli altri, i seguenti parametri:
• info_hash: stringa di 20 byte ottenuta applicando la funzione hash SHA1 al campo info del Metainfo file;
• peer_id: identificativo univoco del client generato in fase di startup; • port: numero della porta su cui è in ascolto il client;
• uploaded: quantità di dati spediti dall’invio di un messaggio di tipo started; • downloaded: quantità di dati scaricati dall’invio di un messaggio di tipo started; • left: numero di byte che il client deve ancora scaricare;
• event: questo campo, se specificato, deve valere started, completed o stopped; • ip: (opzionale) indirizzo IP della macchina su cui è attivo il client. Viene usato
se il client comunica con il tracker attraverso un proxy server altrimenti è omesso e l’indirizzo IP viene ottenuto direttamente dalla richiesta http;
• numwant: (opzionale) numero di peers che il client vuole ricevere dal tracker. Se
non specificato tale numero è tipicamente 50;
• key: (opzionale) un identificativo aggiuntivo non condiviso con gli altri utenti
che permette al client di identificarsi se dovesse cambiare il suo indirizzo IP.
La risposta del tracker contiene invece i seguenti campi:
• failure reason: è un messaggio di errore che spiega perché la richiesta non viene
processata. Se presente è l’unico campo previsto;
• warning message: (opzionale) messaggio simile al precedente. In questo caso
viene notificato l’errore ma il messaggio è comunque processato;
• min interval: (opzionale) intervallo minimo per una nuova richiesta;
• tracker id: stringa che il client deve spedire nella successiva richiesta. Se non è
presente si usa quella spedita nella precedente;
7 • incomplete: numero di peers che non possiedono l’intero file (leechers);
• peers: (dizionario) è una lista di dizionari ognuno dei quali è caratterizzato da un
identificativo, un indirizzo IP e una porta;
• peers: (binario) invece di usare un dizionario si può usare una stringa binaria
avente una dimensione multipla di 6 byte, dei quali, i primi 4 rappresentano l’indirizzo IP e gli ultimi 2 il numero di porta;
Come si è già accennato la lista di peers restituita dal tracker è costituita da 50 elementi di default scelti dal tracker in maniera random. Il tracker può scegliere di implementare un meccanismo di selezione dei peers più intelligente, per esempio, evitando di indicare ai seed quei peers che possiedono anch’essi l’intero file.
I clients possono spedire richieste al tracker più frequentemente rispetto all’intervallo specificato se si verifica un determinato evento (stopped o complete) o se hanno la necessità di incrementare la lista di peers che possiedono. Rimane comunque buona norma non sovraccaricare il tracker di richieste e utilizzare il campo numwant se si vuole ottenere una lista di peers più lunga.
2.3.3 – Instaurazione connessioni
Ottenuta la lista dei peers che partecipano allo swarm il client instaura con ognuno di essi una connessione Tcp bidirezionale e da inizio alla fase dello scambio dei dati. Il client BitTorrent utilizza, in genere, le porte TCP 6881-6999. Per trovare una porta disponibile, il client sceglierà, inizialmente, quella con il numero più basso procedendo fino a trovarne una che potrà essere utilizzata. Ciò significa che il client BitTorrent userà solamente una porta e per eseguirne un altro se ne dovrà scegliere una diversa. Quando un peer riceve una richiesta per un determinato piece da parte di un altro peer, esso può rifiutarsi di offrirlo. Se ciò accade si dice che tale peer è choked (soffocato). Ciò è dovuto principalmente al fatto che, di default, il client mantiene un prefissato numero di upload simultanei, di conseguenza le future richieste saranno “soffocate” (algoritmo di unchoking).
8
In virtù di tale comportamento il client deve mantenere delle informazioni di stato per ogni connessione creata con gli altri peers remoti. Tali informazioni sono specificate dal valore delle seguenti variabili:
• choked: indica se il client è, o no, “soffocato” dal peer remoto con cui sta
comunicando. Quando un peer “soffoca” il client vuole notificare che non risponderà a nessuna richiesta da parte di quest’ultimo finché esso non sarà unchoked (sbloccato). Il client, in questo caso, non dovrebbe tentare di inviare richieste per i blocchi e dovrebbe considerare che tutte le richieste pendenti saranno ignorate dal peer;
• interested: indica se il peer è, o no, interessato a uno o più piece posseduti dal
client. Se il peer si trova in questo stato esso inizierà a richiedere blocchi non appena sarà unchoked dal client;
Il client dovrà tenere traccia oltre che del suo interesse nei confronti del peer remoto anche del comportamento di quest’ultimo nei suoi confronti. Quindi la lista reale risulterà essere del tipo:
• am_choking: il client sta “soffocando” il peer;
• am_interested: il client è interessato ai contenuti posseduti dal peer; • peer_choking: il peer sta “soffocando” il client:
• peer_interested: il peer è interessato ai contenuti del client;
All’instaurazione della connessione il client risulterà di default choked e not interested:
• am_choking = 1;
• am_interested = 0;
• peer_choking = 1;
9
Un blocco è scaricato dal client quando esso risulta interessato al peer e tale peer non lo sta soffocando. Un blocco è uplodato dal client quanto il client non sta soffocando il peer e tale peer è interessato al client.
2.3.4 – Messaggi e scambio dati
Il primo messaggio che viene inviato dal client è un messaggio di richiesta detto di handshake. Esso ha una lunghezza di 49 byte a cui va aggiunta la lunghezza della stringa che identifica il protocollo:
handshake:<pstrlen><pstr><reserved><info_hash><peer_id>
• pstrlen: lunghezza di pstr in un singolo byte; • pstr: stringa che identifica il protocollo;
• reserved: 8 byte riservati. Tutte le correnti implementazioni usano 8 zeri.
Ogni singolo bit può essere usato per cambiare il comportamento del protocollo;
• info_hash: 20 byte che rappresentano il valore hash SHA1 del campo
info del Metainfo file (stesso campo presente nelle richieste al tracker);
• peer_id: 20 byte che identificano univocamente il client (stesso campo
presente nelle richieste al tracker);
Nella versione 1.0 del protocollo BitTorrent il campo psrtlen vale 19 mentre la stringa pstr vale “BitTorrent protocol”.
L’iniziatore della connessione trasmette immediatamente il proprio handshake mentre il peer dall’altro lato della connessione può attendere se è in grado di servire torrent multipli simultaneamente e, non appena ciò accade, deve rispondere. Se un client riceve un messaggio di handshake con un valore del campo info_hash non corretto allora può abbattere la connessione. Allo stesso modo si comporta l’iniziatore della connessione se riceve un handshake nel quale il campo peer_id non corrisponde al valore aspettato. Si
10
può notare che l’iniziatore della connessione riceve le informazioni sul peer dal tracker, tali informazioni comprendono il peer_id che è stato registrato presso quest’ultimo. Ci si aspetta che il peer_id fornito dal tracker e quello presente nell’handshake coincidano.
Tutti i messaggi successivi sono nella forma:
<length prefix><message ID><payload>
il campo length prefix è costituito da 4 byte nel formato big-endian, il message ID è costituito da un singolo byte in formato decimale mentre il payload dipende dal tipo di messaggio.
Dopo che la sequenza di handshaking è stata completata e prima che ogni altro messaggio sia scambiato viene immediatamente inviato un messaggio di tipo bitfield. Esso è opzionale e, nel caso in cui il client non possieda nessun piece, non è necessario spedirlo. Tale messaggio si presenta nella forma:
bitfield:<len=0001+X><id=5><bitfield>
esso ha una lunghezza variabile e dipendente dal fattore X che indica la lunghezza del campo bitfield. Il payload rappresenta i pieces posseduti dal peer che ha inviato il messaggio. Il bit più significativo del primo byte corrisponde al piece di indice 0 e ogni singolo bit specifica se il determinato piece è posseduto (1) o meno (0) dal peer.
Completato lo scambio di bitfield tra i peers in comunicazione, cominciano le richieste dei pieces mancanti attraverso messaggi di request che si presentano nella forma:
request:<len=0013><id=6><index><begin><length>
tale messaggio ha una lunghezza fissa e nel suo payload troviamo le informazioni riguardanti il piece richiesto.
11
Se un peer è in grado di esaudire una richiesta passa alla fase di upload del piece indicato in quest’ultima inviando un messaggio di tipo piece.
piece:<len=0009+X><id=7><index><begin><block>
esso ha una dimensione variabile che dipende da quella del blocco del piece (X) che è stato selezionato. Nel payload troviamo gli indici relativi al piece scelto e il vero e proprio blocco di dati.
Appena un piece è stato scaricato viene controllato tramite il valore hash e la sua ricezione è notificata alla maggior parte dei peers connessi al client con l’invio di un messaggio di have avente lunghezza prefissata.
have:<len=0005><id=4><piece index>
Se in seguito ad un particolare avvenimento un client non è più interessato ad un blocco di cui aveva fatto richiesta invia un messaggio di cancel di dimensione fissa e avente il campo payload uguale a quello della relativa richiesta:
cancel:<len=0013><id=8><index><begin><length>
Un altro dei messaggi scambiati è quello di keep-alive:
keep-alive:<len=0000>
questo messaggio ha una lunghezza di 0 byte ed è specificato dai quattro byte del campo prefix settati tutti a 0. Non contiene né message ID né payload. I peers che non ricevono nessun messaggio entro un certo periodo di tempo possono abbattere la connessione; i keep-alive devono essere quindi spediti per mantenere la connessione attiva se non sono stati spediti comandi per un dato lasso di tempo, tipicamente due minuti.
12
I seguenti messaggi invece servono per poter aggiornare le informazioni di stato della connessione. Sono tutti messaggi di lunghezza fissa caratterizzati dall’assenza di payload. choke:<len=0001><id=0> unchoke:<len=0001><id=1> interested:<len=0001><id=2> not interested:<len=0001><id=3>.
2.4 – Tecniche e Algoritmi
Illustriamo nel seguito le tecniche introdotte per migliorare le performance del protocollo BitTorrent [13]:
2.4.1 – Pipelining
Questa è una tecnica che permette di aumentare la velocità di download quando si trasferiscono dati attraverso il protocollo TCP, come avviene nel caso dell’applicazione BitTorrent. I peers mantengono in coda un certo numero di richieste non soddisfatte per ogni connessione. Si opera in questo modo perché, in caso contrario, sarebbe necessario attendere un intero round trip time (RTT) tra il download di due blocchi successivi (round trip time tra il messaggio di piece che notifica la ricezione del blocco e la successiva richiesta). In link con un elevato bandwidth-delay-product (BDP) ciò comporterebbe una sostanziale perdita di prestazioni.
Il BitTorrent permette ciò segmentando i pieces in sottoparti (blocchi), tipicamente di 16KB, e mantenendo un certo numero di richieste, generalmente 5, accodate. Ogni qualvolta un blocco è stato ricevuto una nuova richiesta è inviata.
13
2.4.2 – Super-Seeding mode
Questo algoritmo non faceva parte delle specifiche originali ed è stato introdotto solo nelle versioni successive con l’intento di aiutare quei seeds che possiedono un file di grosse dimensioni da condividere ma non dispongono di una elevata banda di upload. Con tale algoritmo si riduce la quantità di dati che il seed deve inviare affinché vi siano nuovi seeds nello swarm.
Quando un client entra in questa modalità non si comporterà più come un normale seed ma si maschererà da un normale client che non possiede dati. Alla connessione di nuovi clients il super-seed li informerà di aver ricevuto un piece, un piece che non è mai stato spedito o che risulta essere il più raro se tutti i pieces sono già stati spediti. Questo comportamento indurrà i clients a cercare di scaricare solamente il piece indicato. Appena il client ha finito il download di tale piece il seed non lo informerà degli altri pieces che possiede finché non verrà a conoscenza che quello precedentemente inviato è posseduto da almeno un altro client. Fino ad allora il client non avrà accesso a nessuno altro piece del seed e quindi non ne sprecherà la banda.
L’introduzione di questo algoritmo ha permesso di migliorare l’efficienza del protocollo inducendo i peers a scaricare solo i pieces più rari, riducendo l’invio di dati ridondanti e limitando la quantità di dati che vengono forniti ai peers che non contribuiscono allo swarm. Prima del suo utilizzo un peer doveva inviare una quantità di dati compresa fra il 150% e il 200% della dimensione totale del torrent affinché un altro client diventasse seed. Grazie alla modalità super seeding lo stesso client invierà solamente circa il 105% per ottenere lo stesso risultato.
Tale modalità non è comunque consigliata per una situazione generica. Infatti pur fornendo un aiuto concreto nella diffusione dei dati più rari, limitando la scelta del piece che i clients possono scaricare, limita l’abilità di quest’ultimi di completare quei pieces di cui possiedono già una parte. Di conseguenza tale modalità è consigliata solamente nella fase iniziale di diffusione di un nuovo contenuto.
14
2.4.3 – Piece selection
L’algoritmo di selezione delle parti da scaricare è di fondamentale importanza per ottenere delle buone prestazioni del sistema. Adoperando scelte sbagliate infatti si corre il rischio di arrivare ad una situazione in cui tutte le parti del file che un client offre non siano richieste da nessun altro peer.
Di conseguenza si ricerca una rigida politica per il downalod dei pieces che compongono il file.
La specifica originale del protocollo prevede che i clients possano scaricare i pieces in maniera puramente random ma successivamente [] sono state introdotte altre tecniche per migliorare le prestazioni. L’uso di queste tecniche dipende dalla quantità di dati posseduta dai peers al momento della scelta. Le tecniche introdotte sono nel dettaglio:
Strict priority:
è la prima politica utilizzata dal BitTorrent; se un singolo blocco di un determinato piece è stato richiesto, le rimanenti sotto parti di questo particolare piece avranno la precedenza rispetto alle richieste relative ad un nuovo piece. Questa tecnica permette di completare il più velocemente possibile parti intere del file.
Consideriamo l’esempio illustrato in figura 2.5. Il file che si sta condividendo è stato suddiviso in 8 parti ognuna delle quali è costituita da 6 blocchi. Lo swarm, per semplicità, si considera composto da due soli peers: il peer A che è un seed e quindi possiede l’intero file e il peer B che è un leecher e possiede solamente i pieces 2 e 3 completi e il primo blocco del piece 1. Prima di poter richiedere blocchi appartenenti a qualsiasi altro piece, il peer B, se è applicata la strategia strict priority, dovrà completare il piece incompleto.
15
Figura 2.5 – Strict priority
Rarest First (RF):
quando il peer seleziona quale nuovo piece scaricare sceglie sempre quello con la minore occorrenza all’interno dello swarm. Questa regola di comportamento permette al peer di essere concorrenziale. Il possesso di parti di file molto richieste gli permette di scambiarle più facilmente ricevendone in cambio delle altre. Operando in questa maniera si alleggerisce di molto il carico sul seeder originario specialmente nel momento in cui si introduce un nuovo torrent.
Il client può determinare il piece più raro mantenendo le informazioni ricevute durante lo scambio dei bitfield con gli altri peers e aggiornandole alla ricezione di ogni messaggio di have. Così il client potrà richiedere il piece che ha il minor numero di occorrenze.
Va notato che ogni strategia del tipo Rarest First dovrebbe includere anche un meccanismo di scelta random tra i pieces meno comuni per evitare che tutti i peers finiscano per richiedere lo stesso piece più raro rendendo meno produttiva questa tecnica.
Nella figura 2.6 è presentato un esempio di selezione dei pieces più rari. In questo caso si è considerato uno swarm composto da 5 peers, all’interno del quale si possono distinguere un seed e quattro leechers. Facendo riferimento all’esempio precedente, il
16
peer B, dopo aver completato il download del piece 1, dovrà scegliere quale piece richiedere successivamente. Dal momento che esso è in possesso dei bitfield relativi ai peers A, C, D ed E (rappresentati in figura dai vettori composti da 1 e 0) potrà andare a calcolare il numero di occorrenze all’interno dello swarm per ognuno dei pieces che non possiede. In dettaglio noterà che: i pieces 4 e 6 sono posseduti da tre peers (A,C,E), quelli numero 5 e 7 da due peers (A,D), mentre il piece numero 8 è in possesso solo del peer A. Di conseguenza la scelta ricadrà su quest’ultimo piece, il quale risulta quello più raro all’interno dello swarm.
17 Random first:
l’unica eccezione alla regola del rarest first è concessa quando si inizia il download di un file e il peer non è in posseso di nessun piece. In questa situazione è probabile che le parti più rare del file siano in possesso di pochi peers e, se si applicasse la politica RF, il download risulterebbe rallentato. Di conseguenza la prima parte da scaricare viene scelta in maniera casuale e solo dopo il completamento del download di questa si applica la RF.
Va notato che è importante che un leecher inizi il prima possibile ad inviare i blocchi che possiede in quanto la sua velocità di download dipende da quella di upload. Quindi quando un client non è in possesso di nessun blocco da distribuire è preferibile che adotti un algoritmo che gli permetta rapidamente di avere un piece completo da scambiare.
Endgame mode:
in alcune situazioni un piece può essere richiesto da un peer con una capacità di trasferimento molto bassa. Tale situazione non provoca problemi particolari nella fase intermedia del download del file ma può risultare potenzialmente dannosa quando esso è prossimo al termine. La fase di completamento del download si può rendere più veloce se il client inoltra in broadcast la richiesta degli ultimi blocchi a tutti i peers a cui è connesso. Per evitare che questa situazione diventi inefficiente il client spedirà, sempre in broadcast, un messaggio di cancel appena ogni blocco è stato ricevuto. Quando entrare in questa modalità è ancora oggetto di discussione. Alcuni clients vi entrano quando sono stati richiesti tutti i piece, altri aspettano finché il numero dei blocchi rimanenti è minore di quelli in transito o comunque non è superiore a 20.
18
2.4.4 – Choking algorithm
Nel protocollo BitTorrent non vi è una allocazione delle risorse centralizzata e ogni peer cerca di massimizzare il proprio download rate. Nel far ciò un peer si trova di fronte al problema della cooperazione download/upload analoga al dilemma del prigioniero iterato [14]. L’algoritmo di choking garantisce la collaborazione tra i peers eliminando tale dilemma e permettendo di ottenere l’ottimo paretiano applicando una strategia tit-for-tat.
Le strategie di questo tipo prevedono in un primo momento di fornire cooperazione e in secondo luogo di variare il proprio comportamento in funzione di quello assunto dall’altro partecipante nell’intervallo precedente.
L’atto del choking è un temporaneo rifiuto di fornire i dati ma non di riceverli e quindi il download può continuare e la connessione non deve essere rinegoziata quando termina questa condizione.
Ogni buon algoritmo di choking deve rispettare un certo numero di criteri:
1. deve evitare che si verifichi il fenomeno detto “fibrillazione” per il quale c'è un passaggio veloce dallo stato choked a quello unchoked comportando un notevole overhead all’interno della rete;
2. deve permettere al client di contraccambiare la banda di upload fornita da quei peers dai quali sta scaricando (principio di reciprocità);
3. deve essere in grado di controllare le connessioni non attive per verificare se tra esse ce n'è qualcuna che può risultare più vantaggiosa (optimistic unchoking).
Il fenomeno della fibrillazione è evitato unicamente ripetendo la scelta dei peer da soffocare ogni 10 secondi (choking_ interval).
Ogni client partecipa alla diffusione del file “sbloccando” (unchoke) un fissato numero di peers (valore di default 4) tra tutti quelli con cui ha instaurato una connessione TCP. Il problema si riduce quindi alla scelta di quali di essi non “soffocare”.
Il client fa l’unchoke dei quattro peers che gli garantiscono le maggiori velocità di download e che risultano interessati ad esso. Questi quattro peers vengono detti
19
versione di BitTorrent analizzata prevede di calcolarne la media per ciascuna connessione ogni 20 secondi.
Va notato che se un client è in possesso dell’intero file (è seed) userà il suo rate di upload invece che quello di download per scegliere quali peers non soffocare preferendo, di fatto, quei peers che riescono a scaricare più velocemente.
Figura 2.7 – Choking/Unchoking
Ogni 30 secondi (optimistic_unchoke_interval), inoltre, viene effettuata anche un’ulteriore scelta detta optimistic unchoking. Il client riserverà una ulteriore parte della sua banda di upload ad un peer indipendentemente dal download rate che sperimenta nei suoi confronti. Questo meccanismo permette al client di saggiare la bontà delle connessioni inutilizzate alla ricerca di una migliore di quelle attualmente in uso e fornisce ai peers appena entrati a far parte dello swarm la possibilità di completare il prima possibile una parte del file.
E’ evidente in questo caso l’analogia con le strategie tit-for.tat. L’optimistic unchoking corrisponde alla prima mossa di tale strategia nella quale i partecipanti cooperano.
20 Antisnubbing
A volte può accadere che il client venga “soffocato” da tutti i peers da cui sta scaricando. In questi casi esso continuerà ad ottenere bassi download rate finché l’optimistic unchoking non gli permetterà di trovare peers migliori. Per mitigare questo problema, un client che non riceve nessun piece, per più di un minuto, da un determinato peer soffoca subito la connessione assumendo di essere stato snobbato (snubbed) da quest’ultimo e avvia un optimistic unchoking.
Il client potrebbe continuare comunque a fornire dati al peer che lo ha snobbato se esso fosse il bersaglio dell’optimistic unchoking o nel caso in cui ricominciasse a ricevere dati da quest’ultimo.
2.5 – Miglioramenti
Un punto debole dell’architettura BitTorrent è il tracker. Esso è l’unica entità centrale dell’intero sistema e se viene attaccato o, molto più semplicemente, si rompe tutti i file che riferivano a lui vengono persi.
Per questo motivo dalla versione 4.1 in poi è stata prevista la funzionalità di un tracker decentralizzato (trackerless mode). La soluzione è basata su DHT in particolare sul protocollo Kademlia, un evoluzione di Chord.
2.6 – Considerazioni generali
BitTorrent è uno dei sistemi P2P più diffusi ed è, secondo alcuni studi del 2005 [15], responsabile di almeno il 30% del traffico internet globale.
Molti studi hanno evidenziato che gli utenti nella maggior parte dei software P2P risultano molto più egoisti di quanto lo siano in BitTorrent. La causa di questo comportamento, per alcuni studiosi [16], è da ricercare nell’assenza di un motore di ricerca centralizzato dei file. In sua assenza infatti i file .torrent si possono trovare su siti, forum o essere mandati via mail: tutti questi luoghi elettronici prevedono però interazione sociale fra gli individui coinvolti nello swarm, creando uno spirito di gruppo che rende l’utente meno avido.
21
Queste comunità, dette tribù, inoltre si auto-selezionano espellendo membri che non si comportano secondo le loro regole. Questo meccanismo porta inoltre alla dissoluzione delle tribù composte principalmente da defezionatori. Un'alta presenza di quest'ultimi porta, prima o poi, tutti i peers ad imbrogliare il prossimo portando la tribù alla degradazione di performance e al suo scioglimento.