Сообщение отправлено урезанным до размера полученных данных - PullRequest
2 голосов
/ 24 ноября 2011

Я действительно работал над этим последние несколько часов ... Я преодолел кодирование и декодирование сообщений.

Однако теперь я столкнулся с проблемой различий. Я могу выдавать команды, однако ответы на каждую команду усекаются до длины полученной строки ...

ОЖИДАЕМЫЙ результат чата: О, дорогой, я 152
ПОЛУЧЕНО результат чата: Oh

ОТЛАДКА ОТ СЕРВЕРА:

  2011-11-23 23:22:14 System: Socket Resource id #7 created.
  2011-11-23 23:22:14 System: Socket bound to 192.168.1.144:8000.
  2011-11-23 23:22:14 System: Start listening on Socket.
  2011-11-23 23:22:17 WebSocket: Resource id #9 CONNECTED!
  2011-11-23 23:22:17 WebSocket: Requesting handshake...
  2011-11-23 23:22:17 WebSocket: Key: 42MngFcIhXEKCLFloq6IYQ==
  2011-11-23 23:22:17 WebSocket: Accept: raRUiMJ6z2bTY6pDrOf7K4Q56Fc=
  2011-11-23 23:22:17 WebSocket: Origin: http://192.168.1.144
  2011-11-23 23:22:17 WebSocket: Handshaking...
  2011-11-23 23:22:17 WebSocket: Done handshaking...
  2011-11-23 23:22:18 WebSocket: RECEIVED BEFORE DECODE: ¿õ1ÆÞT
  2011-11-23 23:22:18 WebSocket: RECEIVED AFTER DECODE: age
  2011-11-23 23:22:18 WebSocket: <age
  2011-11-23 23:22:18 WebSocket: >Oh dear, I'm 152
  2011-11-23 23:22:18 WebSocket: SENT BEFORE ENCODE: Oh dear, I'm 152
  2011-11-23 23:22:18 WebSocket: SENT AFTER ENCODE: ¿õ1Æð

ОТЛАДКА ОТ КЛИЕНТА:

  Socket Status: 0
  Socket Status: 1 (open)
  Sent: age
  Received: Oh

ФУНКЦИИ КОДИРОВАНИЯ И ДЕКОДИРОВАНИЯ

function decode($msg) {

    $this->console("RECEIVED BEFORE DECODE: $msg");

    $len = $data = $decoded = $index = null;
    $len = $msg[1] & 127;

    if ($len === 126) {
        $this->masks = substr($msg, 4, 4);
        $data = substr($msg, 8);
        $this->initFrame = substr($msg, 0, 4);
    } else if ($len === 127) {
        $this->masks = substr($msg, 10, 4);
        $data = substr($msg, 14);
        $this->initFrame = substr($msg, 0, 10);
    } else {
        $this->masks = substr($msg, 2, 4);
        $data = substr($msg, 6);
        $this->initFrame = substr($msg, 0, 2);
    }
    for ($index = 0; $index < strlen($data); $index++) {
        $decoded .= $data[$index] ^ $this->masks[$index % 4];
    }

    $this->console("RECEIVED AFTER DECODE: $decoded");

    return $decoded;
}

function encode($msg) {

    $this->console("SENT BEFORE ENCODE: $msg");

    $index = $encoded = null;

    $len = strlen($msg);

    for ($index = 0; $index < $len; $index++) {
        $encoded .= $msg[$index] ^ $this->masks[$index % 4];
    }

    $encoded = $this->initFrame . $this->masks . $encoded;

    $this->console("SENT AFTER ENCODE: $encoded");

    return $encoded;
}

Ответы [ 2 ]

2 голосов
/ 28 ноября 2011

Итак, наконец-то нашли проблему.Это было закодировать / декодировать.Или я должен сказать кодировать.Он кодировал сообщение, но не следовал протоколу кадра.Ниже вы найдете новые функции кодирования / декодирования.Я не создал их, я нашел их в другом исходном коде, я просто не помню, где.лол

public function decrypt(&$socket, &$message) {
    //$this->consoleLog("[DECRYPT][BEFORE][PLAIN]: $message");
    //$this->consoleLog("[DECRYPT][BEFORE][HEX]: " . bin2hex($message));
    $data = $message;

    $payloadLength = '';
    $mask = '';
    $unmaskedPayload = '';
    $decodedData = array();

    // estimate frame type:
    $firstByteBinary = sprintf('%08b', ord($data[0]));
    $secondByteBinary = sprintf('%08b', ord($data[1]));
    $opcode = bindec(substr($firstByteBinary, 4, 4));
    $isMasked = ($secondByteBinary[0] == '1') ? true : false;
    $payloadLength = ord($data[1]) & 127;

    // close connection if unmasked frame is received:
    if ($isMasked === false) {
        $this->disconnect($socket);
    }

    switch ($opcode) {
        // text frame:
        case 1:
            $decodedData['type'] = 'text';
            break;

        // connection close frame:
        case 8:
            $decodedData['type'] = 'close';
            break;

        // ping frame:
        case 9:
            $decodedData['type'] = 'ping';
            break;

        // pong frame:
        case 10:
            $decodedData['type'] = 'pong';
            break;

        default:
            // Close connection on unknown opcode:
            //$this->close(1003);
            break;
    }

    if ($payloadLength === 126) {
        $mask = substr($data, 4, 4);
        $payloadOffset = 8;
    } elseif ($payloadLength === 127) {
        $mask = substr($data, 10, 4);
        $payloadOffset = 14;
    } else {
        $mask = substr($data, 2, 4);
        $payloadOffset = 6;
    }

    $dataLength = strlen($data);

    if ($isMasked === true) {
        for ($i = $payloadOffset; $i < $dataLength; $i++) {
            $j = $i - $payloadOffset;
            $unmaskedPayload .= $data[$i] ^ $mask[$j % 4];
        }
        $decodedData['payload'] = $unmaskedPayload;
    } else {
        $payloadOffset = $payloadOffset - 4;
        $decodedData['payload'] = substr($data, $payloadOffset);
    }



    //$this->consoleLog("AFTER DECRYPTION: $decodedData");

    return $decodedData['payload'];
}

public function encrypt(&$socket, &$message, $type = 'text', $masked = true) {

    $payload = $message;

    $frameHead = array();
    $frame = '';
    $payloadLength = strlen($payload);

    switch ($type) {
        case 'text':
            // first byte indicates FIN, Text-Frame (10000001):
            $frameHead[0] = 129;
            break;

        case 'close':
            // first byte indicates FIN, Close Frame(10001000):
            $frameHead[0] = 136;
            break;

        case 'ping':
            // first byte indicates FIN, Ping frame (10001001):
            $frameHead[0] = 137;
            break;

        case 'pong':
            // first byte indicates FIN, Pong frame (10001010):
            $frameHead[0] = 138;
            break;
    }

    // set mask and payload length (using 1, 3 or 9 bytes) 
    if ($payloadLength > 65535) {
        $payloadLengthBin = str_split(sprintf('%064b', $payloadLength), 8);
        $frameHead[1] = ($masked === true) ? 255 : 127;
        for ($i = 0; $i < 8; $i++) {
            $frameHead[$i + 2] = bindec($payloadLengthBin[$i]);
        }
        // most significant bit MUST be 0 (close connection if frame too big)
        if ($frameHead[2] > 127) {
            $this->close(1004);
            return false;
        }
    } elseif ($payloadLength > 125) {
        $payloadLengthBin = str_split(sprintf('%016b', $payloadLength), 8);
        $frameHead[1] = ($masked === true) ? 254 : 126;
        $frameHead[2] = bindec($payloadLengthBin[0]);
        $frameHead[3] = bindec($payloadLengthBin[1]);
    } else {
        $frameHead[1] = ($masked === true) ? $payloadLength + 128 : $payloadLength;
    }

    // convert frame-head to string:
    foreach (array_keys($frameHead) as $i) {
        $frameHead[$i] = chr($frameHead[$i]);
    }
    if ($masked === true) {
        // generate a random mask:
        $mask = array();
        for ($i = 0; $i < 4; $i++) {
            $mask[$i] = chr(rand(0, 255));
        }

        $frameHead = array_merge($frameHead, $mask);
    }
    $frame = implode('', $frameHead);

    // append payload to frame:
    $framePayload = array();
    for ($i = 0; $i < $payloadLength; $i++) {
        $frame .= ($masked === true) ? $payload[$i] ^ $mask[$i % 4] : $payload[$i];
    }


    //$this->consoleLog("[ENCRYPT][AFTER][PLAIN]: $frame");
    //$this->consoleLog("[ENCRYPT][BEFORE][AFTER]: " . bin2hex($frame));


    return $frame;
}
0 голосов
/ 28 ноября 2011

Схожая проблема с использованием кода phpwebsocket Джорджа Навы, браузера Opera и Firefox, при этом ответы сервера, по-видимому, усечены. Я проверил короткую запись в сокет на сервере - все в порядке. Wireshark показывает, что все байты, записанные сервером, пришли в одном сообщении.

Похоже, это функция современных браузеров?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...