Hace 4 años | Por ccguy a blog.jse.li
Publicado hace 4 años por ccguy a blog.jse.li

Un cliente de BitTorrent escrito desde cero en Go, con el protocolo muy bien explicado y el fuente comentado según va progresando el desarrollo.

Comentarios

D

#8
Que librerias faltarian? por saber. Porque me imagino que estaran hechas por ahi que sirvan.

e

#10 pues no conozco GO pero para hacer un cliente de bittorrent con una buena librería de comunicaciones tcp sincrona y/o asincrona mas otra que maneje streams (memoira y disco), alguna para manejar listas,colecciones o diccionarios, multithread sería un plus bastaría.

D

#8 Por no hablar que la concurrencia a lo CSP que tienes de gratis.

>multithread sería un plus

https://golang.org/doc/faq#goroutines

D

#8 Te dejas que Go puede compilar de forma cruzada automágicamente desde y para WIndows/Linux/OSX y BSD.

e

#14 no no me lo dejo la pregunta no es la diferencia entre go y c es qué necesitaría para programarlo en C

D

#15 Una librería y mucho más código. Entre memcpy y usar canales de Go, la respuesta es obvia.

https://blog.golang.org/share-memory-by-communicating

https://golang.org/doc/codewalk/sharemem/

e

#16 creo que sigues sin entender la pregunta y mi respuesta. Pero te puedo asegurar por que lo he hecho que con una buena librería de TCP y streams haces un cliente de bitorrent en un pispas.
Hay librerias para threading que no tienen nada que envidiar al GO, lo mismo para el resto de cosas....

ccguy

#14 C también.

ccguy

#21 claro que de forma trivial. Tienes el compilador de GNU para todas las plataformas y C siempre ha sido muy portable.

D

#47 No señor. Estamos hablando de que ahora mismo desde mi OpenBSD he generado un binario para Windows sin necesidad de MinGW.
Puedo hacer lo mismo con un target FreeBSD y ARM:

a:~/Docs/go/stuff>uname -s
OpenBSD
a:~/Docs/go/stuff>env GOOS=freebsd GOARCH=arm go build ex.go
a:~/Docs/go/stuff>file ex
ex: ELF 32-bit LSB executable, ARM, version 1

Intenta eso con C sin meter una suite gorda de compiladores cruzados.

Yo solo he instalado el paquete "go" en OpenBSD. Nada más, cero dependencias.

D

#47 Y lo que tu dices es posible, pero con lo opuesto a GNU: el C de plan9

Tienes el compilador 1-9c, donde un número va a asociado a cada plataforma de CPU. Y 1-9l, el enlazador. Todos los binarios son estáticos, y claro está que crear un binario para ARM o MIPS en C de ARM está tirado. Otra cosa son rollos big/little endian, pero creo que la librería C de plan9 (u.h, libc.h) están en un nivel bastante superior en capacidad y sencillez respeto a POSIX.

De hecho la filosofía de Go está basada en la suite de plan9 y en dicho diseño, y creo que usan una concurrencia similar :). Por algo son de los misma gente ha creado C.

d

#49 #41 No exactamente, el propio diseño de internet hace que necesites saber la IP para poder conectarte.
No es algo del torrent.

D

#20

a:~/Docs/go/stuff>nvi ex.go
a:~/Docs/go/stuff>env GOOS=windows GOARCH=amd64 go build ex.go
a:~/Docs/go/stuff>file *
ex.exe: MS-DOS executable PE for MS Windows (console) Mono/.Net assembly
ex.go: ASCII Java program text

D

Interesante!!

D

#1 Más que bien. Más importante que el programa son los comentarios.

¿Qué estoy haciendo aquí?

if ( (a módulo 2) == 0 ) else

Exactamente el mismo código puede usarse para infinidad de cosas diferentes. Si no hay comentarios, ¿qué estoy haciendo? Nadie sabe.

Boleteria

#24 El delito sería añadir un comentario a ese código. Con el nombre de la clase debería ser suficientemente auto explicativo. Cualquier comentario explicando lo obvio no es mas que ruido.

D

#25 Pero es que lo obvio se puede hacer de mil maneras diferentes según la experiencia, talento y el conocimiento del programador. Si tiene comentario sé lo que INTENTA hacer el programador y puedo inventarme algo que sea mucho mejor. Si no tiene comentario solo puedo "mejorar" el código de lo que el otro escribió, cuando pudiera ser mucho mejor hacerlo de una manera completamente diferente. Así que incluso para lo "obvio", los comentarios son buenos.

Adicionalmente, es mucho más rápido leer una línea de comentario que el código de arriba. Eso acelera enormemente la depuración, verificación, y el entendimiento, del programa. Es posible que el comentario (lo que quiere hacer el programador) choque con lo que expresa el código (lo que hace el programa), entonces ¿cuál es lo correcto, lo que el programador me dice (en el comentario) o lo que el programa realmente hace (en el código)?. Si no hay comentarios no se pueden detectar fácilmente esos problemas, y el trabajo de revisión se multiplica por 10, 100 o 1000. A veces se necesitará tener al programador al lado para que explique lo que ha hecho (o lo que realmente intenta hacer) y ver si coincide con lo que hace el código. Eso se resuelve en muchos casos con un simple comentario.

pawer13

#26 el comentario en ese caso es el nombre de la función.
El problema con los comentarios es que te puedes olvidar actualizarlos, con lo que si tienes ese código y un comentario diciendo "hago A si a es impar" y ya no sabes si el código está mal o el comentario no corresponde.

D

#30 Completamente de acuerdo. Recomiendo la lectura de uncle Bob en su libro de prácticas sobre Clean Code.

D

#34 Yo también recomiendo ampliamente el libro. Pero ese es uno de los puntos en el que estoy en desacuerdo y donde veo el libro incompleto.

Ha varios tipos de comentarios, los comentarios par aclarar el código, los comentarios para describir el código. Hablo de los segundos, para describir el código.

D

#37 Un buen código de debe autodescribir. Comentarios que explican lo que hace un trozo de código pueden implicar "un problema". Además después tenemos otro problema: hay que mantener el código Y los comentarios doble trabajo y doble posibilidad de error sobre todo si pasa por 5 manos distintas.
Igualmente en otros casos concretos si veo necesario poner ejemplos en código. Una regular expression por poner un ejemplo muy concteto aunque es aplicable a otros casos. Depende del uso. Siempre hay que aplicar la lógica y filosofía KISS. En mi experiencia es lo que mejores resultados ha dado.
Saludos.

D

#39 Un buen código se debe autodescribir. Sí. Los comentarios que explican un trozo de código implican un problema, tal y como dice dice Robert C. Martin en su su excelente libro Clean Code, pero la cosa va mucho más allá. Un código perfecto (de esos que "no necesitan comentarios" y que son "autoexplicativos" según el libro) se mejora significativamente con los comentarios adecuados. Robert no ha llegado hasta allí. No sabe que hay un tipo de comentarios que son más importantes y valen más que el propio código.

Abajo en la imagen una sección de un programa en assembler para el procesador 8088, que junto con el 8086 fueron los primeros de la serie x86 (y x64). Proviene del libro IBM PC Technical Reference Manual, que puedes bajar por torrent, y donde se encuentra el código fuente de TODO el BIOS del IBM PC en el apéndice A.

En la imagen que envío está el inicio de la interrupción 10h del BIOS, que tenía la funcionalidad de manejar el video, imprime caracteres, hace scroll de partes de la pantalla, etc . En el listado os comentarios comienzan con punto y coma. Al principio describen cómo usar esa interrupción, luego cuando está el código hay prácticamente un comentario por cada línea de código, o sea, por cada instrucción en assembler, y hay muchos comentarios adicionales. Es decir, que hay más líneas de comentarios que de código. Ese código con esos comentarios y el formato son una joya, una obra de arte que se aleja millones de kilómetros de la formas chapuceras de hoy en día.

¿Sobran los comentarios del listado del BIOS? No. No hay un solo comentario que sobre.

Algo curioso está en la línea 3275 que se ve en la imagen, donde aparece:
  SAL AX, 1  ; *2 FOR TABLE LOOKUP

¿qué hace eso? No lo sabrás nunca sin un comentario. Porque esa instrucción, que desplazas los bits hacia la izquierda aritméticamente puede usarse para un millón de cosas diferentes, y necesita un comentario para saber lo que se quiere hacer, la intención del programador. Por cierto, es absurdo usar esa instrucción allí, no era necesaria. Lo correcto hubiera sido usar la siguiente:
  SHL AX, 1  ; *2 FOR TABLE LOOKUP

¿Por qué? Porque es totalmente innecesario y absurdo lo de "shift aritmetic left" (SAL) allí, pues no aplica. Funciona, sí, pero hace el programa confuso. Si no se ponen los comentario se puede deducir con un análisis profundo del código (y que lleva mucho tiempo), con el comentario uno se da cuenta casi instantáneamente.

En los lenguajes de alto nivel no son necesarios tantos comentarios come en assembler, pero sí son extremadamente valiosos al igual que en el assembler. Un código que tenga buenos comentarios (del tipo "algoritmo") por ejemplo, no necesitas leer el código pues el algoritmo está expresado en esos comentarios. Esos comentarios son más importantes que el propio código, pues el código es solo la implemntación de lo que dice el comentario (el verdadero algoritmo), expresado a un altísimo nivel, mucho más arriba que el código "de alto nivel", y ahorran toneladas de horas en el análisis, modificación, entendimiento, etc, de los programas.

¿Pero no es redundante?, ¿para que vas vas a repetir en comentarios lo que hace el algoritmo? Eso no se hace nunca, los comentario no repiten lo que dice el algoritmo. Eso es hacer muy malos comentarios. Lo que vas es a expresar lo que quieres hacer de una manera más clara, mejor, y de más alto nivel, de lo que expresa el propio código. De tal manera que se pueda leer esos comentarios y se entienda el programa sin necesidad de leer los detalles de bajo nivel, engorrosos, y miserables del código de los lenguajes de programación. Usarás el español como lenguaje que expresa el algoritmo, que es de un nivel órdenes de magnitud superior y mucho más conciso, claro, limpio, entendible, etc que las mierdas de código. Pero hay que hacer buenos comentarios, no repetir lo que ya dice el código.

Ejemplo de comentario de mierda:
  i++; // incremento i

Eso no dice nada. Dice exactamente lo mismo que me dice el código pero con otras palabras. No estoy añadiendo ningún valor, no estoy aclarando nada, no estoy explicando cuál es mi intención, no describe lo que quiero hacer sino lo que ya dice el propio código programa. No sirve.

Buen comentario:
  i++; // siguiente estrella

Ahora sí digo qué es lo que stoy haciendo. Y se entenderá perfectamente bien en el contexto, que pudiera ser un telescopio que analice estrellas y las va recorriendo una por una. "i++" puede significar cualquier cosa dentro de un programa, pero en mi programa ese "i++" pasa a la siguiente estrella. (Sí, hay cosas mejores que un "i++", pero es solo un ejemplo). Y observación, estoy tomando el comentario más sencillo, humilde, y menos significativo e importante de un programa, el que describe una línea de código. Los comentarios más avanzados están millones de kilómetros por arriba de eso.

Yo programo en español, yo pienso en español, yo imagino en español, y mi lenguaje de programación para expresar los algoritmos es el español (los comentarios). Luego compilo los comentarios a código de máquina (C++, Java, Python, etc).

D

#39 Imagen que me faltó en #42

D

#42 En assembler es el típico ejemplo de lenguaje de bajo nivel que como bien comentas sin comentarios estás muerto.
El resto como decía depende del contexto. Un i++ dentro de un bucle puede ser nada o bien siguiente estrella como mencionas, con lo cual el sentido del comentario cambia en función de la semántica. Uno es relevante y otro no en el caso de un bucle.
Creo que en el fondo del asunto estamos de acuerdo.

D

#42 Y haciendo una breve puntualización: Sí i++ es siguiente estrella entonces lo mejor es llamar a esa variable siguienteEstrella y ya está.

D

#45 ¿siguienteEstrella++ es la estrella siguiente a la siguiente estrella?

D

Un tutorial muy majo.
A ver si alguien me encuentra fuentes para rust (que compilen/funcionen con versiones actualizadas).

D

Go es una puñeteras maravilla para estas cosas.

D

#3 Pregunta de inculto: Porque esto se puede hacer en Go facil y no en C? Cuanto mas codigo tendrias que escribir en C?

D

Ale, ya teneis cliente bittorrent para cuando en Indra os lo pidan y lo vengan por 100 mil euros para un proyecto de altisima calidad de distribucion p2p.
A picar teclas monos.

Powertrip

#7 ¿es portable a java?

m

#9 ni que eso le importara a Indra

D

#7
Tu calla y a picar! El miercoles por la mañana voy a cliente, tu veras...

D

Lectura de menos de 5 minutos que le vendría bien al autor para empezar.

https://dev.to/jrwren/solid-principles-in-the-go-programming-language-kbc

T

#18 ¿qué tiene que ver SOLID en un lenguaje que no es orientado a objetos (tal y como reconoce el propio autor de tu enlace)? Y lo que es más, ¿qué tiene que ver el enlace que pones con el meneo?

D

#27 Lo explica en el artículo, que como ya he dicho es un "para empezar". Que no haya una traducción directa no quiere decir que no haya principios que no deban aplicarse.

Go tiene interfaces, por lo que te permite depender de abstracciones. No he visto ni una en el código del que sube el artículo.

T

#31 Oops, esto iba para #29

s

#36 el cliente recibe tu ip para poder conectarse, eso significa que ya la tiene, si la enseña o no al usuario es otra cosa. Pero en cualquier caso, aunque el cliente la ocultase el otro lado podría seguir viendo tu ip mirando las conexiones abiertas o analizando los paquetes de red. Además conseguir asegurarte de que el otro lado no hay un cliente que enseñe al usuario tu ip es extremadamente costoso, sino imposible, para la poca utilidad que tendría.

protogenes

#38 #40 Gracias a ambos. Vamos, que el propio diseño torrent lo hace imposible.

protogenes

Pregunta de no-experto: ¿se puede crear (es factible) un cliente de bittorrent realmente anónimo? O sea, me refiero a que no comparta tu IP con otros clientes de la red, sin necesidad de VPN y demás.

Para mí es lo único que le falta (o que no he sabido encontrar) al tema. De esto que en "pares" no te salga la IP en la info del archivo vamos.

PD: uso transmission.

s

#23 Hasta donde yo se no. Bittorrent es un protocolo de comparticion distribuido entre pares. Al no haber servidor en medio, es necesario que las dos pares se conecten y para crear la conexión se requiere la ip.

protogenes

#28 Sí, eso lo entiendo, pero ¿no habría un modo de que tu cliente, digamos... "cifrase/ocultase" tu IP de forma que otros clientes sólo viesen **.***.***.**, como al introducir contraseñas? El propio programa se comunicaría con el otro, pero el cliente no lo ve. Aunque pensándolo bien, supongo que si el otro programa "ve" tu IP porque lo necesita, está en la programación del otro qué hacer con esa IP. Vamos, que en todo caso sólo podría hacerse si ambos usasen el mismo programa, y este ocultase la IP, no si mezclo clientes.

d

#23 Aunque el cliente torrent no envíe la IP, el servidor vería la IP desde donde el cliente se conecta, ya que es parte de los headers del protocolo IP.
Sin esa IP, no se puede establecer una comunicación a través de internet.

T

Segundo párrafo de tu enlace:
Here is why you shouldn't think very much about SOLID in Go

Repito: ¿para qué quieres mezclar churras (SOLID/POO) con merinas (Go)?

Uno crea interfaces (por regla general) si espera que su código sea reusado en algún momento. Para hacer una aplicación final sencilla, lo más probable es que no haga falta crearse abstracciones. ¿Para qué complicar el código?

D

#31 Para crear stubs fácilmente o poder decorar un servicio en el futuro sin tener que tocar la implementación, por ejemplo.

Tu lo llamas complicar el código, yo lo llamo intentar aplicar buenas prácticas para que este sea más mantenible y para que los que intenten aprender de ello no caigan en los mismos errores.

Y, hasta cierto punto, por la misma razón que cuando estoy en casa solo sigo utilizando cubiertos en vez de comer con las manos, o hago la cama por las mañanas, porque no soy un salvaje.