Reputation: 767
Let's start from the beginning: I have installed Wamp Server (version: 2.4.9, php: 5.5.12), and I want to create a simple chat with web sockets.
Great, for this i create two files:
Connect.js
window.onload = function() {
var form = document.getElementById('mensagem-formulario');
var mensagemTexto = document.getElementById('mensagem');
var listaMensagem = document.getElementById('mensagens');
var socketStatus = document.getElementById('status');
var btnFechar = document.getElementById('close');
var socket = new WebSocket('ws://localhost:8080');
socket.onopen = function(event) {
socketStatus.innerHTML = 'Connect with ' + event.currentTarget.URL; socketStatus.className = 'open';
};
socket.onerror = function(error) {
console.log('Error: ' + error);
socketStatus.innerHTML = 'Error: ' + error;
};
form.onsubmit = function(e) { e.preventDefault(); /
var mensagem = mensagemTexto.value;
socket.send(mensagem);
listaMensagem.innerHTML += '<li class="envia"><span>Enviado:</span>' + mensagem + '</li>';
mensagemTexto.value = ''; return false;
};
socket.onmessage = function(event) {
var mensagem = event.data; listaMensagem.innerHTML += '<li class="recebida"><span>Recebida:</span>' + mensagem + '</li>';
};
socket.onclose = function(event) {
socketStatus.innerHTML = 'Disconectado do WebSocket.'; socketStatus.className = 'closed';
};
btnFechar.onclick = function(e) {
e.preventDefault();
socket.close(); return false;
};
};
Server.php
<?php
$server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($server, "localhost", 8080);
socket_listen($server);
$client = socket_accept($server);
$message = socket_read($client, 5000);
$matches = array();
preg_match('#Sec-WebSocket-Key: (.*)\r\n#', $message, $matches);
$new_key = new_key($matches[1]);
$new_message = "HTTP/1.1 101 Switching Protocols\r\n";
$new_message .= "Upgrade: websocket\r\n";
$new_message .= "Connection: Upgrade\r\n";
$new_message .= "Sec-WebSocket-Accept: " . $new_key . "\r\n\r\n";
socket_write($client, $new_message, strlen($new_message));
$new_message = "Test message !";
socket_write($client, $new_message, strlen($new_message));
function new_key($key)
{
$key .= "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
$key = sha1($key);
$new_key = '';
for ($i = 0; $i < strlen($key); $i+=2)
{
$new_key .= chr(intval($key[$i] . $key[$i+1], 16));
}
$new_key = base64_encode($new_key);
return $new_key;
}
/* End of file server.php */
?>
Great, now lets test this code:
When I open connect.js the server.php stop to load in another tab, in console log javascript send to me the following errors:
WebSocket connection to 'ws://localhost:8080/' failed: One or more reserved bits are on: reserved1 = 1, reserved2 = 0, reserved3 = 1
How can I solve this problem? Is a syntax problem or server problem? (I don't want to use node.js, socket.io and others, I'm trying to do it by hand).
Upvotes: 2
Views: 1759
Reputation: 767
Solution
The problem with this code is the php server, So if you're having the same problem, you need to create a new file called server.php and put this code below inside him:
<?php
error_reporting(E_ALL);
set_time_limit(0);
$adr = "localhost";
echo $adr."\n\n";
$port = 8080;
$m_sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($m_sock, SOL_SOCKET, SO_REUSEADDR, 1);
$cls = array($m_sock);
socket_bind($m_sock, $adr, $port);
socket_listen($m_sock, 5);
echo "Starting server...\n\n";
do{
usleep(500);
$changed = $cls;
$val = @socket_select($changed,$write=NULL,$except=NULL,0);
foreach ($changed as $sock) {
if($sock === $m_sock){
echo "wait...\n\n";
$msgsock = socket_accept($m_sock);
array_push($cls, $msgsock);
echo "Connected...\n\n";
socket_recv($msgsock, $hds, 4096, 0);
if(preg_match("/Sec-WebSocket-Key: (.*)\r\n/",$hds,$matchs)){
echo "do handshake...\n\n";
$key = $matchs[1] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
$key = base64_encode(sha1($key, true));
$headers = "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($msgsock, $headers);
echo "handshak done...\n";
}
}else{
$bytes = socket_recv($sock, $data, 2048, null);
$d = unmask($data);
foreach ($cls as $socket) {
if($socket != $m_sock && $val > 0){
try{
socket_write($socket,(encode($d)));
}catch(Exception $e){
unset($cls[$socket]);
socket_close($cls[$socket]);
}
}
}
}
}
}while(1);
socket_close($m_sock);
function unmask($payload) {
$length = ord($payload[1]) & 127;
if($length == 126) {
$masks = substr($payload, 4, 4);
$data = substr($payload, 8);
}
elseif($length == 127) {
$masks = substr($payload, 10, 4);
$data = substr($payload, 14);
}
else {
$masks = substr($payload, 2, 4);
$data = substr($payload, 6);
}
$text = '';
for ($i = 0; $i < strlen($data); ++$i) {
$text .= $data[$i] ^ $masks[$i%4];
}
return $text;
}
function encode($text)
{
// 0x1 text frame (FIN + opcode)
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($text);
if($length <= 125)
$header = pack('CC', $b1, $length);
elseif($length > 125 && $length < 65536)
$header = pack('CCS', $b1, 126, $length);
elseif($length >= 65536)
$header = pack('CCN', $b1, 127, $length);
return $header.$text;
}
?>
Upvotes: 1