问题
Update: I solved the decoding problem, thanks to pimvdb
Follows the solution (in PHP):
$len = $masks = $data = $decoded = null;
$len = ord ($buffer[1]) & 127;
if ($len === 126) {
$masks = substr ($buffer, 4, 4);
$data = substr ($buffer, 8);
}
else if ($len === 127) {
$masks = substr ($buffer, 10, 4);
$data = substr ($buffer, 14);
}
else {
$masks = substr ($buffer, 2, 4);
$data = substr ($buffer, 6);
}
for ($index = 0; $index < strlen ($data); $index++) {
$decoded .= $data[$index] ^ $masks[$index % 4];
}
* Begin of the original topic *
I'm trying to develop HTML5 WebSocket for a personal application, using hybi-17 handshake.
I'm started with phpwebsocket and the only thing I changed is the handshake function, from the original to this:
function dohandshake($user,$buffer){
$key = null;
console("\nRequesting handshake...");
console($buffer);
console("Handshaking...");
preg_match ("#Sec-WebSocket-Key: (.*?)\r\n#", $buffer, $match) && $key = $match[1];
$key .= "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
$key = sha1 ($key);
$key = pack ('H*', $key);
$key = base64_encode ($key);
$upgrade =
"HTTP/1.1 101 Switching Protocols\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"Sec-WebSocket-Accept: {$key}\r\n\r\n";
socket_write($user->socket,$upgrade.chr(0),strlen($upgrade.chr(0)));
$user->handshake=true;
console($upgrade);
console("Done handshaking...");
return true;
}
I used phpwebsocket source code, both for the client (http://code.google.com/p/phpwebsocket/source/browse/trunk/+phpwebsocket/client.html) and the server (http://code.google.com/p/phpwebsocket/source/browse/trunk/+phpwebsocket/server.php).
At this point, I tested the application. Follows the server debug:
Server Started : 2011-10-30 13:45:41
Master socket : Resource id #4
Listening on : localhost port 12345
Resource id #5 CONNECTED!
Requesting handshake...
GET /phpwebsocket/server.php HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: localhost:12345
Sec-WebSocket-Origin: http://localhost
Sec-WebSocket-Key: +S/J2jcp/UKIS1HTW0n1/w==
Sec-WebSocket-Version: 8
Handshaking...
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: LEULWidwXDxY02iv3O+xksrxFz4=
Done handshaking...
< ��z�}p
> ��z�}p not understood
Resource id #5 DISCONNECTED!
And this is the client debug:
WebSocket - status 0
Welcome - status 1
Sent: hello
Disconnected - status 3
What I did was simply connect the client and send the command 'Hello'. As you can see, server received encoded data and not plaintext: why?
I'm looking for someone who helps me to develop html5 websocket with hybi-17.
Cyaz
PS: this (http://stackoverflow.com/questions/7908306/implementing-handshake-for-hybi-17) topic and this one (http://stackoverflow.com/questions/7912772/decoding-network-chars-html5-websocket) might help.
PPS: I tested on Chromium 15.0.874.106~r107270-0ubuntu0.11.04.1
回答1:
Decode solution (thanks to @pimvdb):
$len = $masks = $data = $decoded = null;
$len = ord ($buffer[1]) & 127;
if ($len === 126) {
$masks = substr ($buffer, 4, 4);
$data = substr ($buffer, 8);
}
else if ($len === 127) {
$masks = substr ($buffer, 10, 4);
$data = substr ($buffer, 14);
}
else {
$masks = substr ($buffer, 2, 4);
$data = substr ($buffer, 6);
}
for ($index = 0; $index < strlen ($data); $index++) {
$decoded .= $data[$index] ^ $masks[$index % 4];
}
回答2:
This encode function is great except that chrome 19 doesn't like the data being masked. I get this error after sending the first message to server: "A server must not mask any frames that it sends to the client."
I couldn't figure out how to not mask the data being sent to the server until I found a github example that works and has a flag you can set to not mask the data frames. https://github.com/lemmingzshadow/php-websocket
I had found this updated version of the phpwebsocket code: http://www.wilky.it/phpwebsocket-new-version/ One thing you need to fix in this to make it work is replace this line at line 234: preg_match ("#Sec-WebSocket-Origin: (.*?)\r\n#", $buffer, $match) && $origin = $match[1]; with preg_match ("#Origin: (.*?)\r\n#", $buffer, $match) && $origin = $match[1];
Then to fix the error in chrome: "A server must not mask any frames that it sends to the client." do the following: I fixed the replaced the encode function with the one in the connection.php file in lemmingzshadow's github and it started working. The function is called: hybi10Encode in the \server\lib\WebSocket\connection.php file. change this parameter in the function encode: $masked = true to $masked = false So we have 2 versions that work now in chrome and firefox 12!
来源:https://stackoverflow.com/questions/7945040/html5-websocket-with-hybi-17