還是關於PHP的二進位流問題
之前發了一帖: http://bbs.csdn.net/topics/391024843
版主給了回答,也能夠解析出來,但卻發現出來的結果與真實結果完全不一樣,比如伺服器返回給我的是: ip: 107.145.107.140, port: 26773
但我解析出來卻變成了: ip: 46.48.46.48, port: 63271
這樣就差的遠了, 我用PHP去擷取nodes資訊,然後將nodes資訊自己解析輸出一遍,順便把未解析資料發送給pthon解析一遍,然後兩邊對比,發現結果卻不一樣
PHP(使用了swoole):
$serv = new swoole_server('0.0.0.0', 6882, SWOOLE_PROCESS, SWOOLE_SOCK_UDP);
$serv->set(array(
'worker_num' => WORKER_NUM,
'daemonize' => false,
'max_request' => MAX_REQUEST,
'dispatch_mode' => 2,
'debug_mode' => 1
));
$serv->on('Start', function($serv){
echo "DHT Server start...\n";
$nid = get_node_id();
$msg = array(
't' => entropy(2),
'y' => 'q',
'q' => 'find_node',
'a' => array(
'id' => $nid,
'target' => $nid
)
);
$serv->sendto(gethostbyname('router.bittorrent.com'), 6881, encode($msg));
});
$serv->on('Receive', function($serv, $fd, $from_id, $data){
echo "New receive from ip: ";
$msg = decode($data);
$fdinfo = $serv->connection_info($fd);
echo $fdinfo['remote_ip'] . "\n";
if($msg['y'] == 'r'){
if(array_key_exists('nodes', $msg['r']))
//$this->response_actions($msg, array($fdinfo['remote_ip'], $fdinfo['remote_port']));
$nodes = decode_nodes($msg['r']['nodes']);
foreach($nodes as $node){
echo "nid: " . $node->nid . ", ip: " . $node->ip . ", port: " . $node->port . "\n";
}
$serv->sendto('127.0.0.1', 6813, $data);
}
});
function entropy($length=20){
$s = '';
for($i=0;$i<$length;$i++)
$s .= chr(mt_rand(0, 255));
return $s;
}
function get_node_id(){
return sha1(entropy());
}
function get_neighbor($target, $nid){
return substr($target, 0, 10) . substr($nid, 0, -10);
}
function encode($msg){
return Bencode::encode($msg);
}
function decode($msg){
return Bencode::decode($msg);
}
function decode_nodes($msg){
$n = array();
$length = strlen($msg);
// 由於每個node都為26位, 若總長度不等於26的倍數則直接返回
if(($length % 26) != 0)
return $n;
$i = 0;
while($i<$length){
//$s = substr($msg, $i, 26);
//$d = unpack('a20nid/Lip/Sport', $s);
//var_dump($d);
//$d = unpack('a20nid/lip/sport', $s);
//var_dump($d);
//$n[] = new Node($d['nid'], long2ip($d['ip']), $d['port']);
$nid = substr($msg, $i, 20);
var_dump($nid);
$ip = substr($msg, $i+20, 4);
var_dump($ip);
$ip = long2ip(unpack('L', $ip)[1]);
$port = substr($msg, $i+24, 2);
var_dump($port);
$port = unpack('s', $port)[1];
var_dump($port);
//$n[] = new Node($nid, $ip, $port);
$i += 26;
}
return $n;
}
$serv->start();
python:
#!/usr/bin/env python
#encoding: utf-8
import socket
from hashlib import sha1
from random import randint
from struct import unpack
from socket import inet_ntoa
from threading import Timer, Thread
from time import sleep
from collections import deque
from bencode import bencode, bdecode
def decode_nodes(nodes):
n = []
length = len(nodes)
if(length % 26) != 0:
return n
for i in range(0, length, 26):
nid = nodes[i:i+20]
ip = inet_ntoa(nodes[i+20:i+24])
ip2 = nodes[i+20:i+24]
print ip2
port = unpack("!H", nodes[i+24:i+26])[0]
port2 = nodes[i+24:i+26]
print port2
print "decode_nodes: nid: %s, ip: %s, port: %s\n" % (nid, ip, port)
class DHTServer():
def __init__(self):
self.ufd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
self.ufd.bind(("0.0.0.0", 6813))
def process_find_node_response(self, msg, address):
nodes = decode_nodes(msg["r"]["nodes"])
for node in nodes:
(nid, ip, port) = node
print "find_node: nid: %s, ip: %s, port: %s\n" % (nid, ip, port)
def run(self):
while True:
try:
(data, address) = self.ufd.recvfrom(65536)
msg = bdecode(data)
self.on_message(msg, address)
except Exception:
pass
def on_message(self, msg, address):
try:
if msg["y"] == "r":
if msg["r"].has_key("nodes"):
self.process_find_node_response(msg, address)
except KeyError:
pass
if __name__ == "__main__":
# max_node_qsize bigger, bandwith bigger, spped higher
dht = DHTServer()
dht.run()
------解決思路----------------------
$s = 'P9LI9UagRY0oDfVScSnuyKZHmjRO68KLdlc/0sj1RqBFjSgN9VJxKe7IpkeaNE7rwot2Vz/SyPVGoEWNKA31UnEp7simR5o0TuvCi3ZXP/wj7jU8hMYdclU8RKIZNM7tvZSxt+rIH5A//CPuNTyExh1yVTxEohk0zu29lLG36sgfkD/8I+41PITGHXJVPESiGTTO7b2UsbfqyB+QP/9M6KfuKOE8aeW+E0SS7Ug7UHZlzEY+GuE//0zop+4o4Txp5b4TRJLtSDtQdmXMRj4a4T//TOin7ijhPGnlvhNEku1IO1B2ZcxGPhrhPk6NAzs25ZjxFKrQJrZEjbfkAhg8GYaAGuE+To0DOzblmPEUqtAmtkSNt+QCGDwZhoAa4T5OjQM7NuWY8RSq0Ca2RI235AIYPBmGgBrhPs9ltmz/1Jul2AA0wRDx0d4e2AFR4CzD2+A+z2W2bP/Um6XYADTBEPHR3h7YAVHgLMPb4D7PZbZs/9SbpdgANMEQ8dHeHtgBUeAsw9vgPajAE2YlZG+/uqPNCgQzuP6WjQ7fpv0NGuE=';
$s = base64_decode($s);
foreach(str_split($s, 26) as $s) {
$r = unpack('a20n/Nip/np', $s);
$r['ip'] = long2ip($r['ip']);
print_r($r);
}
Array
(
[n] => ????F E?(
?Rq)???G?4
[ip] => 78.235.194.139
[p] => 30295
)
Array
(
[n] => ????F E?(
?Rq)???G?4
[ip] => 78.235.194.139
[p] => 30295
)
Array
(
[n] => ????F E?(
?Rq)???G?4
[ip] => 78.235.194.139
[p] => 30295
)
Array
(
[n] => ?ü#?5 [ip] => 177.183.234.200
[p] => 8080
)
Array
(
[n] => ?ü#?5 [ip] => 177.183.234.200
[p] => 8080
)
Array
(
[n] => ?ü#?5 [ip] => 177.183.234.200
[p] => 8080
)
Array
(
[n] => ??Lè§?(á [ip] => 101.204.70.62
[p] => 6881
)
Array
(
[n] => ??Lè§?(á [ip] => 101.204.70.62
[p] => 6881
)
Array
(
[n] => ??Lè§?(á [ip] => 101.204.70.62
[p] => 6881
)
Array
(
[n] => >N?;6?????&?D?·?
[ip] => 60.25.134.128
[p] => 6881
)
Array
(
[n] => >N?;6?????&?D?·?
[ip] => 60.25.134.128
[p] => 6881
)
Array
(
[n] => >N?;6?????&?D?·?
[ip] => 60.25.134.128
[p] => 6881
)
Array
(
[n] => >?e?l?????4?????
[ip] => 81.224.44.195
[p] => 56288
)
Array
(
[n] => >?e?l?????4?????
[ip] => 81.224.44.195
[p] => 56288
)
Array
(
[n] => >?e?l?????4?????
[ip] => 81.224.44.195
[p] => 56288
)
Array
(
[n] => =¨?f%do????
3??–?
[ip] => 223.166.253.13
[p] => 6881
)
應該是沒有問題的