2016-01-12 50 views
2

讓我們從頭開始:我已經安裝了Wamp服務器(版本:2.4.9,php:5.5.12),我想創建一個簡單的與網絡套接字聊天。WebSockets + PHP插座不工作

大,爲了這個,我創建兩個文件:

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 */ 

    ?> 

大,現在可以測試這個代碼:

  • 首先我啓動我的Wamp服務器
  • 現在我在瀏覽器中打開server.php文件。
  • 太好了,我認爲連接是打開的(因爲文件不停止加載)
  • 現在打開connect.js並查看結果。

當我打開connect.js的server.php停在另一個選項卡中加載,在控制檯日誌的JavaScript發送給我以下錯誤:

WebSocket連接到「WS://本地主機: 8080 /」失敗:一個或多個 保留位上:保留1 = 1,RESERVED2 = 0,reserved3 = 1

如何解決這個問題?是語法問題還是服務器問題? (我不想使用node.js,socket.io和其他人,我試圖用手做)。

+0

我不認爲你可以使用php的websockets,因爲腳本只能在有限的時間內運行,但也許我錯了。 – jcubic

回答

0

解決方案

這段代碼的問題是PHP的服務器,所以,如果你有同樣的問題,你需要創建一個名爲server.php新文件,並把這個代碼在他下面:

<?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; 
} 


?>