全球主机交流论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

CeraNetworks网络延迟测速工具IP归属甄别会员请立即修改密码
查看: 2225|回复: 22
打印 上一主题 下一主题

彻底陷入困境了,谁懂pack和unpack?

[复制链接]
跳转到指定楼层
1#
发表于 2015-4-30 00:25:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
就是dht,用php来写,由于接收到的node数据是struct结构体,需要对其进行解码
现在已经能够解出nid和ip,但是端口总是出错,郁闷死。。。

在协议中,要求的是端口为2字节,我使用unpack来解,n, s, S, v全部错误,最简单的,正确端口是35765,但解出来却变成了n:46422,s:22197,S:22197,v:22197

求救啊,谁知道要怎么做呢?
2#
发表于 2015-4-30 00:41:52 | 只看该作者
你解出来的这个是byte值.  有代码不, 我帮你一起弄吧
3#
 楼主| 发表于 2015-4-30 09:02:01 | 只看该作者
qibinghua 发表于 2015-4-30 00:41
你解出来的这个是byte值.  有代码不, 我帮你一起弄吧

代码啊?
就是当我发送一段find_node请求到服务器上:{"t":"aa", "y":"q","q":"find_node", "a":{"id":"abcdefghij0123456789","target":"mnopqrstuvwxyz123456"}}
然后服务器给我回复:{"t":"aa", "y":"r", "r":{"id":"0123456789abcdefghij", "nodes":"def456..."}}
而我们最需要的就是最后那段"nodes":"def456..."
其中nodes是保存有node信息的一个列表,其中node信息包含三个字段:nid,ip,port,分别保存有节点的id、ip、端口
按照协议中所说,nid是20字节,ip是4字节、端口为2字节
现在nid能够使用unpack("a20", substr($msg, 0, 20))获取,ip能够使用long2ip(unpack("N", $msg, 21, 4)[1])获取,但是端口就不行,试过所有的unpack格式,就是没办法获取到正确的端口号
4#
发表于 2015-4-30 09:37:10 | 只看该作者
发个端口的例子出来 我告诉你如何弄

评分

参与人数 1威望 +25 收起 理由
cnx + 25 很给力!

查看全部评分

5#
 楼主| 发表于 2015-4-30 09:39:20 | 只看该作者
0000000 发表于 2015-4-30 09:37
发个端口的例子出来 我告诉你如何弄

端口的例子?你指的是服务器实际发送的字节码么?
6#
 楼主| 发表于 2015-4-30 09:45:22 | 只看该作者
0000000 发表于 2015-4-30 09:37
发个端口的例子出来 我告诉你如何弄

比如服务器发了一段数据过来,ip是:188.19.238.146,端口是:6881,然后我截取端口位的2字节数据为:ᢰ
接着就是解码,讲网络字节序转换为端口号:unpack("n", $port),但是转换出来却变成了57763,用unpack("s", $port)变成了-23583,用unpack("S", $port)变成了41953
7#
发表于 2015-4-30 09:55:33 | 只看该作者
你这是php语言?
我不懂php语言 不过可以给你科普一下
端口 范围: 1-65535 就是说是2个字节的范围
你读的数据是原始的2个字节 所以不能用文本方式解析: ᢰ 这个是错误的.
你需要读第一个字节,比如读出来是 0x33 ,再读第二个直接 比如 0xAC
那么再根据服务端的数据顺序可以得到
0x33 << 8 + 0xAC = 0x33AC = 13228
0x33 + 0xAC << 8 = 0xAC33 = 44083
这个顺序得看服务端是什么语言写的. C和java正好相反.

8#
 楼主| 发表于 2015-4-30 09:57:47 | 只看该作者
我把测试代码发上来,可以看看,其中 dht.php 就是开启一个端口来监听,使用了swoole扩展,所以需要安装下,然后class下的Base中就包含了解码的函数,是decode_nodes,首先传入bencode解码过的nodes字节序,然后通过每次截取26个字节来解码数据,就是这里,nid和ip都能解码成功,就是port不行

同时,我把之前论坛里发的那个python版的爬虫改了一点,每次要发送find_node回复的时候会发送一份到我监听的本机端口,同时会将发送的数据写入infohash.log文件中,这样方便对照,这个程序需要安装twistd和kademlia

运行方式:
1. 首先运行php dht.php
2. twistd -y simDHT.py
3. 在php dht.php界面稍等片刻会看到php接收到的数据并输出
4. 将php停止,并下载infohash.log下来对比

dht.zip (21.81 KB, 下载次数: 341)
9#
 楼主| 发表于 2015-4-30 09:59:07 | 只看该作者
0000000 发表于 2015-4-30 09:55
你这是php语言?
我不懂php语言 不过可以给你科普一下
端口 范围: 1-65535 就是说是2个字节的范围

服务端是python写的,编码方式就是 struct.pack("!H", port)
10#
 楼主| 发表于 2015-4-30 10:01:43 | 只看该作者
0000000 发表于 2015-4-30 09:55
你这是php语言?
我不懂php语言 不过可以给你科普一下
端口 范围: 1-65535 就是说是2个字节的范围

如果这样说的话,就是一个字节一个字节读么?
但是获取nid和ip时我都是直接文本方式解析的,郁闷
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|全球主机交流论坛

GMT+8, 2026-1-12 07:14 , Processed in 0.079399 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表