世界を動かす技術を、日本語で。

Show HN: ゼロからBitTorrentクライアントを作成しました

概要

Go-Torrentは、Go言語で実装されたBitTorrentクライアント。 Bencodeエンコーディングや.torrentファイル解析、ピア通信などの主要機能を搭載。 シングル・マルチファイル両対応のダウンロード機能。 HTTPトラッカー、ピア管理、進捗追跡などもサポート。 今後はMagnetリンクやDHT対応も計画中。

Go-Torrent: Go言語によるBitTorrentクライアント

  • Go-Torrent は、 BitTorrentプロトコル に準拠した ファイルダウンロード クライアント
  • Bencodeのエンコード/デコード 全型対応
    • 文字列、整数、リスト、辞書のサポート
    • 堅牢なエラー処理 とバリデーション
  • Torrentファイル処理 機能
    • .torrentファイル解析 (シングル・マルチ両対応)
    • info hash計算、ピースハッシュ抽出
    • 標準的な.torrentファイル項目全対応
  • ピア発見・通信機能
    • HTTPトラッカー 対応
    • ピアハンドシェイク プロトコル実装
    • BitTorrentメッセージプロトコル 全対応
    • ピア接続管理
  • ダウンロード機能
    • ピース・ブロック管理
    • 並列ダウンロード
    • 進捗追跡
    • シングル・マルチファイル両対応のファイル組立
    • ブロック単位のストレージ管理
  • プロジェクト構成
    • cmd/: コマンドラインインターフェース
    • internal/: 内部パッケージ
      • bencode/: Bencode処理
      • torrent/: Torrentファイル処理
      • tracker/: トラッカー通信
      • peer/: ピア通信
      • download/: ダウンロード管理
    • pkg/: 公開用パッケージ

必要条件・インストール

  • Go 1.21以上 必須
  • インストール手順
    • git clone https://github.com/yourusername/go-torrent.git
    • cd go-torrent
    • go mod download

利用方法・開発状況

  • 利用方法は 今後追加予定
  • 積極開発中、進捗はcheckpoint.md参照

今後の予定機能

  • Magnetリンク対応
  • メタデータ交換プロトコル
  • DHT(分散ハッシュテーブル)対応

謝辞・参考資料

  • BitTorrent Protocol Specification
  • Bencode Specification

開発者からのメッセージ

  • 2023年後半 からプログラミングを開始
  • BitTorrentクライアント開発 を目標に挑戦
  • 新しい技術へのチャレンジを楽しむ姿勢

Hackerたちの意見

これ、すごいね!私もこんなの考えてたんだ。どれくらい大変だった?それと、どのくらい「完成度」があると思う?DHTやマグネット、あの複雑なNATトラバーサルのことも対応してるのかな?私にとっての一番の障害は、野良トレントの大半に対応するクライアントに必要な機能の完全なリストが分からないことなんだ。トレントにはいろんなプロトコルがあるみたいで、全体のリストすら知らないし、それぞれが何をするのかも分からない。

確かに挑戦的だったよ。プロトコルに慣れるのにほぼ1ヶ月かかったし、bencodingの仕組みとか、頭の中でモデルを作って、最終的にコードを書くまでに至った。マグネットとDHTはまだ追加してない。

難しさは、経験やプログラミング言語への慣れ、実験的なマインドセットに大きく依存するよ。参考までに言うと、先週GoでBittorrentクライアントを作ることにしたんだけど、1週間で投稿したプロジェクトの80%くらいまで進んでる。まあ、Goにはかなりの経験があるし、プロトコルやネットワークについても詳しいから、実験は自分にとって第二の天性になってるんだ。もし興味があれば、Bittorrentの主要な仕様は実際にはかなり小さいから、1時間くらいで簡単に読んで理解できるよ:https://www.bittorrent.org/beps/bep_0003.html Bittorrentに関する周辺情報もたくさんあるけど、今のところの経験では、多くのクライアントが異なるレベルのサポートをしているね。例えば、プロトコル暗号化(実際には難読化)を使って通信しようとするけど、うまくいかなかったら設定に応じて通常のプロトコルに戻るみたいな感じ。もし、ウェブサイトにある.torrentファイルを使ってLinuxディストリビューション(例えばDebian)をダウンロードしたいだけなら、比較的簡単だよ。ファイルは1つだけで、トラッカーもあって、通常のプロトコルを使っているピアもたくさんいるし、NATの背後にいるときは接続を待たなくても大丈夫なんだ。もちろん、コンテンツのグレーゾーンに入ると、マグネットリンクをパースしたり、DHTを使ってピアを見つけたり、UPnPを実装してモデムのポートを自動的にマッピングしようとしたりする必要があるけど、それもまた反復的なプロセスだから、一つずつ作り上げていけばいいんだ。機能が増えれば増えるほど、発見できるピアが増えて、成功する交換も増えるよ。

マグネットリンクには対応してる? 編集: あ、予定してる機能だね。

まだだよ。すぐに追加するつもり。

素晴らしい!見た目もクリーンでシンプルだね。提案なんだけど、READMEに実際に.torrentファイルをダウンロードするための簡単な使い方を一行で追加してほしいな。例えば、./go-torrent My-Linux-Distro-Wink-ISO.torrent それと、もしtorrent.ParseFromUrlも追加したらボーナスポイント!みんな、自分の精神的な旅のためにこれをやるべきだよ。

提案ありがとう、感謝するよ。

いい仕事だね!ちょっとお知らせだけど、bencodeデコーダーで動的割り当てサイズを制限した方がいいかも。トレントやアナウンスからの信頼できない入力だから、悪意のある入力が文字列解析中に非常に大きな割り当てを要求してクライアントをDoSする可能性がある。良い上限は入力の残りの長さにするのがいいかも。ちゃんとしたトレントはファイルの残りの部分より長い文字列を含むことができないから。

指摘してくれてありがとう。これをやるリストに追加したよ。

すごい!大学時代を思い出すなぁ。ジョージアテックのネットワーキングクラスで、これを最終プロジェクトとしてやったんだ。コードはもう失くしちゃったけど、学んだことは今でも生きてるよ :) こういうプロジェクトは新しい言語を学ぶのにもいい方法だね!

これにGUIを追加するのって、どれくらい大変なんだろう?過去にGOのGUI実装をあまり見たことがない気がする。

たくさんあるよ!https://github.com/go-graphics/go-gui-projects 私のお気に入りはImGuiのラッパーだね。https://github.com/AllenDang/giu 一番機能が豊富なのはおそらくunisonだけど、他のプロジェクト以外で使ってる人はあまりいないかも(https://gurpscharactersheet.com)、だからドキュメントは少なめだね。https://github.com/richardwilkes/unison GioはGUIの考え方がちょっと違ってて、Tailscaleやgotraceuiで使われてるよ。https://gioui.org Wailsはウェブ開発に慣れてるならすごくいいよ。https://wails.io GTK4のバインディングも良さそうだね。https://github.com/diamondburned/gotk4 Cogent Coreも面白そうだけど、Goの代わりにオーディンプログラミング言語を使うようになってからは触る時間がなかったな。https://www.cogentcore.org/core 個人的にはFyneには問題しかなかったけど(特にパフォーマンスに関して、いろんなコンピュータやOSで)、でも多分一番人気の選択肢だね。https://fyne.io

非GO開発者なんだけど、なんで古いGoバージョンの1.21を使ってるの?古いリリースにこだわる理由があるのかな?追記:10ヶ月前に非推奨になったみたいだね。

Windows 7のサポートが、古いGoLangリリースにこだわる理由の一つだね。Go 1.21.4以前のプロジェクトは、すべてのWindowsリリースと2009年以降に作られたコンピュータで動くけど、v1.21.5にバージョンアップすると、最近のコンピュータとWin10、11でしか動かなくなるから、特にメリットはないよ。https://github.com/golang/go/issues/64622

READMEはおそらくAI生成だね。実際のgo.modファイルではGoバージョンが1.23.1と記載されてて、Go 1.23.1以上が必要ってことを示してるよ。[1] https://github.com/piyushgupta53/go-torrent-client/blob/6130... [2] https://go.dev/doc/modules/gomod-ref#go-notes

いいね!codecraftersには、プロセスを少しガイドしてくれるチャレンジがあって、テストとかも提供されてるんだ。無料の月にちょっと遊んでみたけど、楽しかったよ: https://app.codecrafters.io/courses/bittorrent/overview

v2とミュータブルトレントはやった?お願いだから、誰かミュータブルトレントを実装してくれ!

これを作るために何を参考にしたの?プロトコルを読んだの、それとも他の実装を見たの?こういうものをゼロから作る人たちって、どうやってるのかいつも気になるんだよね。

面白いことに(そうでもないかもしれないけど)、先週BittorrentクライアントをGoで書き始めたんだ。AIやLLMを使ってコーディングするのはあまり好きじゃなくて、実際に学ぶことが目的なんだ。AIが書いたコードをただ提供するんじゃなくてね。最初のステップは、プロトコルの実際の仕様があるかどうかを確認することだ。Bittorrentの場合、仕様はあるけど、ちょっと簡潔すぎるかな。基本的にはこれが仕様だよ:https://www.bittorrent.org/beps/bep_0003.html ここにいくつかの追加拡張もある:https://www.bittorrent.org/beps/bep_0000.html 仕事を小さなステップに分けて、それぞれが何らかの結果を出すことが大事だよ。例えば、.torrentファイルのパースから始めたんだけど、そのためにはbencodingを実装しなきゃいけなかった。面白かったのは、Arch Linuxの.torrentをダウンロードしたら、基本的に間違ってたことがわかったんだ。仕様には書かれていないurl-listキーがあったからね。そしたら、そのことについて調べる羽目になったんだけど(結局、これが関係してた:https://www.bittorrent.org/beps/bep_0019.html)。最終的には、Debian Linuxの.torrentファイルを無事にパースできたよ。それからトラッカーのAnnounce HTTPリクエストとピアプロトコルの実装に進んだんだけど、ピアプロトコルは難しかった。そういう時こそ実験的なマインドセットが役立つんだ。DebianのトレントからアナウンスURLを取り除いてKTorrentに読み込ませたら、ピアが見つからなかったんだ。そこで「ピアを追加」オプションを使って自分のクライアントを追加して、どんなメッセージが送られてくるかを確認したり、それをKTorrentに送る実装を進めたりした。試行錯誤とデバッグの連続だったよ。時々、仕様に載ってない小さなプロトコルの詳細についてChatGPTに聞かなきゃいけなかったことを告白するよ。クライアントが時間をかけて実装してきたけど、あまり文書化されていない詳細もたくさんあるんだ。どのピースをダウンロードするか、どのピアを選ぶか、「チョーク」や「アンチョーク」をどうするかなど、定義があまりはっきりしてないんだ。でも、ウェブ検索がすごく役立つよ。それに、https://wiki.theory.org/Main_Page もいい情報があるから、ぜひチェックしてみて。今は、自分のローカルKTorrentでトレントを完全にダウンロード・アップロードできるところまで来たから、次のステップはトラッカーからピアを取得して、ピースをダウンロードしてファイルに保存するアルゴリズムを作ることだね。これが何かの参考になればいいな。プロセスについて具体的な質問があったら教えてね。