Xpoint
   [напомнить пароль]

web socket

Метки: [без меток]
[удл]
2010-07-13 10:41:01 [обр] Александр Петров(2/4)[досье]
Здравствуйте пишу сервер, точнее переделываю немного для работы с web sockets готовый
Наткнулся на проблему в chrome, копал, читал здесь http://www.whatwg.org/specs/web-socket-protocol/ и понял что при рукопожатии (1.3. Opening handshake) chrome ведет себя по стандарту, т.е. сервер должен вернуть обработанный заголовок и тогда клиент понимает что сервер хороший и принимает его рукопожатие. Иначе нет. Помогите пожалуйста что значат эти слова и как это на php реализовать, я имею ввиду подготовку строки для возвращения клиенту.

The third piece of information is given after the fields, in the last
   eight bytes of the handshake, expressed here as they would be seen if
   interpreted as ASCII:

        Tm[K T2u

   The concatenation of the number obtained from processing the |Sec-
   WebSocket-Key1| field, expressed as a big-endian 32 bit number, the
   number obtained from processing the |Sec-WebSocket-Key2| field, again
   expressed as a big-endian 32 bit number, and finally the eight bytes
   at the end of the handshake, form a 128 bit string whose MD5 sum is
   then used by the server to prove that it read the handshake.

спустя 54 минуты [обр] Евгений Седов aka KPbIC(7/176)[досье]
Какое слово непонятно?
спустя 2 минуты [обр] Александр Петров(2/4)[досье]

http://www.websockets.ru/node/8 нашел русский перевод

Но и это еще не все. Дальше идет нечто совершенно безумное, похожее на тело GET-запроса. Страшно писать такие слова...
Два полученных числа представляются как big endian 32-битные целые и затем "слепляются" с образование 8 байт. Затем туда же пристыковываются 8 байт из "тела запроса". Вот эти 16 байт и образуют "секретную" подпись. Теперь задача сервера правильно ответить на такой запрос.

Вот это непонятно как реализовать "слепляются", как их слепить

спустя 12 минут [обр] Евгений Седов aka KPbIC(7/176)[досье]
спустя 6 минут [обр] Александр Петров(2/4)[досье]
ок, спасибо сейчас верхнюю часть алгоритма реализую посмотрю то что вы подсказали
спустя 1 час 57 минут [обр] Александр Петров(2/4)[досье]
Евгений Седов aka KPbIC[досье],а подсказку не кинете еще. Что то не соображается
спустя 2 часа 16 минут [обр] Филипп Ткачев(20/112)[досье]
еще в маны: pack() & unpack()
спустя 17 часов [обр] Александр Петров(2/4)[досье]

ни чего у меня не получается такого результата как в статье, все работает только до шагов где слепить нужно (3,4,5), объединять и md5 подсчитывать, вот тут и расхождения. Я вот так делаю

$key1 = '18x 6]8vM;54 *(5: { U1]8 z [ 8';
$key2 = '1_ tx7X d < nw 334J702) 7]o}` 0';
$body = '^n:ds[4U';


function secret ($key1, $key2, $body)   {   
   //1)Получаю сколько цифр и количество пробелов, возвращает массив
        $key1 = secret_($key1);   
   $key2 = secret_($key2);
   print "key1: {$key1[0]}/{$key1[1]}<br/>";
   print "key2: {$key2[0]}/{$key2[1]}<br/>";
   $key1 = $key1[0]/$key1[1];
   settype($key1, "integer");
   $key2 = $key2[0]/$key2[1];
   settype($key2, "integer");
   //2) Итог деления на пробельные символы
   print "key1: {$key1}<br/>";
   print "key2: {$key2}<br/>";
   //3) Слепляю
        //-------------------------------------------
        $binarydata = pack("Ni*", $key1, $key2);   
   print "слепил key1 и key2: {$binarydata}<br/>";
   //4) Объеденяю с телом
        $concat = $binarydata.$body; 
   print "присоеденил тело: {$concat}<br/>";
   //5)Md 5
        $md = md5($concat, true);
   print "md5 всего этого: {$md5}<br/>";
   return $md;
}

и не могу получить на выходе ни как строку fQJ,fN/4F4!~K~MH

спустя 1 час 14 минут [обр] Александр Петров(2/4)[досье]
Ок, разобрался. закончу покажу скрипт его еще отточить нужно
спустя 3 часа 3 минуты [обр] Александр Петров(2/4)[досье]
Собрал из http://code.google.com/p/phpwe......unk/%20phpwebsocket/server.php и http://webreflection.blogspot.......t-handshake-76-simplified.html
#!/php -q
<?php  /*  >php -q server.php  */
//http://code.google.com/p/phpwebsocket/source/browse/trunk/%20phpwebsocket/server.php
//http://webreflection.blogspot.com/2010/06/websocket-handshake-76-simplified.html
error_reporting(E_ALL);
set_time_limit(0);
ob_implicit_flush();

$master  = WebSocket("system.petav",12345);
$sockets = array($master);
$users   = array();
$debug   = true;

while(true){
  $changed = $sockets;
  socket_select($changed,$write=NULL,$except=NULL,NULL);
  foreach($changed as $socket){
    if($socket==$master){
      $client=socket_accept($master);
      if($client<0){ console("socket_accept() failed"); continue; }
      else{ connect($client); }
    }
    else{
      $bytes = @socket_recv($socket,$buffer,2048,0);
      if($bytes==0){ disconnect($socket); }
      else{
        $user = getuserbysocket($socket);
        if(!$user->handshake){ dohandshake($user,$buffer); }
        else{ process($user,$buffer); }
      }
    }
  }
}

//---------------------------------------------------------------
function process($user,$msg){
  $action = unwrap($msg);
  say("< ".$action);
  switch($action){
    case "hello" : send($user->socket,"hello human");                       break;
    case "hi"    : send($user->socket,"zup human");                         break;
    case "name"  : send($user->socket,"my name is Multivac, silly I know"); break;
    case "age"   : send($user->socket,"I am older than time itself");       break;
    case "date"  : send($user->socket,"today is ".date("Y.m.d"));           break;
    case "time"  : send($user->socket,"server time is ".date("H:i:s"));     break;
    case "thanks": send($user->socket,"you're welcome");                    break;
    case "bye"   : send($user->socket,"bye");                               break;
    default      : send($user->socket,$action." not understood");           break;
  }
}

function send($client,$msg){ 
  say("> ".$msg);
  $msg = wrap($msg);
  socket_write($client,$msg,strlen($msg));
} 

function WebSocket($address,$port){
  $master=socket_create(AF_INET, SOCK_STREAM, SOL_TCP)     or die("socket_create() failed");
  socket_set_option($master, SOL_SOCKET, SO_REUSEADDR, 1)  or die("socket_option() failed");
  socket_bind($master, $address, $port)                    or die("socket_bind() failed");
  socket_listen($master,20)                                or die("socket_listen() failed");
  echo "Server Started : ".date('Y-m-d H:i:s')."\n";
  echo "Master socket  : ".$master."\n";
  echo "Listening on   : ".$address." port ".$port."\n\n";
  return $master;
}

function connect($socket){
  global $sockets,$users;
  $user = new User();
  $user->id = uniqid();
  $user->socket = $socket;
  array_push($users,$user);
  array_push($sockets,$socket);
  console($socket." CONNECTED!");
}

function disconnect($socket){
  global $sockets,$users;
  $found=null;
  $n=count($users);
  for($i=0;$i<$n;$i++){
    if($users[$i]->socket==$socket){ $found=$i; break; }
  }
  if(!is_null($found)){ array_splice($users,$found,1); }
  $index = array_search($socket,$sockets);
  socket_close($socket);
  console($socket." DISCONNECTED!");
  if($index>=0){ array_splice($sockets,$index,1); }
}

function dohandshake($user,$buffer){
   console("\nRequesting handshake...");
   console($buffer);
   list($resource, $host, $origin, $cookie, $key1, $key2, $protocol, $code) = getheaders($buffer);
   console("Handshaking...");
   $upgrade  = 
      "HTTP/1.1 101 WebSocket Protocol Handshake\r\n".
      "Upgrade: WebSocket\r\n".
      "Connection: Upgrade\r\n".
      "Sec-WebSocket-Origin: {$origin}\r\n".
      "Sec-WebSocket-Location: ws://{$host}{$resource}\r\n".
      ($protocol ? "Sec-WebSocket-Protocol: {$protocol}\r\n" : "").
      ($cookie ? "Cookie: {$cookie}\r\n" : "").
      "\r\n".
      _createHandshakeThingy($key1, $key2, $code);
   socket_write($user->socket,$upgrade.chr(0),strlen($upgrade.chr(0)));
   $user->handshake=true;
   console($upgrade);
   console("Done handshaking...");
     return true;
}


function _doStuffToObtainAnInt32($key) {
        return preg_match_all('#[0-9]#', $key, $number) && preg_match_all('# #', $key, $space) ?
            implode('', $number[0]) / count($space[0]) :
            ''
        ;
    }

function _createHandshakeThingy($key1, $key2, $code) {
   return md5(
            pack('N', _doStuffToObtainAnInt32($key1)).
            pack('N', _doStuffToObtainAnInt32($key2)).
            $code,
            true
        );
    }


function getheaders($buffer){
   $resource = $host = $origin = $cookie = $key1 = $key2 = $protocol = $code = $handshake = null;
   preg_match('#GET (.*?) HTTP#', $buffer, $match) && $resource = $match[1];
   preg_match("#Host: (.*?)\r\n#", $buffer, $match) && $host = $match[1];
    preg_match("#Sec-WebSocket-Key1: (.*?)\r\n#", $buffer, $match) && $key1 = $match[1];
    preg_match("#Sec-WebSocket-Key2: (.*?)\r\n#", $buffer, $match) && $key2 = $match[1];
    preg_match("#Sec-WebSocket-Protocol: (.*?)\r\n#", $buffer, $match) && $protocol = $match[1];
    preg_match("#Origin: (.*?)\r\n#", $buffer, $match) && $origin = $match[1];
   preg_match("#Cookie: (.*?)\r\n#", $buffer, $match) && $cookie = $match[1];
    preg_match("#\r\n(.*?)\$#", $buffer, $match) && $code = $match[1];
     return array($resource, $host, $origin, $cookie, $key1, $key2, $protocol, $code);
}

function getuserbysocket($socket){
  global $users;
  $found=null;
  foreach($users as $user){
    if($user->socket==$socket){ $found=$user; break; }
  }
  return $found;
}

function     say($msg=""){ echo $msg."\n"; }
function    wrap($msg=""){ return chr(0).$msg.chr(255); }
function  unwrap($msg=""){ return substr($msg,1,strlen($msg)-2); }
function console($msg=""){ global $debug; if($debug){ echo $msg."\n"; } }

class User{
  var $id;
  var $socket;
  var $handshake;
}

?>
спустя 1 час 1 минуту [обр] Александр Петров(2/4)[досье]
Небольшие изменения для того что бы работала и с новой и со старой версией протокола
function dohandshake($user,$buffer){
   console("\nRequesting handshake...");
   console($buffer);
   list($resource, $host, $origin, $cookie, $key1, $key2, $protocol, $code) = getheaders($buffer);
   console("Handshaking...");
   //Рукопожатие новое если есть ключ и старое если нет ключа
   if ($key1 !=null) {
      $upgrade  = 
         "HTTP/1.1 101 WebSocket Protocol Handshake\r\n".
         "Upgrade: WebSocket\r\n".
         "Connection: Upgrade\r\n".
         "Sec-WebSocket-Origin: {$origin}\r\n".
         "Sec-WebSocket-Location: ws://{$host}{$resource}\r\n".
         ($protocol ? "Sec-WebSocket-Protocol: {$protocol}\r\n" : "").
         ($cookie ? "Cookie: {$cookie}\r\n" : "").
         "\r\n".
         _createHandshakeThingy($key1, $key2, $code);      
   }   else   {
      $upgrade  = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
         "Upgrade: WebSocket\r\n" .
         "Connection: Upgrade\r\n" .
         "WebSocket-Origin: " . $origin . "\r\n" .
         "WebSocket-Location: ws://" . $host . $resource . "\r\n" .
         ($protocol ? "WebSocket-Protocol: {$protocol}\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;
}
Powered by POEM™ Engine Copyright © 2002-2005