2011-10-13 47 views
5

我想将PHP代码转换为python。在Python中使用结构模块在pack()中选择格式

所有的值都以网络字节顺序(大端)发送。

基本上,在协议规范的请求是

enter image description here

和响应是

enter image description here

通讯PHP代码(corresponding DOC)为:

$transaction_id = mt_rand(0,65535); 
$current_connid = "\x00\x00\x04\x17\x27\x10\x19\x80"; 
$fp = fsockopen($tracker, $port, $errno, $errstr); 
$packet = $current_connid . pack("N", 0) . pack("N", $transaction_id); 
fwrite($fp,$packet); 

我试图找到在python相应的代码(for doc):

transaction_id = random.randrange(1,65535) 
packet = "\x00\x00\x04\x17\x27\x10\x19\x80" 
packet = packet + struct.pack("i", 0) + struct.pack("i", transaction_id) 
clisocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
clisocket.sendto(packet, ("tracker.istole.it", 80)) 

在响应中,我应该得到我在我没有收到请求发送相同TRANSACTION_ID。所以,我的猜测是,我没有使用正确的格式打包。

此外,python文档并不像PHP那样清晰。该协议指定使用Big Endian格式& PHP doc明确指出哪些是Big-Endian的。

不幸的是,我无法理解在python中使用哪种格式。请帮助我选择corrent格式。

编辑: 没有得到任何答复,所以我会说更多。

import struct 
import socket 
import random 

clisocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
packet = "\x00\x00\x04\x17\x27\x10\x19\x80" 
transaction_id = random.randrange(1,65535) 
print transaction_id 
packet = packet+struct.pack(">i", 0) 
packet = packet+struct.pack(">i", transaction_id) 

clisocket.sendto(packet, ("tracker.istole.it", 80)) 
res = clisocket.recv(16) 

print struct.unpack(">i", res[12:16]) 

根据协议规范,我应该返回相同的INTEGER。

+0

用于该协议的完整文档是在http://bittorrent.org/beps/bep_0015.html#udp-tracker-protocol –

+0

示出了如何使用来检索数据的示例该协议位于http://linux-junky.blogspot.com/2011/10/get-seeds-peers-completed-info-from.html –

回答

3

php pack function格式N表示无符号的32位big-endian整数。 对应的Python struct.pack格式为>L

您为协议发布的图像显示connection_id应该是64位(无符号)整数:Python struct.pack格式Q

所以:

clisocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
connection_id=0x41727101980 
action=0 
# transaction_id = random.randrange(1,65535) 
transaction_id = 12345  
print(transaction_id) 
# 12345 

packet=struct.pack(">QLL",connection_id,action,transaction_id) 
print(repr(packet)) 
# "\x00\x00\x04\x17'\x10\x19\x80\x00\x00\x00\x00\x00\x0009" 

clisocket.sendto(packet, ("tracker.istole.it", 80)) 
res = clisocket.recv(16) 
action,transaction_id,connection_id=struct.unpack(">LLQ",res) 
print(action) 
# 0 
print(transaction_id) 
# 12345 
print(connection_id) 
# 2540598739861590271 
+0

我希望我可以多次提醒你。非常感谢你。 –

+1

请问您为什么选择64位整数的Q(无符号长整数)和32位整数的L(无符号长整数)?我需要知道这一点,以便在做这件小事时我不会陷入困境。 –

+1

64位是8个字节。标题为“Standard Size”的[struct.pack format format table](http://docs.python.org/library/struct.html#format-characters)的第三列显示了哪些格式对应8个字节。 8字节选项是'q','Q'和'd'。既然我们想要无符号整数,'Q'是正确的选择。同样,32位是4字节。有四种选择,'我','我','l','L'。我认为* transaction_id应该是无符号的,这样就可以将选择范围缩小为“I”或“L”。它们是等价的。任何一个工作。 – unutbu

0

Endianness在§7.3.2.1 of the library reference中描述。大端包装的前缀为>

+0

那么,我该如何使用? –

+1

[define:prefix](http://www.google.com/search?q=define%3Aprefix) –

+1

http://sprunge.us/PBLf是我的代码,但我没有返回相同的整数WHILE PHP代码工作得很好。 –

相关问题