UDP Tracker在PHP中宣布

时间:2013-07-02 09:25:36

标签: php udp bittorrent

基本上我试图从udp torrent跟踪器中获取php中的同行。 目的是分析不同地区的流量。

所以我不需要下载torrent只需获取对等列表并再次宣布获得不同的设置。我试过用PHP

我选择了一个开源代码来擦除udp种子并对其进行修改。

这是代码

require_once(dirname(__FILE__) . '/tscraper.php');

class udptscraper extends tscraper{

    /*  $url: Tracker url like: udp://tracker.tld:port or udp://tracker.tld:port/announce
        $infohash: Infohash string or array (max 74 items). 40 char long infohash. 
        */
    public function scrape($url,$infohash){
        if(!is_array($infohash)){ $infohash = array($infohash); }
        foreach($infohash as $hash){
            if(!preg_match('#^[a-f0-9]{40}$#i',$hash)){ throw new ScraperException('Invalid infohash: ' . $hash . '.'); }
        }
        if(count($infohash) > 74){ throw new ScraperException('Too many infohashes provided.'); }
        if(!preg_match('%udp://([^:/]*)(?::([0-9]*))?(?:/)?%si', $url, $m)){ throw new ScraperException('Invalid tracker url.'); }
        $tracker = 'udp://' . $m[1];
        $port = isset($m[2]) ? $m[2] : 80;
        $transaction_id = mt_rand(0,65535);
        $fp = fsockopen($tracker, $port, $errno, $errstr);
        if(!$fp){ throw new ScraperException('Could not open UDP connection: ' . $errno . ' - ' . $errstr,0,true); }
        stream_set_timeout($fp, $this->timeout);

        $current_connid = "\x00\x00\x04\x17\x27\x10\x19\x80";

        //Connection request
        $packet = $current_connid . pack("N", 0) . pack("N", $transaction_id);
        fwrite($fp,$packet);

        //Connection response
        $ret = fread($fp, 16);
        if(strlen($ret) < 1){ throw new ScraperException('No connection response.',0,true); }
        if(strlen($ret) < 16){ throw new ScraperException('Too short connection response.'); }
        $retd = unpack("Naction/Ntransid",$ret);
        if($retd['action'] != 0 || $retd['transid'] != $transaction_id){
            throw new ScraperException('Invalid connection response.');
        }
        $current_connid = substr($ret,8,8);

        //ANNOUNCE request
        $hashes = '';
        $pid ='O5214m2Y0z6178K1z090';
        $key = mt_rand(0,65535);
        $down =mt_rand(0,12345);
        $left =mt_rand(0,12345);
        $upped =mt_rand(0,12345);
        $transaction_id = mt_rand(0,65535);
        $event = 2;
        $socket = socket_create_listen (19624);

        foreach($infohash as $hash){ $hashes .= pack('H*', $hash); }
        $packet = $current_connid . pack("N", 1) . pack("N", $transaction_id) . $hashes . pack("N", $pid) . pack("N", $down) . pack("N", $left) . pack("N", $upped) . pack("N", 0) . pack("N", 0) . pack("N", $key) . pack("N", -1) . pack("N", 19624);
        fwrite($fp,$packet);

        //ANNOUNCE response
        $readlength = 20 + (6 * count($infohash));
        $ret = fread($fp, $readlength);
        echo $ret;
        if(strlen($ret) < 1){ throw new ScraperException('No .',0,true); }
        if(strlen($ret) < 8){ throw new ScraperException('Too short  response.'); }
        $retd = unpack("Naction/Ntransid",$ret);
        // Todo check for error string if response = 3
        if($retd['action'] != 1 || $retd['transid'] != $transaction_id){
            throw new ScraperException('Invalid scrape response.');
        }
        if(strlen($ret) < $readlength){ throw new ScraperException('Too short scrape response.'); }
        $torrents = array();
        $index = 8;
        foreach($infohash as $hash){
            $retd = unpack("Ninterval/Nleechers/Nseeders/Nipaddr/NTCP",substr($ret,$index));
            print_r($retd);
            $retd['infohash'] = $hash;
            $torrents[$hash] = $retd;
            $index = $index + 12;
        }

        return($torrents);
    }
}





try{
        $timeout = 2;

        $scraper = new udptscraper($timeout);
        $ret = $scraper->scrape('udp://tracker.openbittorrent.com:80/announce',array('8B60D5838A2CE34294AF9E49FF990C5BEC6C61B1'));

        //print_r($ret);
    }catch(ScraperException $e){
        echo('Error: ' . $e->getMessage() . "<br />\n");
        echo('Connection error: ' . ($e->isConnectionError() ? 'yes' : 'no') . "<br />\n");
    }

&GT;

我只使用1个HASH值 请帮忙。

1 个答案:

答案 0 :(得分:0)

编辑:跟踪服务器有时会发送响应消息,其对等体列表由每个对等体的6个字节替换。前4个字节是主机IP,最后2个字节是端口号。你应该解析它们以便与同行沟通。

我认为理论(规格)可能不是事实。关于互联网Bittorent的所有规格都已过时。通过遵循规范来检查通知请求是否正确可能是不可能的 我建议你尝试使用Wireshark。捕获常见的Bittorent-client发送的数据包,然后检查Bittornet客户端的常用工作方式。比较你的php代码发送的通知请求,到一个普通客户端发送。

实际上,我正在尝试在C中实现Bittorent客户端。我很难与跟踪服务器通信,因为没有在请求消息中指定压缩字段。但是大多数规范都说声明请求中的紧凑字段是可选的。

尝试使用wireshark。然后比较两个请求(您的请求和公共bittorent发送的另一个请求。) enter image description here