Aprende

Aprende sobre la última tecnología.

Construye

Da rienda suelta a tus conocimientos y construye!

Comparte

Que más gente lo aproveche para mejorar!
 

Aspectos básicos de la implementación del protocolo BitTorrent

miércoles, 30 de julio de 2014

Lo primero para la implementación del protocolo Bittorrent es ver la especificación del mismo.
Lo tenemos en http://www.bittorrent.org/beps/bep_0003.html a partir de aquí tenemos varias cosas a tener en cuenta una de ellas es el lenguaje en el que realizar las implementaciones.
Podríamos detallar código pero es perdida de tiempo,a continuación algunas implementaciones interesantes :
- https://github.com/mpetazzoni/ttorrent  esta implementación es totalmente fiel al protocolo pero las descargas son excesivamente lentas.

- http://bitpower.sourceforge.net esta es la implementación mas completa

Una porción del código
File metadataDirectory = new File("/Users/ldipotet/javaapps/testclientTor/TorrentClientProject");
   
try {
//lo cierto es que aun no se para que usan este metadirectory,se crea la carpeta en el sitio indicado con un id 
//luego esta carpeta la entramos siempre vacía 
     controller = new TorrentSetController (metadataDirectory);
    } catch (IOException e) {
 e.printStackTrace ();
 exitWithError ("Could not open server socket");
    }

 // Can't actually happen. Satisfies compiler stupidity
 if (controller == null) return;

   TorrentManager manager = null;
 try {
 //implica que el fichero el fichero sera descargado en la raiz del proyecto....
 //podriamos agregar un TorrentManager por cada peticion??? 
    
 manager = controller.addTorrentManager (torrentFile, new File("."));
    manager.start (false);


Tal y como detallo en el código el código descargado se deja en la raíz del proyecto y el metadatadirectory solo es necesario para seguir los trackers dado el caso que se interrumpa por alguna razón la descarga.
En esta implementación (bitpower) la clase ConnectionManager es la que gestiona las conexiones.



public synchronized int listen (InetAddress listenAddress, int listenPort, InboundConnectionListener listener) throws IOException {
if (this.closed) {
 throw new IOException ("ConnectionManager is closed");
}

  // Open a server channel and register it with the selector
final ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking (false);
InetSocketAddress socketAddress = new InetSocketAddress (listenAddress, listenPort);
serverSocketChannel.socket().bind (socketAddress);
int boundPort = serverSocketChannel.socket().getLocalPort();

  // Associate the server channel with the specified listener
this.inboundConnectionListeners.put (serverSocketChannel, listener);

  // Queue the server socket for registration, asynchronously
synchronized (this.queuedTasks) {
 this.queuedTasks.add (new Runnable() {
  public void run() {
    try {
  serverSocketChannel.register (ConnectionManager.this.selector, SelectionKey.OP_ACCEPT);
.............



public synchronized Connection connect (final InetAddress remoteAddress, ...) 
throws IOException
{
 if (this.closed) {
 throw new IOException ("ConnectionManager is closed");
  }
final SocketChannel socketChannel = SocketChannel.open();
socketChannel.configureBlocking (false);
final Connection connection = new Connection (this, socketChannel);

  // Queue the connection to be opened
synchronized (this.queuedTasks) {
  this.queuedTasks.add (new Runnable() {
  public void run() {
 try {
              boolean completeConnection = socketChannel.connect 
               (new InetSocketAddress (remoteAddress, remotePort));
  SelectionKey key = socketChannel.register 
                (ConnectionManager.this.selector, SelectionKey.OP_CONNECT);
  key.attach (connection);
  Long deadline = (connectTimeout == 0) ? 
                Long.MAX_VALUE : System.currentTimeMillis() + 
                (connectTimeout * 1000);
  ConnectionManager.this.pendingConnections.put 
                (socketChannel, deadline);
  ConnectionManager.this.outboundConnectionListeners.put 
                (socketChannel, listener);
  if (completeConnection) {
        processConnect (key);


Para no hacer esto tedioso con tanto código, los dos métodos básicos listen y connect implementan los sockets aquí se registran y además se hacen los binding a las respectivas direcciones.
Esta información así como la cantidad de piezas la coge de los hash y las direcciones a conectarse de los torrent tracker server .
En fin para ser una implementación en cliente standalone es una buena opción .

Si fuera constituir el core para el lugar de llamar a un torrent llamar a un conjunto de torrent implementan un elasticseed,este no lo he probado os lo dejo a vosotros.

El core de este tema para hacer llamadas múltiples es una explotación a fondo del api de concurrencia de java http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html que va desde los tipos thread safe hasta la implementación de Executors o Semaphores.

He aquí algunos enlaces de clientes torrent online :

http://www.noobstogeek.com/free-online-torrent-downloader/
https://www.furk.net/
https://www.furk.net/


Vale destacar que además de ellos tenemos algunas versiones en c++ standalone para linux que funcionan de muerte tanto como librerías para ser usadas digase por ejemplo a través de un servicio rest o a través de  la shell en linux :

http://aria2.sourceforge.net/manual/en/html/README.html

Esta implementación esta fenomeno ..totalmente indescriptible con un consumo mínimo de memoria, el problema es la limitación a usuarios linux para el caso que queramos disfrutar de esta máxima eficiencia......


People hasta otra entrega ...seguimos sin poner imágenes ,para la próxima ...
 








0 comentarios:

Publicar un comentario