проблема php websocket - PullRequest
       10

проблема php websocket

2 голосов
/ 04 августа 2011

Я новичок в веб-сокетах ... Я сделал свой первый веб-сокет, и у меня сейчас проблемы с его запуском!

вот код розетки

// set some variables 
$host = "127.0.0.1"; 
$port = 1234; 

// don't timeout! 
set_time_limit(0); 

// create socket 
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n"); 
if($socket){
    echo "socket created .... $socket\n";
}

// bind socket to port 
$result = socket_bind($socket, $host, $port) or die("Could not bind to socket\n"); 
if($result){
    echo "socket binded ... $result\n";
}
// start listening for connections 
$result = socket_listen($socket, 3) or die("Could not set up socket listener\n"); 
if($result){
    echo "socket is now listening ... $result";
}
// accept incoming connections 
// spawn another socket to handle communication 
$spawn = socket_accept($socket) or die("Could not accept incoming connection\n"); 
if($spawn){
    echo $spawn."\n";
}
// read client input 
$input = socket_read($spawn, 1024) or die("Could not read input\n"); 
if($input){
    echo $input."\n";
}
// clean up input string 
$input = trim($input); 

// reverse client input and send back 
$output = strrev($input) . "\n"; 
socket_write($spawn, $output, strlen ($output)) or die("Could not write output\n"); 

// close sockets 
socket_close($spawn); 
socket_close($socket);

Теперь, как я могу запустить этот код? я написал на моей оболочке xampp следующий код:

php htdocs/socket/server.php -q

отображает:

socket created....Resource id #4
socket binded... 1
socket is now listening...1 Resource is #5
GET socket/server.php HTTP 1.1
upgrade: WebSocket
connection: Upgrade
Host: http://localhost
sec-WebSocket-key1: 14 53    8501 z4 5R'
sec-WebSocket-key2: S 9\ 2s63, *8460!~MO@

Теперь, как я могу запустить его ... Как я могу отправить вход на него и как я могу использовать его с JavaScript ??

Я сделал код JavaScript, но он подключился на секунду, а затем отключился ...

вот код javascipt:

$(document).ready(function() {

if(!("WebSocket" in window)){
    $('#chatLog, input, button, #examples').fadeOut("fast");    
    $('<p>Oh no, you need a browser that supports WebSockets. How about <a   href="http://www.google.com/chrome">Google Chrome</a>?</p>').appendTo('#container');       
}else{
    //The user has WebSockets

connect();

function connect(){
        var socket;
        var host = "ws://localhost:1234/websocket_source_files/myown.php";

        try{
            var socket = new WebSocket(host);
            message('<p class="event">Socket Status: '+socket.readyState);
            socket.onopen = function(){
                message('<p class="event">Socket Status: '+socket.readyState+' (open)');    
            }

            socket.onmessage = function(msg){
                message('<p class="message">Received: '+msg.data);                  
            }

            socket.onclose = function(){
                message('<p class="event">Socket Status: '+socket.readyState+' (Closed)');
            }           

        } catch(exception){
            message('<p>Error'+exception);
        }

        function send(){
            var text = $('#text').val();
            if(text==""){
                message('<p class="warning">Please enter a message');
                return ;    
            }
            try{
                socket.send(text);
                message('<p class="event">Sent: '+text)
            } catch(exception){
                message('<p class="warning">');
            }
            $('#text').val("");
        }

        function message(msg){
            $('#chatLog').append(msg+'</p>');
        }//End message()

        $('#text').keypress(function(event) {
                  if (event.keyCode == '13') {
                     send();
                   }
        }); 

        $('#disconnect').click(function(){
            socket.close();
        });

    }


}//End connect()

});
</script>

<title>WebSockets Client</title>

</head>
<body>
<div id="wrapper">

<div id="container">

    <h1>WebSockets Client</h1>

    <div id="chatLog">

    </div>
    <p id="examples">e.g. try 'hi', 'name', 'age', 'today'</p>

    <input id="text" type="text" />
    <button id="disconnect">Disconnect</button>

</div>

  </div>
</body>
</html>​

, пожалуйста, помогите мне запустить этот код и изучить веб-сокеты .. Мне действительно нужно использовать их с моим школьным проектом.

Ответы [ 3 ]

2 голосов
/ 04 августа 2011

Функция socket_accept блокирует (ждет), пока клиент не подключится к нему.Это стандартное поведение.

Но функции, которые вы выполняете после того, как вы подключили сокет, не блокируются (если вы не скажете им это).Таким образом, вы захотите попросить ваш скрипт подождать, пока он не сможет читать из сокета.

Для этого используется функция socket_set_block .Кроме того, вы можете проверить наличие возможных ошибок, используя socket_last_error -функцию .

Хотя я думаю, что Java или C лучше подходят для использования сокетов.

0 голосов
/ 05 августа 2011

вы не делаете рукопожатие должным образом.

из того, что вы опубликовали, вы имеете дело с реализацией 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>
0 голосов
/ 04 августа 2011

Напишите другой PHP-скрипт, который будет подключаться к нему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...