I'm implementing the BitTorrent protocol in python, and so far I've been able to establish connections between peers and pass messages to them. I was messing around today with writing a piece request algorithm and I started off by requesting pieces in sequential order. If the peer doesn't have the piece, or if the piece was already requested, I'd just increment the index of the piece and see if the peer has that one.
I have a message passing loop that looks like this:
while dont_have_all_pieces:
write = [peer for peer in self.peerConnector.peers if peer.write_data != '']
read = self.peerConnector.peers[:]
rx_list, tx_list, x_list = select.select(read, write, [])
for peer in rx_list:
# get messages to read
for peer in tx_list:
# send messages to peers
if peer.unchoked:
peer.next_message_to_send = MakeNewRequest()
The way I started sending requests as shown above is if the peer unchoked me, then I could make a new request.
I noticed some weird things when observing the network traffic in wireshark. During some experiments I would prevent the sending of a request to a peer if I sent to that peer in a certain time interval. I noticed that some peers I was sending to quite heavily and some not at all.
After I took away that restriction, I saw that I was requesting pieces from peers faster than they could give them back to me, and wireshark would show "TCP Zero Window" warnings.
The last thing that I tried was to only request a piece from a peer if I had just received one from that peer. That seemed to work the best, since the peer that I was neglecting (my torrent only has 2 peers) is no servicing all of my piece requests, but it seems very slow. In 40 minutes I've received 37 pieces which is a little over 70Mb.
How many requests should I be sending a certain peer in a given time?
It seems that have 3 problems:
1) You don't keep track/status for each peer. So when you send a piece request to a peer you need to put in a status "downloading" and when the peer send you the piece back or rejected you put it back to "ready" for you next request
2) You are messing up the pieces with blocks (sub-pieces). Each piece has a number of smaller pieces. Usually the max size the you can request is 0x4000 / 16384 bytes. So you need to split your initial piece to sub-pieces of 16384 with the last one (probably) have a smaller one.
3) How many blocks / sub-pieces you send in a 'single request' ... you cannot just send a large number of sub-pieces requests as you will get rejected or even disconnected from the other side. Again, usually 6 sub-pieces at once it should be OK.
Unfortunately, those details are not really documented. You can find them only by debugging (wireshark rocks) & trying :)