Ein von Grund auf selbst implementierter BitTorrent-Client
(github.com/piyushgupta53)- Dieses Open-Source-Projekt ist ein in Go implementierter BitTorrent-Client, der die grundlegende Logik für den Dateidownload selbst umsetzt
- Bencode-Kodierung/-Dekodierung wird direkt verarbeitet und umfasst eine robuste Fehlerprüfung
- Es unterstützt umfassend Kernfunktionen wie Parsen von
.torrent-Dateien, Berechnung des Info-Hashs und Peer-to-Peer-Kommunikation - Enthält Funktionen mit hohem Praxisnutzen wie parallele Downloads und Dateizusammenbau sowie blockweises Speichermanagement
- Im Vergleich zu bestehendem BitTorrent-Open-Source-Code liegen die Stärken in der Einfachheit von Go, der Klarheit der Codestruktur und der Modularisierung
Überblick
Dieses Projekt implementiert einen BitTorrent-Client direkt in Go
Es stellt die Dateidownload-Funktion auf Basis des BitTorrent-Protokolls als Eigenimplementierung bereit
Im Kern behandelt es Parsen von Torrent-Dateien, Peer-Erkennung und Dateidownload
Hauptfunktionen
-
Bencode-Kodierung/-Dekodierung
- Unterstützt alle Bencode-Typen wie Strings, Integer, Listen und Dictionaries
- Verwendet robuste Fehlerbehandlung und Datenvalidierung
-
Verarbeitung von Torrent-Dateien
- Kann sowohl Single-File- als auch Multi-File-Torrents parsen
- Extrahiert den Info-Hash und die Hashes der einzelnen Pieces, unterstützt alle Standardfelder
-
Peer-Erkennung und Kommunikation
- Unterstützung für HTTP-Tracker
- Implementierung des Peer-Handshake-Protokolls
- Führt das BitTorrent-Nachrichtenprotokoll und die Verwaltung von Peer-Verbindungen aus
-
Download-Funktionen
- Verwaltung auf Piece- und Block-Ebene
- Verarbeitung paralleler Downloads
- Verfolgung des Download-Fortschritts und Dateizusammenbau
- Effizienz durch blockweises Speichermanagement
Projektstruktur
- cmd/ : Kommandozeilenschnittstelle und ausführbare Dateien
- internal/
- bencode/ : Funktionen für Bencode-Kodierung und -Dekodierung
- torrent/ : Parsen und Verarbeiten von Torrent-Dateien
- tracker/ : Implementierung des Tracker-Protokolls
- peer/ : Funktionen für Peer-to-Peer-Kommunikation
- download/ : Funktionen zur Download-Verwaltung
- pkg/ : Sammlung von Paketen, die extern verfügbar gemacht werden können
Anforderungen
- Go 1.21 oder höher erforderlich
Verwendung
- Das Projekt befindet sich derzeit in einer frühen Entwicklungsphase; eine Nutzungsanleitung wird später ergänzt
Entwicklungsstand und Planung
- Die Entwicklung wird derzeit aktiv vorangetrieben
- Die detaillierten Entwicklungsphasen sind in der Datei
checkpoint.mddokumentiert - Geplante nächste Schritte:
- Unterstützung für Magnet-Links
- Metadaten-Austauschprotokoll
- Geplante Unterstützung für DHT (Distributed Hash Table)
Referenzdokumente
- BitTorrent-Protokollspezifikation
- Bencode-Spezifikation
Bedeutung und Stärken des Projekts
- Dieses Projekt nutzt die für Go typische einfache Syntax und Parallelität, um die komplexen Elemente eines BitTorrent-Clients klar modularisiert zu implementieren
- Die klare Struktur bietet Vorteile für Erweiterbarkeit und Wartbarkeit – sowohl zum Lernen als auch für den praktischen Einsatz
- Obwohl es sich noch um ein relativ frühes Stadium handelt, wurden die zentralen Funktionen des BitTorrent-Protokolls bereits schnell umgesetzt
1 Kommentare
Hacker-News-Kommentare
Es wurde vorgeschlagen, die Größe dynamischer Speicherallokationen im bencode-Decoder zu begrenzen. Da Eingabewerte aus Torrent-Dateien oder aus
announcenicht vertrauenswürdig sind, könnten bösartige Eingaben sehr große Allokationsanfragen auslösen und so einen Denial-of-Service (DoS) verursachen. Beim String-Parsing kann eine sinnvolle Obergrenze auf die verbleibende Eingabelänge gesetzt werden, denn ein korrekter Torrent kann keine Zeichenkette enthalten, die länger ist als die restliche DateilängeDas Projekt wirkt schön aufgeräumt und simpel, was sehr gefällt. Es wäre gut, im Readme ein Einzeiler-Beispiel zur Nutzung hinzuzufügen, zum Beispiel eine Zeile wie
./go-torrent My-Linux-Distro-Wink-ISO.torrent, die die Verwendung zeigt. Falls außerdem nochtorrent.ParseFromUrldazukommt, gäbe das noch mehr Pluspunkte. Solche Erfahrungen sind für die eigene „spirituelle Reise“ für jeden lohnenswertHinweis auf eine ähnliche Challenge von codecrafters. Dort wird beim Fortschritt und Testen geholfen, und ein kostenloser Monat hat ziemlich viel Spaß gemacht
https://app.codecrafters.io/courses/bittorrent/overview
Aus Sicht eines Nicht-Go-Entwicklers wurde gefragt, warum eine ältere Go-Version 1.21 verwendet wird. Ob es einen besonderen Grund gibt, an einer alten Version festzuhalten. Laut Recherche wurde sie bereits vor 10 Monaten eingestellt
Wegen der Unterstützung für Windows 7. Projekte, die mit Go 1.21.4 oder älter geschrieben wurden, laufen auf fast allen Windows-Versionen seit 2009 und auf praktisch jedem Rechner, aber ab 1.21.5 nur noch auf modernen Rechnern mit Windows 10 oder 11, ohne besonderen Vorteil
https://github.com/golang/go/issues/64622
Das README wurde wahrscheinlich von einer AI geschrieben. In der eigentlichen
go.mod-Datei ist die Go-Version auf 1.23.1 gesetzt, daher wird letztlich 1.23.1 oder höher benötigthttps://github.com/piyushgupta53/go-torrent-client/blob/6130f4e/go.mod#L3 https://go.dev/doc/modules/gomod-ref#go-notes
Wirklich ein großartiges Projekt. Im Networking-Kurs an Georgia Tech im Studium war das einmal die Abschlussaufgabe. Der Code ist zwar verloren gegangen, aber die dabei gelernten Lektionen sind fürs Leben geblieben. Solche Projekte sind ein sehr guter Weg, um eine neue Sprache zu lernen
Es wurde gefragt, ob Magnet-Links unterstützt werden.
Edit: Inzwischen wurde klar, dass das eine geplante Funktion ist
Es wurde gefragt, wie so etwas gebaut wurde. Ob direkt die Protokollspezifikation gelesen wurde oder ob man sich an anderen Implementierungen orientiert hat. Es sei immer interessant, wie man so etwas von Grund auf umsetzt
https://www.bittorrent.org/beps/bep_0003.html
Zusätzliche Erweiterungen finden sich unter
https://www.bittorrent.org/beps/bep_0000.html
Wichtig ist, die Arbeit in sehr kleine Schritte zu zerlegen und die Ergebnisse laufend selbst zu überprüfen. Ich habe zum Beispiel mit dem Parsen von
.torrent-Dateien begonnen und musste bencoding selbst implementieren. Als ich ein.torrentfür Arch Linux heruntergeladen habe, war das Format unerwartet und enthielt Schlüssel wieurl-list, die ich nicht erwartet hatte. Bei der Recherche stellte sich heraus, dass das mit bep_0019 zusammenhängt. Am Ende konnte ich eine Debian-Linux-.torrent-Datei erfolgreich parsenDanach habe ich die HTTP-
announce-Anfragen an den Tracker und auch das Peer-Protokoll implementiert. Das Peer-Protokoll war ziemlich schwierig, und eine experimentelle Herangehensweise war dabei sehr hilfreich. Ich habe in einem Debian-Torrent dieannounce-URL entfernt, damit überhaupt keine Peers vorhanden waren, und dann meinen Client direkt in KTorrent hinzugefügt, um die ausgetauschten Nachrichten zu beobachten und meinen Code anhand dessen anzupassen. Es gab sehr viel Trial-and-Error und DebuggingManche Protokolldetails ließen sich in der offiziellen Dokumentation überhaupt nicht finden, daher habe ich gelegentlich auch ChatGPT zu Kleinigkeiten befragt. Außerdem unterscheiden sich Implementierungen je nach Client etwas, sodass detaillierte Algorithmen nicht klar definiert sind. Dinge wie die Auswahl der nächsten Blöcke, die Wahl der zu verbindenden Peers oder das Verhalten von choke/unchoke sind nicht wirklich sauber dokumentiert. Websuche hilft dabei sehr
Zusätzlich gibt es auf https://wiki.theory.org/Main_Page hilfreiche Informationen
Aktuell ist der Stand erreicht, dass vollständiger Download und Upload mit KTorrent möglich sind. Als Nächstes bleibt die Entwicklung von Algorithmen, um Peers vom Tracker zu beziehen, herunterzuladende Blöcke auszuwählen und sie in Dateien zu speichern
Falls du mehr Details zum Ablauf wissen möchtest, frag jederzeit nach
Es wurde gefragt, wie schwierig das Hinzufügen einer GUI wäre. Beispiele für GUI-Implementierungen in Go sehe man nicht oft
Persönlich bevorzuge ich https://github.com/AllenDang/giu, einen ImGui-Wrapper
Am funktionsreichsten ist wohl unison, aber ob es in der Praxis wirklich weit verbreitet ist, weiß ich nicht, und die Dokumentation scheint sehr spärlich zu sein https://github.com/richardwilkes/unison
Gio ist ein GUI-Framework mit neuem Ansatz und wird von Tailscale und gotraceui verwendet https://gioui.org
Wails ist leicht zu erlernen, wenn man Erfahrung in der Webentwicklung hat https://wails.io
Auch GTK4-Bindings sehen ordentlich aus https://github.com/diamondburned/gotk4
Cogent Core wirkt ebenfalls interessant, ich habe es aber nur kurz genutzt, bevor ich statt Go zur Sprache Odin gewechselt bin https://www.cogentcore.org/core
Fyne hatte bei mir persönlich auf mehreren Rechnern und Betriebssystemen viele Performance-Probleme, ist aber dennoch das bekannteste GUI-Framework https://fyne.io
Jemand interessierte sich für solche Projekte und hatte überlegt, es selbst einmal zu versuchen. Gefragt wurde, wie schwierig es ist, wie ausgereift die Umsetzung ist und ob auch komplexe Funktionen wie DHT, Magnet und NAT-Traversal implementiert wurden. Es sei nicht einmal klar, welche Funktionen zwingend nötig sind, um praktisch alle Torrents da draußen abzudecken. Rund um Torrents gebe es so viele Protokolle, dass man nicht einmal die vollständige Liste kenne, geschweige denn die Aufgabe jedes einzelnen Protokolls
Der Schwierigkeitsgrad hängt stark von Erfahrung, Sprachkenntnissen und experimenteller Arbeitsweise ab. Ich selbst habe zum Beispiel letzte Woche begonnen, einen Bittorrent-Client in Go zu schreiben, und bin innerhalb einer Woche auf etwa 80 % des hier gezeigten Projekts gekommen. Ich kenne Go, Protokolle und Netzwerke gut und arbeite ohnehin gern experimentell, deshalb ging es schnell voran
Die offizielle Bittorrent-Spezifikation selbst ist wirklich kurz und lässt sich in etwa einer Stunde lesen und verstehen https://www.bittorrent.org/beps/bep_0003.html
Allerdings gibt es sehr viele Erweiterungsprotokolle drumherum, und jeder Client unterstützt sie in unterschiedlichem Maß. Zum Beispiel wird oft zuerst Protokollverschlüsselung versucht, die in Wirklichkeit eher eine Verschleierung ist, und wenn das nicht klappt, wird mit dem normalen Protokoll weitergemacht
Wenn man nur offizielle
.torrent-Dateien wie bei Linux-Distributionen herunterladen möchte, ist der Schwierigkeitsgrad deutlich geringer. Meist gibt es nur eine Datei, einen Tracker, und die meisten Peers sprechen Standardprotokolle, sodass es auch hinter NAT ohne offene eingehende Ports gut funktioniertWenn man jedoch allgemeine Torrents möchte, insbesondere in der Grauzone, muss man nach und nach mehr hinzufügen: Parsen von Magnet-Links, DHT zur Peer-Erkennung und UPnP für automatisches Port-Mapping. Aber auch das lässt sich Funktion für Funktion in einzelne Schritte zerlegen. Je mehr Funktionen vorhanden sind, desto mehr Peers lassen sich finden und desto erfolgreicher funktioniert der Austausch
Es war ziemlich anspruchsvoll, und fast ein Monat ging dafür drauf, das Protokoll und die bencoding-Methode zu verstehen, die Gesamtstruktur im Kopf aufzubauen und dann den Code zu schreiben. Magnet und DHT werden noch nicht unterstützt
Es wurde gefragt, ob v2 und mutable torrents implementiert wurden. Dabei wurde der Wunsch geäußert, mutable torrents auf jeden Fall zu unterstützen