Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
BitTorrent客户端:从跟踪器获取对等列表[Python]_Python_Get_P2p_Bittorrent - Fatal编程技术网

BitTorrent客户端:从跟踪器获取对等列表[Python]

BitTorrent客户端:从跟踪器获取对等列表[Python],python,get,p2p,bittorrent,Python,Get,P2p,Bittorrent,我正在尝试使用 但是网络上可用的大多数torrent文件都使用udp跟踪器。上面的网站是为HTTP跟踪器提供的。带有基于HTTP的跟踪器的torrent文件给出了一个错误。(密钥错误、散列错误、用户错误或404找不到响应) 现在,我对所有HTTP跟踪器的请求代码如下所示: payload = urllib.urlencode(payload) for ann in self.torrent.announce_list: if("udp" not in an

我正在尝试使用

但是网络上可用的大多数torrent文件都使用
udp
跟踪器。上面的网站是为HTTP跟踪器提供的。带有基于HTTP的跟踪器的torrent文件给出了一个错误。(
密钥错误、散列错误、用户错误或404找不到响应

现在,我对所有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
我已经对照uTorrent使用wireshark发出的请求交叉检查了我的请求URL。他们都很般配。正在正确生成信息哈希


如何从UDP和HTTP跟踪器中检索对等列表?我尽量不使用任何外部库,如lib torrent。一些指导会非常有用。

以下代码对我很有用。使用跟踪器URL调用annound_udp(),使用所有URL参数调用有效负载字典

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))
导入binascii、urllib、套接字、随机、结构
从bcode导入bdecode
从URLPRASE导入URLPRASE,URLUNSPLACT
def通告U udp(跟踪器、有效负载):
tracker=tracker.lower()
parsed=urlparse(跟踪器)
#t临时将udp://更改为http://以获取主机名和端口号
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(主机名),端口)
#sock.bind((socket.gethostname(),s_端口))
#获取连接ID
请求,事务\u id=udp\u创建\u连接\u请求()
插座发送至(要求,连接);
buf=sock.recvfrom(2048)[0]
连接\u id=udp\u解析\u连接\u响应(buf,事务\u id)
#注释
s_port=sock.getsockname()[1]#获取套接字连接到的端口号
请求,事务id=udp创建宣告请求(连接id,有效负载,s端口)
插座发送至(要求,连接)
打印“已发送通知请求”
buf=sock.recvfrom(2048)[0]
打印“收到答复”
返回udp解析公告响应(buf,事务id)
def udp_创建_公告_请求(连接id、负载、s_端口):
动作=0x1#动作(1=宣布)
事务\u id=udp\u获取\u事务\u id()
#打印“2.Transaction ID:”,事务\u ID
buf=struct.pack(“!q”,连接id)#前8个字节是连接id
buf+=struct.pack(“!i”,action)#接下来的4个字节是action
buf+=struct.pack(“!i”,事务id)#后跟4字节事务id
buf+=struct.pack(“!20s”,urllib.unquote(payload['info_hash'))#我们在其中宣布的torrent的信息散列
buf+=struct.pack(“!20s”,urllib.unquote(有效负载['peer\u id'))#我们宣布的peer\u id
buf+=struct.pack(“!q”,int(urllib.unquote(有效负载['download']))#下载的字节数
buf+=struct.pack(“!q”,int(urllib.unquote(payload['left']))#剩余字节数
buf+=struct.pack(“!q”,int(urllib.unquote(负载['upload']))#上载的字节数
buf+=struct.pack(“!i”,0x2)#事件2表示开始下载
buf+=结构包(“!i”,0x0)#IP地址设置为0。已收到对此数据包的发件人的响应
key=udp_get_transaction_id()#由客户端随机分配的唯一密钥
buf+=结构包(“!i”,键)
buf+=struct.pack(“!i”,-1)#需要的对等数量。默认设置为-1
buf+=struct.pack(“!i”,s#端口)#将在其上发送响应的端口
返回(buf,事务处理id)
def udp解析通告响应(buf,已发送事务id):
#打印“响应为:”+str(buf)
如果len(buf)<20:
raise RUNTIMERROR(“宣布时响应长度错误:%s”%len(buf))
action=struct.unpack_from(“!i”,buf)[0]#前4个字节是action
res_transaction_id=struct.unpack_from(“!i”,buf,4)[0]#接下来的4个字节是事务id
如果资源事务id!=已发送\u事务\u id:
raise RUNTIMERROR(“公布响应中的事务ID不匹配!应为%s,已为%s”
%(已发送交易id、已恢复交易id))
打印“阅读响应”
如果操作==0x1:
打印“动作是3”
ret=dict()
偏移量=8#操作后的下4个字节是事务id,所以数据直到字节8才开始
ret['interval']=结构从(“!i”,buf,offset)解包[0]
打印“间隔:”+str(ret['Interval']))
偏移量+=4
ret['leeches']=struct.unpack_from(“!i”,buf,offset)[0]
打印“Leeches:+str(ret['Leeches']))
偏移量+=4
ret['seeds']=struct.unpack_from(“!i”,buf,offset)[0]
打印“种子”:+str(ret['Seeds'])
偏移量+=4
对等方=列表()
x=0
而偏移量!=len(buf):
peers.append(dict())
对等方[x]['IP']=结构从(“!i”,buf,offset)解包[0]
打印“IP:+socket.inet_ntoa(结构包(“!i”,对等[x]['IP']))
偏移量+=4
如果偏移量>=长度(buf):
引发运行时错误(“读取对等端口时出错”)
对等方[x]['port']=结构从(“!H”,buf,offset)解包[0]
打印“端口:”+str(对等[x]['Port'])
偏移量+=2
x+=1
返回ret,同行
其他:
#发生错误,请尝试提取错误字符串
error=struct.unpack_from(“!s”,buf,8)
打印“Action=”+str(操作)
引发运行时错误(“注释时出错:%s”%Error)
def udp_创建_连接_请求():
连接id=0x41727101980#默认连接id
action=0x0#action(0=给我一个新的连接id)