DEV Community

rohit20001221
rohit20001221

Posted on

⚡ I Built a BitTorrent Client in Go — And Finally Understood How Torrents Work

I used to think torrents were magic.

Files downloading from “somewhere”… insanely fast… no server?

So I decided to break that illusion and built a minimal BitTorrent client in Go.

👉 Source code: https://github.com/rohit20001221/ripple


🧠 What is BitTorrent (Really)?

At its core, BitTorrent is simple:

  • Split a file into pieces
  • Download pieces from multiple peers
  • Verify everything using hashes

No central server. Just a swarm of peers.


🏗️ High-Level Architecture


📦 Step 1: Parsing the .torrent File

A .torrent file is bencoded data containing:

  • Tracker URL
  • File metadata
  • Piece hashes

🔑 Info Hash (Critical)

bencode.Marshal(&buf, t.Info)
sha1(buf.Bytes())
Enter fullscreen mode Exit fullscreen mode

This hash uniquely identifies the torrent across the network.


🌐 Step 2: Finding Peers

We contact the tracker with:

  • info_hash
  • peer_id
  • port

Tracker returns peers in compact format:

[IP (4 bytes)] [PORT (2 bytes)]
Enter fullscreen mode Exit fullscreen mode

🤝 Step 3: Handshake

Before anything else, peers must agree:

handshake.SetInfoHash(...)
handshake.SetPeerID(...)
Enter fullscreen mode Exit fullscreen mode

If the hash doesn’t match → connection closed.


🧩 Step 4: Bitfield (Who Has What?)

Each peer sends a bitfield.

Each bit represents whether a piece exists:

func (bf BitField) HasIndex(index int) bool {
    return bf[byteIndex]>>uint(7-offset)&1 != 0
}
Enter fullscreen mode Exit fullscreen mode

⚡ Step 5: Worker Pool Design

This is where performance comes in.

  • Pieces → tasks
  • Peers → workers
  • Channels → coordination

🧱 Step 6: Breaking Pieces into Blocks

Each piece is split into 16KB blocks:

const MAX_BLOCK_SIZE = 16384
Enter fullscreen mode Exit fullscreen mode

📥 Step 7: Download Flow


🔁 Step 8: Fault Tolerance

Peers are unreliable.

So I requeue failed tasks:

c.TaskQueue <- task
Enter fullscreen mode Exit fullscreen mode

🔐 Step 9: Integrity Check

Every piece is verified:

sha1(piece) == expectedHash
Enter fullscreen mode Exit fullscreen mode

💾 Step 10: Writing the File

Pieces arrive out of order.

So we use random access:

outFile.Seek(offset, 0)
outFile.Write(piece)
Enter fullscreen mode Exit fullscreen mode

🧠 What I Learned

  • BitTorrent is simple but powerful
  • Concurrency is a game changer
  • Real systems must handle failure gracefully
  • Protocols are just structured bytes

💡 Future Improvements

  • Upload capability
  • Resume downloads

🎯 Final Thoughts

Building a BitTorrent client was one of the most educational projects I’ve done.

It forced me to understand:

  • Networking
  • Concurrency
  • Distributed systems

⭐ If you liked this

Top comments (0)