Распаковка PHP и Python возвращает разные результаты из одного источника - PullRequest
4 голосов
/ 01 декабря 2011

Я не могу получить даже смутно одинаковые данные из сценариев Python (который я предпочел бы использовать) и PHP (который прекрасно работает, кодируется хостом сайта).

PHP подключается к той же папке, что и скрипт Python.

И до того, как кто-нибудь бросит оружие, я знаю, что скрипт на Python извлекает только часть данных. Но я не могу получить даже смутно те же данные с сервера.

Python:

import socket, struct

host,port = 'baystation12.net', 8000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.send('status\r\n')
data = s.recv(1024)
s.close()
print 'Received:', repr(data) # >>> Received: '\x00\xc7\x00\x07\x02\xadj\x00\x00\x1c\xf6'
cache,form,listy = "",">H",[]
for i in data:
    if cache != "":
        listy.append(struct.unpack(form,cache+i))
    else:
        cache = i
print "Unpacked:",listy # >>> Unpacked: [(199,), (0,), (7,), (2,), (173,), (106,), (0,), (0,), (28,), (246,)]


text = ""
for i in listy:
    text += chr(i[0])
print "Text:",text # >>> Text: Ç
#Shows up incorrectly when I try to copy it.

PHP:

#!/usr/bin/php
<?php
function export($addr,$port,$str)
{
    if($str{0} != "?") $str = ("?" . $str);
    $query = "\x00\x83" . pack("n",strlen($str)+6) . "\x00\x00\x00\x00\x00" . $str . "\x00";
    $server = socket_create(AF_INET,SOCK_STREAM,SOL_TCP) or exit('Unable to create export socket; ' . socket_strerror(socket_last_error()));
    socket_connect($server,$addr,$port) or exit('Unable to establish socket connection; ' . socket_strerror(socket_last_error()));
    $bytessent = 0;
    while($bytessent < strlen($query))
    {
        $result = socket_write($server,substr($query,$bytessent),strlen($query)-$bytessent);
        if($result === FALSE) return('Unable to transfer requested data; ' .  socket_strerror(socket_last_error()));
        $bytessent += $result;
    }
    $resbuf = '';
    while( socket_recv($server, $message,1,0 )){
       $resbuf .= $message;
    if(strpos($resbuf,"&end")!=FALSE)
      {
       echo $resbuf;
       socket_close($server);
       return($resbuf);
      }
    echo $message;
    };
    echo $resbuf."\n";
    socket_close($server);
}
export("localhost","8000","status");
?>

Вывод PHP:

version=Baystation+12&mode=extended&respawn=0&enter=1&vote=1&ai=1&host&players=5&player0=CompactNinja&player1=Sick+trigger&player2=SweetJealousy&player3=Cacophony&player4=Anchorshag&end

Любая идея, почему Python выдает бессмысленные символы при распаковке данных, в то время как PHP выдает выше.

Ответы [ 2 ]

2 голосов
/ 07 декабря 2011

Вы не отправляете тот же запрос на свой сервер в Python.

В Python вы отправляете status

В PHP вы отправляете что-то вроде \x00\x83\x00\x0d\x00\x00\x00\x00\x00\x00?status\x00

Если вы измените свой python, чтобы более точно имитировать PHP, он будет работать намного лучше:

import socket, struct

host,port = 'baystation12.net', 8000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))

senddata = "?status"
query  = '\x00\x83' + struct.pack(">H", len(senddata)+6) + '\x00'*5 + senddata + '\x00'
s.send(query)

data = s.recv(1024)
print `data`

Когда я попробовал это, он напечатал

'\x00\x83\x00\xe9\x06version=Baystation+12&mode=traitor&respawn=0&enter=1&vote=1&ai=1&host&players=7&player0=Kosherman&player1=Ghazkull&player2=Doug+H.+Nuts&player3=Lord+Braindead&player4=KirbyElder&player5=Master+of+Apples&player6=Cacophony&end=%23end\x00'

Что похоже на то, что получал PHP.

0 голосов
/ 01 декабря 2011

Попробуйте listy.append(struct.unpack(form,cache+i)[0])

В итоге вы получите список из 1 элемента, а не список чисел.

Из документов: http://docs.python.org/library/struct.html#struct.unpack

 struct.unpack(fmt, string) 

Распаковать строку (предположительно упакован pack (fmt, ...)) в соответствии с заданным форматом. Результатом является кортеж даже если он содержит ровно один элемент. Строка должна содержать точно объем данных, требуемый форматом (len (строка) должен быть равен calcsize (FMT)).

...