Выбор формата в pack() с помощью модуля struct в python


Я пытаюсь преобразовать PHP-код в python.

Все значения отправляются в сетевом порядке байтов (большой конец).

В принципе, ЗАПРОС в спецификации протокола

enter image description here

И ответ

enter image description here

Соответствующий код PHP ( соответствующий документ ):

$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);

Я пытаюсь найти соответствующий код ( для doc) в python:

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))

В ответе я должен получить то же самое транзакция_id Я отправил запрос, который я не получаю. Итак, я предполагаю, что я не упаковываю вещи в правильном формате.

Кроме того, документация по python не так понятна, как документация по PHP. В протоколе указано использовать формат Big Endian, и в документе PHP четко указано, какие из них предназначены для 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])

Согласно спецификации протокола, мне должно быть возвращено то же ЦЕЛОЕ число.

Author: Abhijeet Rastogi, 2011-10-13

2 answers

Функция php pack формат N означает 32-разрядное целое число без знака с большим порядком. Соответствующий 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
 3
Author: unutbu, 2011-10-13 20:30:25

Конечность описана в §7.3.2.1 библиотечного справочника. Упаковка большого конца имеет префикс >.

 0
Author: Ignacio Vazquez-Abrams, 2011-10-13 18:12:01