我正在尝试了解种子文件的工作原理,并编写了python脚本以将连接请求发送到跟踪器URL并获得一些响应。我按照协议准备了连接消息,并使用sock.send()
方法通过ip和端口发送了该消息(检查get_peers_list
函数,它的功能不完整,因为我陷入了连接请求部分)。我收到超时错误,无法继续前进。这是我的脚本:
from bcoding import bdecode, bencode
import time, hashlib
from urllib.parse import urlparse
import socket
import random
from struct import pack, unpack
def load_from_path(path):
with open(path, 'rb') as file:
contents = bdecode(file)
#random seed to generate peer_id
seed = str(time.time())
return {
"torrent_file": contents,
"piece_length": contents['info']['piece length'],
"pieces": contents['info']['pieces'],
"info_hash": hashlib.sha1( bencode(contents['info']) ).digest(),
"peer_id": hashlib.sha1(seed.encode('utf-8')).digest(),
"announce": contents['announce']
}
class UdpTrackerConnection():
def __init__(self):
self.conn_id = pack('>Q', 0x41727101980)
self.action = pack('>I', 0)
self.trans_id = pack('>I', random.randint(0, 100000))
def to_bytes(self):
return self.conn_id + self.action + self.trans_id
def from_bytes(self, payload):
self.action, = unpack('>I', payload[:4])
self.trans_id, = unpack('>I', payload[4:8])
self.conn_id, = unpack('>Q', payload[8:])
def _read_from_socket(sock):
data = b''
while True:
try:
buff = sock.recv(4096)
print("got some response", buff)
if len(buff) <= 0:
break
data += buff
except socket.error as e:
print(e)
break
except Exception:
print("Recv failed")
break
return data
def get_peers_list(torrent):
parsed = urlparse(torrent['announce'])
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.settimeout(4)
ip, port = socket.gethostbyname(parsed.hostname), parsed.port
tracker_connection_input = UdpTrackerConnection()
message = tracker_connection_input.to_bytes()
sock.sendto(message, (ip, port))
try:
response = _read_from_socket(sock)
except socket.timeout as e:
print("Timeout : %s" % e)
return
except Exception as e:
print("Unexpected error when sending message : %s" % e.__str__())
return
tracker_connection_output = UdpTrackerConnection()
path_to_torrent = "test.torrent"
torrent = load_from_path(path_to_torrent)
get_peers_list(torrent)
我得到这个输出
got some response b'\x00\x00\x00\x00\x00\x00\xe2\x9b{E\xf0U\xfb\x9b\xf2\xc6'
timed out
我对这里的套接字很陌生,任何帮助都很好。
您有一个字节字符串,您需要像这样将每个字节转换为其等效的整数。
>>> mt = b'\x00\x00\x00\x00
>>> intg = list(b)
>>> intg
[0, 0, 0, 0]
此document可能会对您有所帮助。