はじめに
すべての読者に良い一日を!
最近、あるプロジェクトでは、プログラムでトレントをダウンロードして配布し、その後ダウンロード済みのデータ用に新しいトレントファイルを作成する必要がありました。 当然、私は本当に車輪を再発明したくなかったので、Java用のBitTorrentライブラリのニッチにあるものを検索エンジンで調べることにしました。
引き渡しが私を非常に動揺させたと言いたいです。 言及された実装はごくわずかであり、それらも長い間更新されていませんでした。 Stackoverflowは以下を提案しました。
それでは、それぞれについて見ていきましょう。
- Azureus (現在はVuze)は、Javaで記述されたトレントクライアントです。 プロトコルの実装はプラグインを介して行われ、統合するのがより難しく、非常にコンパクトではなかったため、私には向いていません。
- Snark-サイトは消滅し、ライブラリの最後の更新は2003年でした。この間にBTには多くの変更があり、その1つはDHTです。
- 最後に-機会の主人公、この記事の説明オブジェクト、-少し後でjBitTorrent APIについて知ります 。
jBitTorrent APIの長所と短所
これは、JavaでBitTorrentプロトコルを実装するための実質的に唯一のスタンドアロンライブラリであるという事実にもかかわらず、何らかの形で一般に機能しますが、ベータステータスのままです。 SourceForgeプロジェクトの死んだフォーラム、そこに死んだバグ追跡システムもあります。これらすべては、発見されたバグの相談と修正に親切に同意してくれたプロジェクトの作者への書き込みを止めるものではありませんでした。
長所
- スタンドアロン実装
- 軽量(不要なクラスを安全に削除できます)
- 良いJavaDoc
- Javaのほぼ唯一の通常のBitTorrent実装
- 最も単純なトレントトラッカーとその他の小さなものの実装例が含まれています
短所
以下で説明するすべての欠点は現時点で当てはまります。プロジェクトの作者がそれらを修正し、プロジェクトが再び生き返ることを大いに期待しています。 少なくとも私は彼を放っておきません。
- 死んだコミュニティ(著者のみが回答し、その後電子メールで回答)
- いくつかのバグ(発見したことを以下に説明します)
jBitTorrentをクライアントとして使用するためのパターン
残念ながら、 jBitTorrentのサーバー側(トラッカー自体)を扱っていないため、それについては何も言えません。 すぐにやりたいと思わない限り。 したがって、トレントファイルを作成するためのテンプレートと、トレントを介してファイルをダウンロードするためのテンプレートの表示を開始しましょう。 ところで、 src / jBittorrentAPIには実装があります: ExampleCreateTorrent.javaおよびExampleDownloadFiles.java 。 また、トレントファイルをトラッカーに公開するためのAPIを示すクラスであるExamplePublish.javaがありますが、私はそれを使用しませんでした。 はい、これらの例はあまりにも多くロードされており、0.5リットルでは作成できません。
トレントファイルを作成する
// , TorrentProcessor tp = new TorrentProcessor(); // tp.setCreationDate(System.currentTimeMillis()); // tp.setCreator("jBittorrentAPI 1.0"); // tp.setComment("test"); // URL , - . , . tp.setAnnounceURL(null); // tp.setPieceLength(100); // tp.setEncoding("UTF-8"); // , - tp.setName(torrentSavedTo); // , File checkData = new File(torrentSavedTo); if(checkData.isDirectory()) { // File - tp.addFiles(checkData.listFiles()); } else { // , tp.addFile(checkData); } // , tp.setPieceLength() tp.generatePieceHashes(); // - byte[] generateTorrent = tp.generateTorrent(); File generateTorrentFile = new File(torrentName); try { generateTorrentFile.createNewFile(); } catch(IOException ex) { Logger.getLogger(DownloadTorrent.class.getName()).log(Level.SEVERE, null, ex); } try { DataOutputStream dos = new DataOutputStream(new FileOutputStream(generateTorrentFile)); try { dos.write(generateTorrent); dos.flush(); dos.close(); } catch(IOException ex) { Logger.getLogger(DownloadTorrent.class.getName()).log(Level.SEVERE, null, ex); } } catch(FileNotFoundException ex) { Logger.getLogger(DownloadTorrent.class.getName()).log(Level.SEVERE, null, ex); }
jBitTorrent APIでのtorrentファイルの作成は次のようになります。
TorrentProcessor.setTorrentData()
など、さらにいくつかの方法がありますが、それらはほとんど同じです。
シードせずにファイルをダウンロードする
ここでは、次の構成を使用します。
// - TorrentProcessor tp = new TorrentProcessor(); TorrentFile tf = tp.getTorrentFile(tp.parseTorrent(torrentPath)); DownloadManager dm = new DownloadManager(tf, Utils.generateID()); // dm.startListening(6882, 6889); dm.startTrackerUpdate(); while(true) { // , if(dm.isComplete()) { break; } try { Thread.sleep(1000); } catch(InterruptedException ex) { Logger.getLogger(DownloadTorrent.class.getName()).log(Level.SEVERE, null, ex); } } // dm.stopTrackerUpdate(); dm.closeTempFiles(); // , ( , TorrentProcessor.setName()) String torrentSavedTo = tp.getTorrentFile(tp.parseTorrent(torrentPath)).saveAs;
シードを使用してファイルをダウンロードする
必要ありませんでしたが、コードは文字通り半分になりました。
// - TorrentProcessor tp = new TorrentProcessor(); TorrentFile tf = tp.getTorrentFile(tp.parseTorrent(torrentPath)); DownloadManager dm = new DownloadManager(tf, Utils.generateID()); // dm.startListening(6882, 6889); dm.startTrackerUpdate(); dm.blockUntilCompletion(); // dm.stopTrackerUpdate(); dm.closeTempFiles(); // , ( , TorrentProcessor.setName()) String torrentSavedTo = tp.getTorrentFile(tp.parseTorrent(torrentPath)).saveAs;
ご覧のとおり、ここでは
DownloadManager.blockUntilCompletion()
メソッドが呼び出され、ピアとの作業を実装しています。
バグ、バグ、バグ
一般的に、正直に言うと、ここで説明するバグは重大ではありませんが、修正する必要がないという意味ではありません。 彼らはまだいくつかの不便をもたらします。
TorrentFile.printData()メソッドのエラー
このメソッドが呼び出されたときにのみ発生します。スクリーンショットを次に示します。
メソッドのソースコードを見ると、
this.piece_hash_values_as_hex.get(i)
をバイパスしていることがわかります
this.piece_hash_values_as_hex.get(i)
ここで
ArrayList
のサイズがゼロであるため、この例外がトリガーされます。
生成されたトレントファイルに複数のファイルを追加することの欠点
TorrentProcessor.addFile()
を使用して単一のファイルを追加する場合
TorrentProcessor.addFile()
すべてが正常です。 ただし、
TorrentProcessor.addFiles()
(List、Fileの配列、または
TorrentProcessor.addFile()
複数呼び出し
TorrentProcessor.addFiles()
を使用して複数のファイルを追加すると、次のようになります。
ここでわかるように、追加されるファイルへのフルパスがトレントファイルに追加されます(fuh、well、voice traffic!)。 これまでのところ、ここでの解決策は、たとえばフォルダーアーカイブを追加することです。
ファイルのアップロードエラー
エラー自体は実際には干渉しませんが、修正する必要があります。 例外がスローされた場合でも、ダウンロードはさらに続行され、ファイルの整合性が維持されます。 残念ながら、その時点ではスクリーンショットを作成できなかったため、クライアントの作業のログを次に示します。
run:
Contact Tracker. URL source = ***
{interval=3300, complete=6, peers=[B@1c184f4, min interval=60, incomplete=6}
Peer List updated from tracker with 22 peers
Piece completed by 109.62.187.159:35691 : 0 (Total dl = 100.0% )
Task completed
Sharing... Press Ctrl+C to stop client
Sharing... Press Ctrl+C to stop client
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
Sharing... Press Ctrl+C to stop client
at java.util.LinkedList.entry(LinkedList.java:365)
at java.util.LinkedList.remove(LinkedList.java:357)
at jBittorrentAPI.DownloadManager.optimisticUnchoke(DownloadManager.java:617)
at jBittorrentAPI.DownloadManager.unchokePeers(DownloadManager.java:608)
at jBittorrentAPI.DownloadManager.blockUntilCompletion(DownloadManager.java:171)
at torrentstealer.DownloadTorrent.run(DownloadTorrent.java:32)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Sharing... Press Ctrl+C to stop client
Sharing... Press Ctrl+C to stop client
クライアントはマルチスレッド化されているため、いくつかのトレントファイルがダウンロードされます。この出力はクライアントデバッグであるため、多少のゴミがあります。 極端な場合は、実行中のプログラムを一時停止してから再起動できます-jBitTorrent APIはダウンロードを再度ダウンロードするのではなく、 再開することをサポートします。
おわりに
まあ、それは基本的にそれです。 プロジェクトの作者がバグを修正するので、この投稿に興味がある場合は、Java Javaハブブログの読者に新しいバージョンについて通知するようにします。