2011-11-24 101 views
2

我在過去的幾個小時裏一直在研究這個問題......我已經克服了消息的編碼和解碼。發送的消息被截斷爲接收數據的大小

但是,我現在面臨着一個不同的問題。我可以下達指令,然而,每個命令的響應將被截斷,以接收到的字符串的長度...

預期聊天結果:哦,親愛的,我是152
接收到的聊天結果:哦

調試從服務器:

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; 
} 
+0

所以...經過多次調試,我仍然卡住了。我發現加密的消息是整個字符串。但是,通過PHP套接字發送的內容會被截斷。 –

回答

1

所以,終於找到了問題。這是編碼/解碼。或者我應該說編碼。它正在對消息進行編碼,但沒有遵循幀協議。下面你會發現新的編碼/解碼功能。我沒有創建這些,我發現他們在另一個源代碼中,我只是不記得在哪裏。大聲笑

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

在使用phpwebsocket代碼由喬治·納瓦和兩個Opera和Firefox瀏覽器與服務器的響應顯然截斷類似的問題。 我檢查了一個簡短的寫入到服務器的套接字 - 它沒問題。 Wireshark顯示服務器寫入的所有字節都到達一條消息。

似乎是當前瀏覽器的功能?