2011-10-13 13 views
5

Estoy tratando de convertir un código PHP a python.Elegir el formato en el paquete() usando el módulo struct en python

Todos los valores se envían en orden de bytes de red (big endian).

Básicamente, la petición en la especificación de protocolo es

enter image description here

y la respuesta es

enter image description here

Correspondiente Código PHP (corresponding DOC) es:

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

estoy tratando de encontrar el código correspondiente (for doc) en 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)) 

En la respuesta, que debería obtener el mismo transaction_id envié en la solicitud que no estoy recibiendo. Entonces, mi suposición es que no estoy empacando usando el formato correcto.

Además, la documentación de Python no es tan clara como la de PHP. El protocolo especifica usar el formato Big Endian & El doc de PHP indica claramente cuáles son los de Big-Endian.

Lamentablemente, no pude comprender qué formato usar en python. Por favor, ayúdenme a elegir el formato corrent.

EDITAR: No recibo ninguna respuesta, por lo que diría más.

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

Según la especificación del protocolo, debería devolverse el mismo INTEGER.

+0

documento completo para el protocolo está en http://bittorrent.org/beps/bep_0015.html#udp-tracker-protocol –

+0

Un ejemplo que muestra sobre cómo recuperar los datos utilizando el protocolo está en http://linux-junky.blogspot.com/2011/10/get-seeds-peers-completed-info-from.html –

Respuesta

3

El formato php pack functionN significa entero sin signo de 32 bits big-endian. El formato Python struct.pack correspondiente es >L.

Las imágenes que ha publicado para el protocolo muestran que connection_id debe ser un entero de 64 bits (sin signo): formato struct.pack de Python Q.

Así:

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

Ojalá pudiera votarte más de una vez. MUCHAS GRACIAS. –

+1

¿Podría decirme por qué eligió Q (sin signo de larga duración) para entero de 64 bits y L (sin signo largo) para entero de 32 bits? Necesito saber esto para no meterme en problemas mientras hago esto trivial. –

+1

64 bits es de 8 bytes. La tercera columna de la [tabla de formato de struct.pack] (http://docs.python.org/library/struct.html#format-characters) titulada "Tamaño estándar" muestra qué formatos corresponden a 8 bytes. Las opciones de 8 bytes son 'q',' Q' y 'd'. Como queremos enteros sin signo, 'Q' es la elección correcta. Del mismo modo, 32 bits es 4 bytes. Hay cuatro opciones, 'i',' I', 'l',' L'. I * supone * que transaction_id no debe estar firmado, por lo que la opción se reduce a 'I' o' L'. Ellos son equivalentes. Cualquiera de los dos trabaja – unutbu

0

Endianness se describe en §7.3.2.1 of the library reference. El embalaje Big-endian tiene un prefijo de >.

+0

Entonces, ¿cómo debo usar? –

+1

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

+1

http://sprunge.us/PBLf es mi código pero no me devuelven el mismo número entero MIENTRAS que el PHP el código funciona bien –

Cuestiones relacionadas