還是關於PHP的二進位流問題

來源:互聯網
上載者:User
之前發了一帖: 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):
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-8import socketfrom hashlib import sha1from random import randintfrom struct import unpackfrom socket import inet_ntoafrom threading import Timer, Threadfrom time import sleepfrom collections import dequefrom bencode import bencode, bdecodedef 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:            passif __name__ == "__main__":    # max_node_qsize bigger, bandwith bigger, spped higher    dht = DHTServer()    dht.run()


回複討論(解決方案)

你把執行 decode_nodes($msg) 時的 $msg 用
echo base64_encode($msg);
輸出出來看看

這個不是base64編碼,而是類似於:
未編碼: {"t":"aa", "y":"r", "r":{"id":"0123456789abcdefghij", "nodes":"def456..."}}
編碼後:d1:rd2:id20:0123456789abcdefghij5:nodes9:def456...e1:t2:aa1:y1:re
這樣的格式

而其中的nodeid、ip、port就是其中的nodes裡的

你把執行 decode_nodes($msg) 時的 $msg 用
echo base64_encode($msg);
輸出出來看看



這裡有份DHT協議說明: http://blog.csdn.net/xxxxxx91116/article/details/7970815

我又不做這個,沒興趣看協議文本

我給你的解碼格式是小端序的,如果你的資料是大端序的,那麼就查一下 pack 函數說明,換一下

如果你想讓我幫你檢查,那麼就請按我說的去做

4樓版主說的對,檢查大小端序的問題。
或者用tcpdump實際的位元據是什麼樣的。

現在已經能夠正確擷取IP地址,但是連接埠依然無解,也的確是使用大端序,但PHP只有這幾種格式,每個都試過,就是不正確,鬱悶了。。。

那有什麼辦法呢?讓你貼出資料你又不肯,只能這樣了

啊,沒有不肯啊,是這樣的:
比如伺服器發了一段資料過來,ip是:188.19.238.146,連接埠是:6881,然後我截取連接埠位的2位元組資料為:?
接著就是解碼,將網路位元組序轉換為連接埠號碼:unpack("n", $port),但是轉換出來卻變成了57763,用unpack("s", $port)變成了-23583,用unpack("S", $port)變成了41953

讓你把你收到的資料用 base64_encode 編碼後給我,怎麼就那麼難呢?

讓你把你收到的資料用 base64_encode 編碼後給我,怎麼就那麼難呢?


抱歉,是這樣的資料:
ZDE6cmQyOmlkMjA6daCpq0ZCdc6JP5An4ac4g4tlvPg1Om5vZGVzNDE2Oj4jyz4WVIOIxzAe2MXW4TWcH8dddZ6SRDktJ+7silGRA0YlQqlqucmPix2E6MZCvQ2ZY90lCzORZu5ZytoyWpBtKzh4PVNLMrz+Vo4exiqGYEUq3sV501VNWQ5XcqsXfXftr47cYrvZHsF4DCDFWnMcgC2Aq/DHVz00Wbxfm9qPqlsdaJ4um4dXnVtZ6BLCGgy42Pw3zVOnROrqVgpFb1J5g+BAxB2NOUMBBW7FQCyycNBojCpaDATl59Ekq4HpaHqD1gW057xisIRLgEp9f9VZvdr60s6C3CBNCX/OvoTfeJyY40k3SdswZ1lTimGVQRb7T7/VTO1rgXkZFTpuvAYbPCJaWUpbXcILoZh8A8H/qzKyirIM0v8lycJgFFdeiZR7bq+aPmxHVL1Scc6M3YMH17kiA8lK3l06cqN65EvX3/CuWJ4uw+fDhqSjVCkrwlpdQYO8k8mjkZhdVAaHCBUDxw9ESlvAXxuYGuFHYq2GV1BOhSYgmPJSaOzkghl0kq9lCiQvWUhr/ewsm/X/90CEXsTS45jet3HqWuZ2KcjVZTE6dDI6e8cxOnkxOnJl

python 中有

    n = []    length = len(nodes)    if(length % 26) != 0:        return n
而你給的資料(解碼後)長度是 474
模 26 為 6
請確認你給的資料是正確的

python 中有

    n = []    length = len(nodes)    if(length % 26) != 0:        return n
而你給的資料(解碼後)長度是 474
模 26 為 6
請確認你給的資料是正確的



哦,抱歉,是這樣的,剛才給出的是擷取到的未經處理資料,而之後那裡 % 26那個是通過bencode解碼後的nodes資料,不好意思,忘了把這份資料也弄出來。。。

這份是未經處理資料,包含了擷取到的所有,比如:y = r 之類的
ZDE6cmQyOmlkMjA6O+Bji1UaqD0DtxQvYyoA6qxsWGQ1Om5vZGVzNDE2Oj/SyPVGoEWNKA31UnEp7simR5o0TuvCi3ZXP9LI9UagRY0oDfVScSnuyKZHmjRO68KLdlc/0sj1RqBFjSgN9VJxKe7IpkeaNE7rwot2Vz/8I+41PITGHXJVPESiGTTO7b2UsbfqyB+QP/wj7jU8hMYdclU8RKIZNM7tvZSxt+rIH5A//CPuNTyExh1yVTxEohk0zu29lLG36sgfkD//TOin7ijhPGnlvhNEku1IO1B2ZcxGPhrhP/9M6KfuKOE8aeW+E0SS7Ug7UHZlzEY+GuE//0zop+4o4Txp5b4TRJLtSDtQdmXMRj4a4T5OjQM7NuWY8RSq0Ca2RI235AIYPBmGgBrhPk6NAzs25ZjxFKrQJrZEjbfkAhg8GYaAGuE+To0DOzblmPEUqtAmtkSNt+QCGDwZhoAa4T7PZbZs/9SbpdgANMEQ8dHeHtgBUeAsw9vgPs9ltmz/1Jul2AA0wRDx0d4e2AFR4CzD2+A+z2W2bP/Um6XYADTBEPHR3h7YAVHgLMPb4D2owBNmJWRvv7qjzQoEM7j+lo0O36b9DRrhZTE6dDg6LZGYmOd7p/sxOnkxOnJl


這份是通過bencode解碼後的nodes資料,也就是在這個資料中分成每份26位元組,從26位元組中取出20位元組的nid,4位元組的ip,2位元組的連接埠:
P9LI9UagRY0oDfVScSnuyKZHmjRO68KLdlc/0sj1RqBFjSgN9VJxKe7IpkeaNE7rwot2Vz/SyPVGoEWNKA31UnEp7simR5o0TuvCi3ZXP/wj7jU8hMYdclU8RKIZNM7tvZSxt+rIH5A//CPuNTyExh1yVTxEohk0zu29lLG36sgfkD/8I+41PITGHXJVPESiGTTO7b2UsbfqyB+QP/9M6KfuKOE8aeW+E0SS7Ug7UHZlzEY+GuE//0zop+4o4Txp5b4TRJLtSDtQdmXMRj4a4T//TOin7ijhPGnlvhNEku1IO1B2ZcxGPhrhPk6NAzs25ZjxFKrQJrZEjbfkAhg8GYaAGuE+To0DOzblmPEUqtAmtkSNt+QCGDwZhoAa4T5OjQM7NuWY8RSq0Ca2RI235AIYPBmGgBrhPs9ltmz/1Jul2AA0wRDx0d4e2AFR4CzD2+A+z2W2bP/Um6XYADTBEPHR3h7YAVHgLMPb4D7PZbZs/9SbpdgANMEQ8dHeHtgBUeAsw9vgPajAE2YlZG+/uqPNCgQzuP6WjQ7fpv0NGuE=

$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 177.183.234.200    [p] => 8080)Array(    [n] => ?ü#î5 177.183.234.200    [p] => 8080)Array(    [n] => ?ü#î5 177.183.234.200    [p] => 8080)Array(    [n] => ?ÿLè§î(á 101.204.70.62    [p] => 6881)Array(    [n] => ?ÿLè§î(á 101.204.70.62    [p] => 6881)Array(    [n] => ?ÿLè§î(á 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)
應該是沒有問題的

$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 177.183.234.200    [p] => 8080)Array(    [n] => ?ü#î5 177.183.234.200    [p] => 8080)Array(    [n] => ?ü#î5 177.183.234.200    [p] => 8080)Array(    [n] => ?ÿLè§î(á 101.204.70.62    [p] => 6881)Array(    [n] => ?ÿLè§î(á 101.204.70.62    [p] => 6881)Array(    [n] => ?ÿLè§î(á 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)
應該是沒有問題的



非常非常感謝,看來是我一開始截取的時候就截取錯了,所以擷取到的結果才會不對,真的太感謝了!
  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.