2013-06-05 81 views
2

我試圖從公共UDP跟蹤器如tracker.publicbt.com或tracker.openbittorrent.com使用BitTorrent UDP Tracker Protocol執行UDP刮。我的應用程序向跟蹤器發送了一個connection_id的請求,並使用該ID來執行刮擦。刮擦響應從追蹤器返回,沒有錯誤表明形成了嚴重的數據包,但無論我使用什麼info_hash,我都會返回「0」表示播種器,掃描器和完成的數量。UDP跟蹤器刮意外

我已經徹底檢查數據包的大小是否合適,該info_hash開始於正確的偏移量,該數據是正確的。據我所知,創建和發送數據包沒有問題。這個問題已經公開並且有幾天沒有答案,所以我已經更新和編輯了下面的代碼示例,希望有人能夠提供幫助。

我硬編碼的info_hash到下面的例子。當在命令行上運行時,這段代碼應該連接到跟蹤器,獲取一個connection_id,然後在Ubuntu的torrent上執行一次刷新info_hash,將各種信息輸出到控制檯。

的CONNECTION_ID被分成2份,因爲它是一個64位的整數。

var dgram = require('dgram'), 
    server = dgram.createSocket("udp4"), 
    connectionIdHigh = 0x417, 
    connectionIdLow = 0x27101980, 
    transactionId, 
    action, 
    trackerHost = "tracker.publicbt.com", 
    trackerPort = 80, 
    infoHash = "", 
    ACTION_CONNECT = 0, 
    ACTION_ANNOUNCE = 1, 
    ACTION_SCRAPE = 2, 
    ACTION_ERROR = 3, 
    sendPacket = function (buf, host, port) { 
     "use strict"; 
     server.send(buf, 0, buf.length, port, host, function(err, bytes) { 
      if (err) { 
       console.log(err.message); 
      } 
     }); 
    }, 
    startConnection = function (host, port) { 
     "use strict"; 
     var buf = new Buffer(16); 

     transactionId = Math.floor((Math.random()*100000)+1); 

     buf.fill(0); 

     buf.writeUInt32BE(connectionIdHigh, 0); 
     buf.writeUInt32BE(connectionIdLow, 4); 
     buf.writeUInt32BE(ACTION_CONNECT, 8); 
     buf.writeUInt32BE(transactionId, 12); 

     sendPacket(buf, host, port); 
    }, 
    scrapeTorrent = function (host, port, hash) { 
     "use strict"; 
     var buf = new Buffer(56), 
      tmp = ''; 

     infoHash = hash; 

     if (!transactionId) { 
      startConnection(host, port); 
     } else { 

      buf.fill(0); 

      buf.writeUInt32BE(connectionIdHigh, 0); 
      buf.writeUInt32BE(connectionIdLow, 4); 
      buf.writeUInt32BE(ACTION_SCRAPE, 8); 
      buf.writeUInt32BE(transactionId, 12); 
      buf.write(infoHash, 16, buf.length); 

      console.log(infoHash); 
      console.log(buf.toString('utf8', 16, buf.length)); 

      // do scrape 
      sendPacket(buf, host, port); 

      transactionId = null; 
      infoHash = null; 
     } 

    }; 

server.on("message", function (msg, rinfo) { 
    "use strict"; 
    var buf = new Buffer(msg), 
     seeders, 
     completed, 
     leechers; 

    console.log(rinfo); 

    action = buf.readUInt32BE(0, 4); 
    transactionId = buf.readUInt32BE(4, 4); 

    console.log("returned action: " + action); 
    console.log("returned transactionId: " + transactionId); 

    if (action === ACTION_CONNECT) { 
     console.log("connect response"); 

     connectionIdHigh = buf.readUInt32BE(8, 4); 
     connectionIdLow = buf.readUInt32BE(12, 4); 

     scrapeTorrent(trackerHost, trackerPort, infoHash); 

    } else if (action === ACTION_SCRAPE) { 
     console.log("scrape response"); 

     seeders = buf.readUInt32BE(8, 4); 
     completed = buf.readUInt32BE(12, 4); 
     leechers = buf.readUInt32BE(16, 4); 

     console.log(seeders); 
     console.log(completed); 
     console.log(leechers); 

    } else if (action === ACTION_ERROR) { 
     console.log("error response"); 
    } 
}); 

server.on("listening", function() { 
    "use strict"; 
    var address = server.address(); 
    console.log("server listening " + address.address + ":" + address.port); 
}); 

server.bind(); 

scrapeTorrent(trackerHost, trackerPort, "335990D615594B9BE409CCFEB95864E24EC702C7");
+1

我已經添加上方的輕微改善的代碼示例。在過去的幾天我一直在試圖確定是否有什麼問題我創建了緩衝區的方式,但據我可以告訴領域是正確的,包括info_hash部分。 – Pappa

回答

4

我終於解決了這個問題,並且因爲沒有及時實現,

info_hash是一個十六進制編碼的字符串,所以當它被寫入緩衝區時需要它的編碼集。例如:

buf.write(infoHash, 16, buf.length, 'hex'); 

UDP跟蹤器協議沒有提到所需的編碼,它只是將其描述爲一個20字節的字符串。希望這個Q & A可以幫助遇到同樣問題的其他人。