📜 ⬆️ ⬇️

Using BitTorrent in Java: jBitTorrent API

Introduction



Good day to all readers!

Recently, in one project, I needed to programmatically download and distribute torrents, and later create new torrent files to the already downloaded data. Naturally, I really didn’t want to reinvent the wheel, and I decided to look in a search engine for what is in the niche of BitTorrent libraries for Java.
I want to say that the issue made me very upset. Only a few implementations were mentioned, and even those were not updated for a long time. Stackoverflow prompted the following:
')


Now go through each of them.

  1. Azureus , now Vuze, is a torrent client written in Java. It does not suit me, because the implementation of the protocol goes through plug-ins, and it was more difficult to integrate and not very compact.
  2. Snark - the site died, and the last library update was in 2003, during this time there were many changes in BT, one of which is DHT.
  3. Finally - the hero of the occasion, the object of the description in this article, get to know the jBitTorrent API , about it just below.


Pros and cons of the jBitTorrent API



Despite the fact that it is practically the only stand-alone Java BitTorrent implementation library of the protocol, which somehow works at all, it is still in beta status. The dead forum on the SourceForge project , the deadly bug tracking system is the same — it didn’t stop me to write to the author of the project, who kindly agreed to consult and fix the found bugs.

Virtues




disadvantages


All of the shortcomings described below relate to the current moment, there is great hope that the author of the project will correct them, and the project will come to life again. At least I won't leave him alone.



JBitTorrent usage templates as a client



Unfortunately, I did not deal with the server side of jBitTorrent (the tracker itself), so I can’t say anything about it. Unless I hope to do it soon. Therefore, let's proceed to viewing the templates for creating a torrent file and the template for downloading files through a torrent. By the way, src / jBittorrentAPI has implementations: ExampleCreateTorrent.java and ExampleDownloadFiles.java . There is also ExamplePublish.java , a class that shows the torrent file publishing API on the tracker, but I have not used it. Yes, these examples are too heavy, you can’t figure it out without half a liter.

Create a torrent file


// ,    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); } 


This is how creating a torrent file in the jBitTorrent API . There are several other ways, for example, TorrentProcessor.setTorrentData() , but they are almost the same.

Download files without sitting


Here we use the following construction:
  //  - 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; 


Download files with seated


I did not need it, but the code is literally reduced by half, if not more:
  //  - 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; 


As you can see, the DownloadManager.blockUntilCompletion() method is called here, which implements the work with peers.

Bugs, bugs, bugs



In general, to be honest, the bugs described here are not critical, although this does not mean that you do not need to correct them. Some inconvenience they still deliver.

Error in TorrentFile.printData ()


It occurs only in the case of calling this method, here is a screenshot:



If you look at the source code of the method, you can see that when you this.piece_hash_values_as_hex.get(i) this very exception works because the size of the ArrayList is zero here.

The disadvantage of adding multiple files to the generated torrent file


When adding a single file using TorrentProcessor.addFile() everything is fine. But when adding multiple files using TorrentProcessor.addFiles() (List array, File, or multiple TorrentProcessor.addFile() call), the following happens:



As you can see here, the full path to the file being added is added to the torrent file (eh, well, a speech turn!). For now, the output here is to add a folder archive, for example.

Error uploading files


The error itself does not really interfere, although it is necessary to correct it. The download also continues further, even if an exception was thrown, the files retain integrity. Unfortunately, I could not take a screenshot at that moment, so here is the log of my client's work:
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


The client causes multithreaded downloads for several torrent files, and this output is client debugging, so there is some garbage. In extreme cases, you can pause the running program and run it again - the jBitTorrent API supports resuming, not downloading again.

Conclusion



Well, in principle, that's all. As the bug fixes by the author of the project, I will try to notify the readers of Habrablog “Java” about new versions if this post is interesting to you.

Source: https://habr.com/ru/post/117116/


All Articles