全球主机交流论坛

标题: 彻底陷入困境了,谁懂pack和unpack? [打印本页]

作者: 带头盔滴衰锅    时间: 2015-4-30 00:25
标题: 彻底陷入困境了,谁懂pack和unpack?
就是dht,用php来写,由于接收到的node数据是struct结构体,需要对其进行解码
现在已经能够解出nid和ip,但是端口总是出错,郁闷死。。。

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

求救啊,谁知道要怎么做呢?
作者: qibinghua    时间: 2015-4-30 00:41
你解出来的这个是byte值.  有代码不, 我帮你一起弄吧
作者: 带头盔滴衰锅    时间: 2015-4-30 09:02
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格式,就是没办法获取到正确的端口号
作者: 0000000    时间: 2015-4-30 09:37
发个端口的例子出来 我告诉你如何弄
作者: 带头盔滴衰锅    时间: 2015-4-30 09:39
0000000 发表于 2015-4-30 09:37
发个端口的例子出来 我告诉你如何弄

端口的例子?你指的是服务器实际发送的字节码么?
作者: 带头盔滴衰锅    时间: 2015-4-30 09:45
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
作者: 0000000    时间: 2015-4-30 09:55
你这是php语言?
我不懂php语言 不过可以给你科普一下
端口 范围: 1-65535 就是说是2个字节的范围
你读的数据是原始的2个字节 所以不能用文本方式解析: ᢰ 这个是错误的.
你需要读第一个字节,比如读出来是 0x33 ,再读第二个直接 比如 0xAC
那么再根据服务端的数据顺序可以得到
0x33 << 8 + 0xAC = 0x33AC = 13228
0x33 + 0xAC << 8 = 0xAC33 = 44083
这个顺序得看服务端是什么语言写的. C和java正好相反.


作者: 带头盔滴衰锅    时间: 2015-4-30 09:57
我把测试代码发上来,可以看看,其中 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下来对比

(, 下载次数: 341)
作者: 带头盔滴衰锅    时间: 2015-4-30 09:59
0000000 发表于 2015-4-30 09:55
你这是php语言?
我不懂php语言 不过可以给你科普一下
端口 范围: 1-65535 就是说是2个字节的范围

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

如果这样说的话,就是一个字节一个字节读么?
但是获取nid和ip时我都是直接文本方式解析的,郁闷
作者: 0000000    时间: 2015-4-30 10:03
带头盔滴衰锅 发表于 2015-4-30 09:59
服务端是python写的,编码方式就是 struct.pack("!H", port)

我不懂python ip能对是因为ip本身就是字符串
如果说端口是2个字节 那就绝对是原始数据
用我告诉你方法2个字节进行计算还原为端口整数
不要用字符串去解析整数.
作者: 0000000    时间: 2015-4-30 10:05
带头盔滴衰锅 发表于 2015-4-30 10:01
如果这样说的话,就是一个字节一个字节读么?
但是获取nid和ip时我都是直接文本方式解析的,郁闷 ...

文本型的你就可以用文本读
短整数 2个字节 是整数 用文本读就错了.
你可以拿到字节1 字节2 进行计算一下 端口就出来了
这是程序猿基础.
作者: 0000000    时间: 2015-4-30 10:06
带头盔滴衰锅 发表于 2015-4-30 10:01
如果这样说的话,就是一个字节一个字节读么?
但是获取nid和ip时我都是直接文本方式解析的,郁闷 ...

还有一种方式 python在输出的时候 把端口转换为文本字符串
这样你用文本读就没问题了.
但是字节数量就不是 2了 是 1-5 个字节.
作者: 带头盔滴衰锅    时间: 2015-4-30 10:07
0000000 发表于 2015-4-30 10:05
文本型的你就可以用文本读
短整数 2个字节 是整数 用文本读就错了.
你可以拿到字节1 字节2 进行计算一下  ...

恩,好的,多谢,等回家之后试试,现在上班,不好写代码。。。
作者: 带头盔滴衰锅    时间: 2015-4-30 10:08
0000000 发表于 2015-4-30 10:06
还有一种方式 python在输出的时候 把端口转换为文本字符串
这样你用文本读就没问题了.
但是字节数量就不 ...

恩,明白了,回家试试一个字节一个字节的读
作者: 带头盔滴衰锅    时间: 2015-4-30 12:31
0000000 发表于 2015-4-30 10:05
文本型的你就可以用文本读
短整数 2个字节 是整数 用文本读就错了.
你可以拿到字节1 字节2 进行计算一下  ...

不行,获取不到,把两个字节分开来计算就出错了。。。
作者: 0000000    时间: 2015-4-30 17:43
带头盔滴衰锅 发表于 2015-4-30 12:31
不行,获取不到,把两个字节分开来计算就出错了。。。

不知道你是怎么分的.
作者: hising    时间: 2015-4-30 17:57
全球代码交流论坛
作者: onlybird    时间: 2015-4-30 18:28
感觉只要读取2字节的端口信息后 进行16转到10进制操作就行了
作者: 带头盔滴衰锅    时间: 2015-4-30 18:52
0000000 发表于 2015-4-30 17:43
不知道你是怎么分的.

现在解决了,发现貌似是我截取26个字节的时候有点问题,没截取正确还是怎么滴。。。
作者: 带头盔滴衰锅    时间: 2015-4-30 18:57
onlybird 发表于 2015-4-30 18:28
感觉只要读取2字节的端口信息后 进行16转到10进制操作就行了

不是的。。。。
作者: codegear    时间: 2015-4-30 19:48
估计lz遇到了大小端的问题。
网络序和主机序在一般的电脑上是颠倒的。

所以网络上给的 AB CD EF 12, 直接unpack会被识别成0x12EFCDAB。
作者: 带头盔滴衰锅    时间: 2015-5-1 09:36
codegear 发表于 2015-4-30 19:48
估计lz遇到了大小端的问题。
网络序和主机序在一般的电脑上是颠倒的。

额,不是的,已经确认了,是我截取那26个字节时截取错误了。。。




欢迎光临 全球主机交流论坛 (https://loc.888543.xyz/) Powered by Discuz! X3.4