我正在尝试使用https://wiki.theory.org/BitTorrent_Tracker_Protocol从跟踪器获取同行列表
但是网上大多数可用的torrent文件都使用udp
跟踪器。上面的网站适用于HTTP跟踪器。使用基于HTTP的跟踪器的种子文件会出现错误。(Passkey error , or hash error or user error or 404 not found response
)
现在,我对所有HTTP跟踪器的请求代码如下所示:
payload = urllib.urlencode(payload)
for ann in self.torrent.announce_list:
if("udp" not in ann[0]):
url = ann[0]
print "Encoded Request URL :",(url + "?" + payload)
print "Requesting Tracker for Peer List"
try:
response = urllib.urlopen(url + "?" + payload).read()
print "RESPONSE :",response
except Exception, e:
print e
我已经将我的请求URL与uTorrent使用Wireshark发出的请求进行了交叉检查。他们都匹配。信息哈希已正确生成。
如何从UDP和HTTP跟踪器检索对等列表?我试图不使用任何外部库,例如lib-torrent。一些指导确实会有所帮助。
python大神给出的解决方案
以下代码对我有用。使用跟踪器URL和带有所有URL参数的有效负载字典调用announce_udp()。
import binascii, urllib, socket, random, struct
from bcode import bdecode
from urlparse import urlparse, urlunsplit
def announce_udp(tracker,payload):
tracker = tracker.lower()
parsed = urlparse(tracker)
# Teporarly Change udp:// to http:// to get hostname and portnumbe
url = parsed.geturl()[3:]
url = "http" + url
hostname = urlparse(url).hostname
port = urlparse(url).port
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(8)
conn = (socket.gethostbyname(hostname), port)
#sock.bind((socket.gethostname(),s_port))
#Get connection ID
req, transaction_id = udp_create_connection_request()
sock.sendto(req, conn);
buf = sock.recvfrom(2048)[0]
connection_id = udp_parse_connection_response(buf, transaction_id)
#Annoucing
s_port = sock.getsockname()[1] #get port number to which socket is connected
req, transaction_id = udp_create_announce_request(connection_id, payload,s_port)
sock.sendto(req, conn)
print "Announce Request Sent"
buf = sock.recvfrom(2048)[0]
print "Response received"
return udp_parse_announce_response(buf, transaction_id)
def udp_create_announce_request(connection_id, payload, s_port):
action = 0x1 #action (1 = announce)
transaction_id = udp_get_transaction_id()
# print "2.Transaction ID :", transaction_id
buf = struct.pack("!q", connection_id) #first 8 bytes is connection id
buf += struct.pack("!i", action) #next 4 bytes is action
buf += struct.pack("!i", transaction_id) #followed by 4 byte transaction id
buf += struct.pack("!20s", urllib.unquote(payload['info_hash'])) #the info hash of the torrent we announce ourselves in
buf += struct.pack("!20s", urllib.unquote(payload['peer_id'])) #the peer_id we announce
buf += struct.pack("!q", int(urllib.unquote(payload['downloaded']))) #number of bytes downloaded
buf += struct.pack("!q", int(urllib.unquote(payload['left']))) #number of bytes left
buf += struct.pack("!q", int(urllib.unquote(payload['uploaded']))) #number of bytes uploaded
buf += struct.pack("!i", 0x2) #event 2 denotes start of downloading
buf += struct.pack("!i", 0x0) #IP address set to 0. Response received to the sender of this packet
key = udp_get_transaction_id() #Unique key randomized by client
buf += struct.pack("!i", key)
buf += struct.pack("!i", -1) #Number of peers required. Set to -1 for default
buf += struct.pack("!i", s_port) #port on which response will be sent
return (buf, transaction_id)
def udp_parse_announce_response(buf, sent_transaction_id):
#print "Response is:"+str(buf)
if len(buf) < 20:
raise RuntimeError("Wrong response length while announcing: %s" % len(buf))
action = struct.unpack_from("!i", buf)[0] #first 4 bytes is action
res_transaction_id = struct.unpack_from("!i", buf, 4)[0] #next 4 bytes is transaction id
if res_transaction_id != sent_transaction_id:
raise RuntimeError("Transaction ID doesnt match in announce response! Expected %s, got %s"
% (sent_transaction_id, res_transaction_id))
print "Reading Response"
if action == 0x1:
print "Action is 3"
ret = dict()
offset = 8; #next 4 bytes after action is transaction_id, so data doesnt start till byte 8
ret['interval'] = struct.unpack_from("!i", buf, offset)[0]
print "Interval:"+str(ret['interval'])
offset += 4
ret['leeches'] = struct.unpack_from("!i", buf, offset)[0]
print "Leeches:"+str(ret['leeches'])
offset += 4
ret['seeds'] = struct.unpack_from("!i", buf, offset)[0]
print "Seeds:"+str(ret['seeds'])
offset += 4
peers = list()
x = 0
while offset != len(buf):
peers.append(dict())
peers[x]['IP'] = struct.unpack_from("!i",buf,offset)[0]
print "IP: "+socket.inet_ntoa(struct.pack("!i",peers[x]['IP']))
offset += 4
if offset >= len(buf):
raise RuntimeError("Error while reading peer port")
peers[x]['port'] = struct.unpack_from("!H",buf,offset)[0]
print "Port: "+str(peers[x]['port'])
offset += 2
x += 1
return ret,peers
else:
#an error occured, try and extract the error string
error = struct.unpack_from("!s", buf, 8)
print "Action="+str(action)
raise RuntimeError("Error while annoucing: %s" % error)
def udp_create_connection_request():
connection_id = 0x41727101980 #default connection id
action = 0x0 #action (0 = give me a new connection id)
transaction_id = udp_get_transaction_id()
print "1.Transaction ID :", transaction_id
buf = struct.pack("!q", connection_id) #first 8 bytes is connection id
buf += struct.pack("!i", action) #next 4 bytes is action
buf += struct.pack("!i", transaction_id) #next 4 bytes is transaction id
return (buf, transaction_id)
def udp_parse_connection_response(buf, sent_transaction_id):
if len(buf) < 16:
raise RuntimeError("Wrong response length getting connection id: %s" % len(buf))
action = struct.unpack_from("!i", buf)[0] #first 4 bytes is action
res_transaction_id = struct.unpack_from("!i", buf, 4)[0] #next 4 bytes is transaction id
if res_transaction_id != sent_transaction_id:
raise RuntimeError("Transaction ID doesnt match in connection response! Expected %s, got %s"
% (sent_transaction_id, res_transaction_id))
if action == 0x0:
connection_id = struct.unpack_from("!q", buf, 8)[0] #unpack 8 bytes from byte 8, should be the connection_id
return connection_id
elif action == 0x3:
error = struct.unpack_from("!s", buf, 8)
raise RuntimeError("Error while trying to get a connection response: %s" % error)
pass
def udp_get_transaction_id():
return int(random.randrange(0, 255))
用大写字母拆分字符串,但忽略AAA Python Regex - python我的正则表达式:vendor = "MyNameIsJoe. I'mWorkerInAAAinc." ven = re.split(r'(?<=[a-z])[A-Z]|[A-Z](?=[a-z])', vendor) 以大写字母分割字符串,例如:'我的名字是乔。 I'mWorkerInAAAinc”变成…
Python sqlite3数据库已锁定 - python我在Windows上使用Python 3和sqlite3。我正在开发一个使用数据库存储联系人的小型应用程序。我注意到,如果应用程序被强制关闭(通过错误或通过任务管理器结束),则会收到sqlite3错误(sqlite3.OperationalError:数据库已锁定)。我想这是因为在应用程序关闭之前,我没有正确关闭数据库连接。我已经试过了: connectio…
从Flask路由进行Python异步调用 - python我想在每次执行Flask路由时执行一个异步函数。为什么abar函数从不执行?import asyncio from flask import Flask async def abar(a): print(a) loop = asyncio.get_event_loop() app = Flask(__name__) @app.route("/…
在Flask中测试文件上传 - python我在Flask集成测试中使用Flask-Testing。我有一个表单,该表单具有我要为其编写测试的徽标的文件上传,但是我不断收到错误消息:TypeError: 'str' does not support the buffer interface。我正在使用Python3。我找到的最接近的答案是this,但是它对我不起作用。这是我的许多尝…
从文件中读取用户名和密码[重复] - pythonThis question already has answers here: How to read a file line-by-line into a list? (28个答案) 2年前关闭。 如何在Python中逐行读取文本(例如用户名和密码)?例如,我可以在shell / bash中实现此目的:#!/bin/bash AUTH='/aut…