NAME - A quick demo of what can be accomplished in (slightly) less than 100 lines


In truth, this is still a very basic demonstration of a full Net::BitTorrent-based client but I wanted to fit this into 100 comfortable lines.

It's certainly enough to get you started.

Synopsis - (Sorta) Complete Net::BitTorrent client in under 100 lines file.torrent
   or [options] [file ...]

   -t     --torrent     .torrent file to load
   -p     --port        TCP/UDP port opened for incoming connections
   -d     --directory   Base directory to store downloaded files
   --no-check           Skip integrity check at start
   --options            Advanced settings
   -?     --help        Display full documentation
   --version            Display version information

To get client-wide progress updates, press Ctrl+C. For more, see perldoc.



Open this .torrent file.

You may pass several -torrent parameters and load more than one .torrent torrent.


Port number opened to the world for incoming connections. This defaults to 0 and lets Net::BitTorrent bind to a random, unused port.


Relative or absolute directory used as a base directory for storage. By default, this is the current working directory.

Please see Net::BitTorrent::Torrent for related information.


If found, the files will not be checked for integrity and we assume that we have none of the data of this torrent.


Allows otherwise private settings to be changed. For example, to set the upload bandwidth limit... --options _set_max_ul_rate=8192 [...]

You may pass several --options parameters.




This section only makes sense when you view the source.

Line 8

If encryption is enabled, Net::BitTorrent::Peer relies on Math::BigInt to do all the 96bit math the MSE specification requires. This math is done for each and every encrypted connection so, using the slow, stock libraries will cause you all sorts of headaches.

Here, we prioritize using the easy-to-build Pari library. I suggest you do the same in your scripts if you leave encryption enabled.

Line 16

Uses Getopt::Long to parse any options and, if none are found, falls back to Pod::Usage and lists all available options.

Line 30

Shoves everything Getopt::Long couldn't parse and looks like a file on the system into the list of potential .torrent files.

Line 31

Prints usage info and exits if no torrents are in the aforementioned list.

Line 35

Creates Net::BitTorrent object which opens on the port defined with the -p command line parameter (falls back to 0).

If N::B fails to create the new object, the script croaks here with an error message.

Line 38

This is the function used later by the piece_hash_pass and piece_hash_pass callbacks.

It prints (among other things) the piece's index, the related infohash, and a rough estimate of the torrent's completion.

Line 48

This function is used by the incoming_packet and outgoing_packet callbacks to report various block-level status updates in both directions.

Line 56

This function saves resume data for every torrent loaded. For more information on resume data and how it's used, see

Line 61

Sets a handler to catch Ctrl+C key combinations. When triggered, it saves the resume data and dumps "verbose information" about each loaded torrent.

If this is triggered more than once in a 3 second period, the script will exit.

Line 66

Saves resume data on script exit.

Lines 67-83

Sets client-wide callbacks for incoming_packet, outgoing_packet, piece_hash_pass, and piece_hash_fail events. These in turn hand most of their data to functions described earlier.

Lines 84-94

Loops through each torrent file listed on the commandline...

Line 85

Attempts to load the torrent into a new Net::BitTorrent::Torrent object. The new object stores related data in the directory defined on the command line, if the user decided to skip hash checking, the torrent's status is set to START otherwise, it defaults to START_AFTER_CHECK. The Resume parameter is set to [.torrent's filename].resume.

If creating the new object fails, the script skips to the next potential torrent.

Line 91

Validates the new Net::BitTorrent::Torrent object object's data if the user hasn't disabled it on the command line.

Line 92

Prints a quick status line which includes the torrent's path, a snippet of the infohash, and an indication of whether or not the torrent allows the use or the DHT swarm.

Line 95

Sets a client-wide callback for file_error events.

Note that this callback is set after the torrents are hashchecked. I've done this because this event is triggered every time Net::BitTorrent::Torrent::File attempts to open the file and fails. So, unless the files are preexisting, the script would dump screens full of useless error messages.

Line 96-98

This nested loop is really more of a hack than useful code... it allows users to set otherwise private data in each loaded torrent. In the wrong hands, this can be dangerous, in the right hands, it's a great way to test activity in the swarm under various conditions without digging too deeply into the source. For more, see the --options ...option.

You'll probably not need anything that messes with N::B's internals in your script.

Line 99

Goes to work and takes a short nap between loops to save the CPU.


This script used to be installed with Net::BitTorrent as

See Also

For more examples, see the files under the /tatoeba/ directory.


Sanko Robinson <> -


License and Legal

Copyright (C) 2008-2009 by Sanko Robinson <>

This program is free software; you can redistribute it and/or modify it under the terms of The Artistic License 2.0. See the LICENSE file included with this distribution or For clarification, see

When separated from the distribution, all POD documentation is covered by the Creative Commons Attribution-Share Alike 3.0 License. See For clarification, see

Neither this module nor the Author is affiliated with BitTorrent, Inc.