我实际上在过去的几个小时里一直在做这个…我已经破解了信息的编码和解码。
然而,我现在面临一个差异问题。我可以发出命令,但是,对每个命令的响应被截断为接收到的字符串的长度…
预期聊天结果:哦,亲爱的,我是152
收到的聊天结果:Oh
DEBUGGING FROM SERVER:
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Æð
DEBUGGING FROM CLIENT:
Socket Status: 0 Socket Status: 1 (open) Sent: age Received: Oh
ENCODE和DECODE函数
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;
}
于是,终于找到了问题所在。这是编码/解码。或者我应该说编码。它正在对消息进行编码,但没有遵循帧协议。下面是新的编码/解码函数。我没有创建这些,我在另一个源代码中找到了它们,我只是不记得在哪里。lol
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;
}
使用George Nava的phpwebsocket代码和Opera和Firefox浏览器有类似的问题,服务器响应明显被截断。我检查了一个短写到套接字在服务器-它是好的。Wireshark显示服务器写入的所有字节都在一条消息中到达。
似乎是当前浏览器的一个功能?