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 ...
 








Bittorrent on cloud ,crónica de una muerte anunciada.

viernes, 25 de julio de 2014

Intento fallido de montar en un entorno cloud un proyecto bittorent.
El principal problema ha sido la plataforma OpenShift ,no permite abir puertos al exterior.El core del problema funciona en mi local , intentamos subirlo a una plataforma cloud (PaaS) y no ha sido posible.En un principio por nuestras direcciones locales.Luego de ello hemos sustituido por las variables de entorno de OpenShift y entonces podía hacer un binding desde una dirección local via socket pero toda vez que intentaba cambiar dichas direcciones SocketDenied!!!!!!.Si hubieramos conseguido una implementación del protocolo BitTorrent via Websocket podríamos haber tenido nuestra solución en las manos SI los Miami HEAT hubieran ganado la liga Lebron no estaría en Cleveland , así es la vida. 

Existían 2 soluciones al respecto una de ellas buscar un servidor Dedicado y subir alli nuestro .war y empezar a trabajar.
Hemos optado por la segunda ,pasar del tema .Ha salido la ley de la Propiedad Intelecual  o al menos la han aprobado,sale en el 2015.Multas muy grandes de 30 000 - 300 000 para temas que se ajustaban al proyecto que nos encontramos desarrollando.
La solución sera ir a por otro tema así que al menos de momento esta es la muerte un un proyecto que apenas empezó en sus pruebas.
Voy a empezar a poner imágenes a este blog ..de todos modos nadie lo mira.