вы не делаете рукопожатие должным образом.
из того, что вы опубликовали, вы имеете дело с реализацией ietf-00 (http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00)
это старый и устарелпоследний, кажется, ietf-10 (http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-10).
очень базовое описание рукопожатия, которое вам нужно, можно найти здесь: http://en.wikipedia.org/wiki/WebSockets
(вытам можно найти ссылки на новые и официальные спецификации).
Важная часть в вашем случае это:
Sec-WebSocket-Key1 и Sec-WebSocket-Key2поля и 8 байтов после полей являются случайными токенами, которые сервер использует для создания 16-байтового токена в конце своего рукопожатия, чтобы доказать, что он прочитал рукопожатие клиента.
рукопожатие создается путем объединениячисла от первого ключа и деления на количество пробелов.Затем это повторяется для второго ключа.Два результирующих числа объединяются друг с другом и с последними 8 байтами после полей.
Окончательный результат представляет собой сумму MD5 объединенной строки. [7]Рукопожатие выглядит как HTTP, но на самом деле это не так.Это позволяет серверу интерпретировать часть запроса на квитирование как HTTP, а затем переключиться на WebSocket.После установки фреймы данных WebSocket могут отправляться взад-вперед между клиентом и сервером в полнодуплексном режиме.Текстовые фреймы могут быть отправлены в дуплексном режиме, в любом направлении одновременно.
Данные минимально обрамлены всего двумя байтами.Каждый кадр начинается с байта 0x00, заканчивается байтом 0xFF и содержит промежуточные данные UTF-8.Двоичные кадры еще не поддерживаются в API.Текстовые фреймы WebSocket используют терминатор, в то время как бинарные фреймы используют префикс длины.
Теперь некоторый код (это примет одно соединение, получит сообщение, а затем отправит ответ, как очень простойи пример, демонстрирующий, как это можно сделать):
// Just to log to console
function myLog($msg)
{
echo date('m/d/Y H:i:s ', time()) . $msg . "\n";
}
// This will actually read and process the key-1 and key-2 variables, doing the math for them
function getWebSocketKeyHash($key)
{
$digits = '';
$spaces = 0;
// Get digits
preg_match_all('/([0-9])/', $key, $digits);
$digits = implode('', $digits[0]);
// Count spaces
$spaces = preg_match_all("/\\s/ ", $key, $dummySpaces);
$div = (int)$digits / (int)$spaces;
myLog('key |' . $key . '|: ' . $digits . ' / ' . $spaces . ' = ' . $div);
return (int)$div;
}
// This will read one header: value from the request header
function getWebSocketHeader($buffer, &$lines, &$keys)
{
preg_match_all("/([a-zA-Z0-9\\-]*)(\\s)*:(\\s)*(.*)?\r\n/", $buffer, $headers);
$lines = explode("\r\n", $buffer);
$keys = array_combine($headers[1], $headers[4]);
}
// This is where the handshake gets done
function handshake($peer)
{
$buffer = socket_read($peer, 4096, PHP_BINARY_READ);
socket_getpeername($peer, $address, $port);
$peerName = $address . ':' . $port;
myLog('Got from: ' . $peerName . ': ' . $buffer);
getWebSocketHeader($buffer, $lines, $keys);
if (!isset($keys['Sec-WebSocket-Key1']) || !isset($keys['Sec-WebSocket-Key2'])) {
myLog('Invalid websocket handshake for: ' . $peerName);
return;
}
$key1 = getWebSocketKeyHash($keys['Sec-WebSocket-Key1']);
$key2 = getWebSocketKeyHash($keys['Sec-WebSocket-Key2']);
$code = array_pop($lines);
// Process the result from both keys and form the response header
$key = pack('N', $key1) . pack('N', $key2) . $code;
myLog('1:|' . $key1 . '|- 2:|' . $key2 . '|3:|' . $code . '|4: ' . $key);
$response = "HTTP/1.1 101 WebSocket Protocol Handshake\r\n";
$response .= "Upgrade: WebSocket\r\n";
$response .= "Connection: Upgrade\r\n";
$response .= "Sec-WebSocket-Origin: " . trim($keys['Origin']) . "\r\n";
$response .= "Sec-WebSocket-Location: ws://" . trim($keys['Host']) . "/\r\n";
$response .= "\r\n" . md5($key, true); // this is the actual response including the hash of the result of processing both keys
myLog($response);
socket_write($peer, $response);
}
// This is where you can send a frame (delimited by 0x00 and 0xFF)
function send($peer, $message)
{
socket_write($peer, pack('c', (int)0) . utf8_encode($message) . pack('c', (int)255));
}
// This is where you receive a frame (delimited again by 0x00 and 0xFF)
function receive($peer)
{
$buffer = socket_read($peer, 4096, PHP_BINARY_READ);
if (empty($buffer)) {
myLog('Error receiving from peer');
return;
}
return substr($buffer, 1, -1);
}
// Now create a socket
$socket = socket_create_listen(1026);
$peer = socket_accept($socket);
// Do the handshake and wait for an incoming message from the client
handshake($peer);
myLog('Got ' . receive($peer));
// Respond!
send($peer, 'hi there');
socket_close($peer);
socket_close($socket);
РЕДАКТИРОВАТЬ:
это очень простой HTML, который работает в Chrome (по крайней мере, мой):
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
function WebSocketTest()
{
if ("WebSocket" in window)
{
// Let us open a web socket
var ws = new WebSocket("ws://host:1026");
ws.onopen = function()
{
// Web Socket is connected, send data using send()
ws.send("Message to send");
console.log('send');
};
ws.onmessage = function (evt)
{
var received_msg = evt.data;
console.log(received_msg);
var txt = document.createTextNode(received_msg);
document.getElementById('messages').appendChild(txt);
};
ws.onclose = function()
{
// websocket is closed.
console.log('close');
};
}
else
{
// The browser doesn't support WebSocket
alert("WebSocket NOT supported by your Browser!");
}
}
</script>
</head>
<body>
<div id="sse">
<a href="javascript:WebSocketTest()">Run WebSocket</a>
</div>
<div id="messages">
</div>
</body>
</html>