Выбор формата в pack() с помощью модуля struct в python
Я пытаюсь преобразовать PHP-код в python.
Все значения отправляются в сетевом порядке байтов (большой конец).
В принципе, ЗАПРОС в спецификации протокола
И ответ
Соответствующий код 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])
Согласно спецификации протокола, мне должно быть возвращено то же ЦЕЛОЕ число.
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
Конечность описана в §7.3.2.1 библиотечного справочника. Упаковка большого конца имеет префикс >
.