{"id":209864,"date":"2014-01-22T12:57:08","date_gmt":"2014-01-22T08:57:08","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=209864"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=209864","title":{"rendered":"<span class=\"post_title\">\u0414\u0435\u043b\u0430\u0435\u043c \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u044b \u043d\u0430 PHP \u0441 \u043d\u0443\u043b\u044f<\/span>"},"content":{"rendered":"<div class=\"content html_format\"> \t\t\t\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u0437\u0430\u0434 \u044f \u0432\u044b\u0431\u0438\u0440\u0430\u043b \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u0430\u043c\u0438. \u041d\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u0440\u0430\u0445 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430 \u044f \u043d\u0430\u0442\u044b\u043a\u0430\u043b\u0441\u044f \u043d\u0430 \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u043e \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 node.js \u0441 yii, \u0430 \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u043e \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u0430\u0445 \u043d\u0430 \u0445\u0430\u0431\u0440\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u043b\u0438\u0441\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f\u043c\u0438 \u043a \u0442\u043e\u043c\u0443, \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c phpdaemon.<\/p>\n<p>  \u042f \u0438\u0437\u0443\u0447\u0430\u043b \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 <a href=\"http:\/\/daemon.io\/\">phpdaemon<\/a> \u0438 <a href=\"http:\/\/socketo.me\/\">ratchet<\/a>, \u043e\u043d\u0438 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043c\u043e\u043d\u0441\u0442\u0440\u0443\u043e\u0437\u043d\u044b (\u043f\u0440\u0438\u0447\u0451\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f ratchet \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u043d\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"http:\/\/wamp.ws\/\">wamp<\/a>). \u041c\u043d\u0435 \u043d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u0431\u044b\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0434\u043b\u044f \u0447\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u0438\u0445 \u043c\u043e\u043d\u0441\u0442\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u0434\u0440\u0443\u0433\u0438\u0445 \u043c\u043e\u043d\u0441\u0442\u0440\u043e\u0432. \u041f\u043e\u0447\u0438\u0442\u0430\u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u044d\u0442\u0438\u0445, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u0440\u0443\u0433\u0438\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a, \u044f \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0441\u044f \u043a\u0430\u043a \u0432\u0441\u0451 \u0443\u0441\u0442\u0440\u043e\u0435\u043d\u043e \u0438 \u043c\u043d\u0435 \u0437\u0430\u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442-\u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 php \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e. \u042d\u0442\u043e \u043f\u043e\u043c\u043e\u0433\u043b\u043e \u043c\u043d\u0435 \u0437\u0430\u043a\u0440\u0435\u043f\u0438\u0442\u044c \u0438\u0437\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0438 \u043d\u0430\u0442\u043a\u043d\u0443\u0442\u044c\u0441\u044f \u043d\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0435 \u043a\u0430\u043c\u043d\u0438, \u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u044f \u043d\u0435 \u0438\u043c\u0435\u043b \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f.<\/p>\n<p>  \u0422\u0430\u043a \u044f \u0440\u0435\u0448\u0438\u043b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u0434\u043b\u044f \u043c\u0435\u043d\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0441 \u043d\u0443\u043b\u044f.<br \/>  <a name=\"habracut\"><\/a>  <\/p>\n<h4>\u041f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0446\u0435\u043b\u0438:<\/h4>\n<p>  1) \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u043c\u0438 \u0441\u043e\u043a\u0435\u0442\u0430\u043c\u0438 \u0432 php<br \/>  2) \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0441 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u043e\u043c \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u043e\u0432<br \/>  3) \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441 \u043d\u0443\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u043e\u0432<\/p>\n<h4>1) \u0421\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0435 \u0441\u043e\u043a\u0435\u0442\u044b \u0432 php<\/h4>\n<p>  \u0414\u043e \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u044f \u0438\u043c\u0435\u043b \u0441\u043c\u0443\u0442\u043d\u044b\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043e \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0445 \u0441\u043e\u043a\u0435\u0442\u0430\u0445. \u041f\u043e\u0447\u0438\u0442\u0430\u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u0430\u043c\u0438 \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u0434\u0432\u0443\u043c\u044f \u0441\u0445\u0435\u043c\u0430\u043c\u0438 \u0438\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439:<\/p>\n<p>  \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 php \u00absocket\u00bb:  <\/p>\n<pre><code class=\"php\">$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);\/\/\u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0441\u043e\u043a\u0435\u0442 socket_bind($socket, '127.0.0.1', 8000);\/\/\u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u043c \u0435\u0433\u043e \u043a \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u043c ip \u0438 \u043f\u043e\u0440\u0442\u0443 socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);\/\/\u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u043f\u043e\u0440\u0442 \u0434\u043b\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 socket_listen($socket);\/\/\u0441\u043b\u0443\u0448\u0430\u0435\u043c \u0441\u043e\u043a\u0435\u0442 <\/code><\/pre>\n<p>  \u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 php \u00abstream\u00bb:  <\/p>\n<pre><code class=\"php\">$socket = stream_socket_server(&quot;tcp:\/\/127.0.0.1:8000&quot;, $errno, $errstr); <\/code><\/pre>\n<p>  \u042f \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0451\u043b \u0432\u0442\u043e\u0440\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0432\u0432\u0438\u0434\u0443 \u0435\u0433\u043e \u043a\u0440\u0430\u0442\u043a\u043e\u0441\u0442\u0438.<\/p>\n<p>  \u0418\u0442\u0430\u043a, \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 \u0441\u043e\u043a\u0435\u0442 \u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u0445\u043e\u0442\u0438\u043c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043a \u043d\u0435\u043c\u0443, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043e\u043f\u044f\u0442\u044c \u0436\u0435 \u0435\u0441\u0442\u044c \u0434\u0432\u0430 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430  <\/p>\n<pre><code class=\"php\">while ($connect = stream_socket_accept($socket, -1)) {\/\/\u043e\u0436\u0438\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 (\u0431\u0435\u0437 \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u0430)     ...\u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c $connect } <\/code><\/pre>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e http \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430 \u0432\u0441\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442: \u041f\u0440\u0438\u0432\u0435\u0442<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"php\">#!\/usr\/bin\/env php &lt;?php  $socket = stream_socket_server(&quot;tcp:\/\/0.0.0.0:8000&quot;, $errno, $errstr);  if (!$socket) {     die(&quot;$errstr ($errno)\\n&quot;); }  while ($connect = stream_socket_accept($socket, -1)) {     fwrite($connect, &quot;HTTP\/1.1 200 OK\\r\\nContent-Type: text\/html\\r\\nConnection: close\\r\\n\\r\\n\u041f\u0440\u0438\u0432\u0435\u0442&quot;);     fclose($connect); }  fclose($socket); <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0438\u043b\u0438 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c stream_select<\/p>\n<pre><code class=\"php\">$connects = array(); while (true) {     \/\/\u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u043f\u0440\u043e\u0441\u043b\u0443\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0441\u043e\u043a\u0435\u0442\u043e\u0432:     $read = $connects;     $read[] = $socket;     $write = $except = null;          if (!stream_select($read, $write, $except, null)) {\/\/\u043e\u0436\u0438\u0434\u0430\u0435\u043c \u0441\u043e\u043a\u0435\u0442\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f (\u0431\u0435\u0437 \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u0430)         break;     }      if (in_array($socket, $read)) {\/\/\u0435\u0441\u0442\u044c \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435         $connect = stream_socket_accept($socket, -1);\/\/\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u043c \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435         $connects[] = $connect;\/\/\u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438         unset($read[ array_search($socket, $read) ]);     }      foreach($read as $connect) {\/\/\u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u0432\u0441\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f         ...\u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c $connect         unset($connects[ array_search($connect, $connects) ]);     } } <\/code><\/pre>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e http \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c stream_select, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430 \u0432\u0441\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442: \u041f\u0440\u0438\u0432\u0435\u0442<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"php\">#!\/usr\/bin\/env php &lt;?php  $socket = stream_socket_server(&quot;tcp:\/\/0.0.0.0:8000&quot;, $errno, $errstr);  if (!$socket) {     die(&quot;$errstr ($errno)\\n&quot;); }  $connects = array(); while (true) {     \/\/\u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u043f\u0440\u043e\u0441\u043b\u0443\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0441\u043e\u043a\u0435\u0442\u043e\u0432:     $read = $connects;     $read []= $socket;     $write = $except = null;      if (!stream_select($read, $write, $except, null)) {\/\/\u043e\u0436\u0438\u0434\u0430\u0435\u043c \u0441\u043e\u043a\u0435\u0442\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f (\u0431\u0435\u0437 \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u0430)         break;     }      if (in_array($socket, $read)) {\/\/\u0435\u0441\u0442\u044c \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435         $connect = stream_socket_accept($socket, -1);\/\/\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u043c \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435         $connects[] = $connect;\/\/\u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438         unset($read[ array_search($socket, $read) ]);     }      foreach($read as $connect) {\/\/\u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u0432\u0441\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f         $headers = '';         while ($buffer = rtrim(fgets($connect))) {             $headers .= $buffer;         }         fwrite($connect, &quot;HTTP\/1.1 200 OK\\r\\nContent-Type: text\/html\\r\\nConnection: close\\r\\n\\r\\n\u041f\u0440\u0438\u0432\u0435\u0442&quot;);         fclose($connect);         unset($connects[ array_search($connect, $connects) ]);     } }  fclose($server); <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0422.\u043a. \u043d\u0430\u043c \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 \u0441\u043e\u043a\u0435\u0442 \u043d\u0430 \u043f\u0440\u0435\u0434\u043c\u0435\u0442 \u043d\u043e\u0432\u044b\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439, \u0438 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f, \u043d\u0430 \u043f\u0440\u0435\u0434\u043c\u0435\u0442 \u043d\u043e\u0432\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u0442\u043e \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c\u0441\u044f \u043d\u0430 \u0432\u0442\u043e\u0440\u043e\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435.<\/p>\n<h4>2) \u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u043e\u0432<\/h4>\n<p>  \u0412 <a href=\"http:\/\/habrahabr.ru\/post\/179585\/\">\u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a> \u0445\u043e\u0440\u043e\u0448\u043e \u043e\u043f\u0438\u0441\u0430\u043d \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f.<br \/>  \u041d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u0434\u0432\u0430 \u043c\u043e\u043c\u0435\u043d\u0442\u0430:  <\/p>\n<h5>\u00ab\u0420\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u0435\u00bb \u0438\u043b\u0438 handshake:<\/h5>\n<p>  \u0421\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 Sec-WebSocket-Key \u0438\u0437 \u043f\u0440\u0438\u0448\u0435\u0434\u0448\u0435\u0433\u043e \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430, \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u043d\u0430 \u0435\u0433\u043e \u043e\u0441\u043d\u043e\u0432\u0435 Sec-WebSocket-Accept \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u0442\u043e\u0433\u043e\u0432\u044b\u0439 \u043e\u0442\u0432\u0435\u0442:  <\/p>\n<pre><code class=\"php\">$SecWebSocketAccept = base64_encode(pack('H*', sha1($SecWebSocketKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'))); $response = &quot;HTTP\/1.1 101 Web Socket Protocol Handshake\\r\\n&quot; .     &quot;Upgrade: websocket\\r\\n&quot; .     &quot;Connection: Upgrade\\r\\n&quot; .     &quot;Sec-WebSocket-Accept:$SecWebSocketAccept\\r\\n\\r\\n&quot;; <\/code><\/pre>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041f\u0440\u0438\u043c\u0435\u0440 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"php\">function handshake($connect) {     $info = array();      $line = fgets($connect);     $header = explode(' ', $line);     $info['method'] = $header[0];     $info['uri'] = $header[1];      \/\/\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u0438\u0437 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f     while ($line = rtrim(fgets($connect))) {         if (preg_match('\/\\A(\\S+): (.*)\\z\/', $line, $matches)) {             $info[$matches[1]] = $matches[2];         } else {             break;         }     }      $address = explode(':', stream_socket_get_name($connect, true)); \/\/\u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0430\u0434\u0440\u0435\u0441 \u043a\u043b\u0438\u0435\u043d\u0442\u0430     $info['ip'] = $address[0];     $info['port'] = $address[1];      if (empty($info['Sec-WebSocket-Key'])) {         return false;     }      \/\/\u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u0430     $SecWebSocketAccept = base64_encode(pack('H*', sha1($info['Sec-WebSocket-Key'] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));     $upgrade = &quot;HTTP\/1.1 101 Web Socket Protocol Handshake\\r\\n&quot; . \t&quot;Upgrade: websocket\\r\\n&quot; . \t&quot;Connection: Upgrade\\r\\n&quot; . \t&quot;Sec-WebSocket-Accept:$SecWebSocketAccept\\r\\n\\r\\n&quot;;     fwrite($connect, $upgrade);      return $info; } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<h5>\u043e\u0431\u043c\u0435\u043d \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u043c\u0438<\/h5>\n<p>  \u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u0430 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0438\u0445 \u0440\u0430\u0441\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0430 \u043f\u0440\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u0437\u0430\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c.<br \/>  \u0412\u0441\u0451 \u0432 <a href=\"http:\/\/habrahabr.ru\/post\/179585\/\">\u0442\u043e\u0439 \u0436\u0435 \u0441\u0442\u0430\u0442\u044c\u0435<\/a> \u0445\u043e\u0440\u043e\u0448\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u043d\u043e \u043d\u0430\u043c \u043f\u043e-\u0441\u0443\u0442\u0438 \u043d\u0443\u0436\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u0432\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438: decode \u0438 encode.  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041f\u0440\u0438\u043c\u0435\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 decode \u0438 encode<\/b><\/p>\n<div class=\"spoiler_text\">function decode($data)<br \/>  {<br \/>   $unmaskedPayload = &#187;;<br \/>   $decodedData = array();<\/p>\n<p>  \/\/ estimate frame type:<br \/>   $firstByteBinary = sprintf(&#8216;%08b&#8217;, ord($data[0]));<br \/>   $secondByteBinary = sprintf(&#8216;%08b&#8217;, ord($data[1]));<br \/>   $opcode = bindec(substr($firstByteBinary, 4, 4));<br \/>   $isMasked = ($secondByteBinary[0] == &#8216;1&#8217;)? true: false;<br \/>   $payloadLength = ord($data[1]) &#038; 127;<\/p>\n<p>  \/\/ unmasked frame is received:<br \/>   if (!$isMasked) {<br \/>   return array(&#8216;type&#8217; =&gt; &#187;, &#8216;payload&#8217; =&gt; &#187;, &#8216;error&#8217; =&gt; &#8216;protocol error (1002)&#8217;);<br \/>   }<\/p>\n<p>  switch ($opcode) {<br \/>   \/\/ text frame:<br \/>   case 1:<br \/>   $decodedData[&#8216;type&#8217;] = &#8216;text&#8217;;<br \/>   break;<\/p>\n<p>  case 2:<br \/>   $decodedData[&#8216;type&#8217;] = &#8216;binary&#8217;;<br \/>   break;<\/p>\n<p>  \/\/ connection close frame:<br \/>   case 8:<br \/>   $decodedData[&#8216;type&#8217;] = &#8216;close&#8217;;<br \/>   break;<\/p>\n<p>  \/\/ ping frame:<br \/>   case 9:<br \/>   $decodedData[&#8216;type&#8217;] = &#8216;ping&#8217;;<br \/>   break;<\/p>\n<p>  \/\/ pong frame:<br \/>   case 10:<br \/>   $decodedData[&#8216;type&#8217;] = &#8216;pong&#8217;;<br \/>   break;<\/p>\n<p>  default:<br \/>   return array(&#8216;type&#8217; =&gt; &#187;, &#8216;payload&#8217; =&gt; &#187;, &#8216;error&#8217; =&gt; &#8216;unknown opcode (1003)&#8217;);<br \/>   }<\/p>\n<p>  if ($payloadLength === 126) {<br \/>   $mask = substr($data, 4, 4);<br \/>   $payloadOffset = 8;<br \/>   $dataLength = bindec(sprintf(&#8216;%08b&#8217;, ord($data[2])). sprintf(&#8216;%08b&#8217;, ord($data[3]))) + $payloadOffset;<br \/>   } elseif ($payloadLength === 127) {<br \/>   $mask = substr($data, 10, 4);<br \/>   $payloadOffset = 14;<br \/>   $tmp = &#187;;<br \/>   for ($i = 0; $i &lt; 8; $i++) {<br \/>   $tmp .= sprintf(&#8216;%08b&#8217;, ord($data[$i + 2]));<br \/>   }<br \/>   $dataLength = bindec($tmp) + $payloadOffset;<br \/>   unset($tmp);<br \/>   } else {<br \/>   $mask = substr($data, 2, 4);<br \/>   $payloadOffset = 6;<br \/>   $dataLength = $payloadLength + $payloadOffset;<br \/>   }<\/p>\n<p>  \/**<br \/>   * We have to check for large frames here. socket_recv cuts at 1024 bytes<br \/>   * so if websocket-frame is &gt; 1024 bytes we have to wait until whole<br \/>   * data is transferd.<br \/>   *\/<br \/>   if (strlen($data) &lt; $dataLength) {<br \/>   return false;<br \/>   }<\/p>\n<p>  if ($isMasked) {<br \/>   for ($i = $payloadOffset; $i &lt; $dataLength; $i++) {<br \/>   $j = $i \u2014 $payloadOffset;<br \/>   if (isset($data[$i])) {<br \/>   $unmaskedPayload .= $data[$i] ^ $mask[$j % 4];<br \/>   }<br \/>   }<br \/>   $decodedData[&#8216;payload&#8217;] = $unmaskedPayload;<br \/>   } else {<br \/>   $payloadOffset = $payloadOffset \u2014 4;<br \/>   $decodedData[&#8216;payload&#8217;] = substr($data, $payloadOffset);<br \/>   }<\/p>\n<p>  return $decodedData;<br \/>  }<\/p>\n<p>  function encode($payload, $type = &#8216;text&#8217;, $masked = false)<br \/>  {<br \/>   $frameHead = array();<br \/>   $payloadLength = strlen($payload);<\/p>\n<p>  switch ($type) {<br \/>   case &#8216;text&#8217;:<br \/>   \/\/ first byte indicates FIN, Text-Frame (10000001):<br \/>   $frameHead[0] = 129;<br \/>   break;<\/p>\n<p>  case &#8216;close&#8217;:<br \/>   \/\/ first byte indicates FIN, Close Frame(10001000):<br \/>   $frameHead[0] = 136;<br \/>   break;<\/p>\n<p>  case &#8216;ping&#8217;:<br \/>   \/\/ first byte indicates FIN, Ping frame (10001001):<br \/>   $frameHead[0] = 137;<br \/>   break;<\/p>\n<p>  case &#8216;pong&#8217;:<br \/>   \/\/ first byte indicates FIN, Pong frame (10001010):<br \/>   $frameHead[0] = 138;<br \/>   break;<br \/>   }<\/p>\n<p>  \/\/ set mask and payload length (using 1, 3 or 9 bytes)<br \/>   if ($payloadLength &gt; 65535) {<br \/>   $payloadLengthBin = str_split(sprintf(&#8216;%064b&#8217;, $payloadLength), 8);<br \/>   $frameHead[1] = ($masked === true)? 255: 127;<br \/>   for ($i = 0; $i &lt; 8; $i++) {<br \/>   $frameHead[$i + 2] = bindec($payloadLengthBin[$i]);<br \/>   }<br \/>   \/\/ most significant bit MUST be 0<br \/>   if ($frameHead[2] &gt; 127) {<br \/>   return array(&#8216;type&#8217; =&gt; &#187;, &#8216;payload&#8217; =&gt; &#187;, &#8216;error&#8217; =&gt; &#8216;frame too large (1004)&#8217;);<br \/>   }<br \/>   } elseif ($payloadLength &gt; 125) {<br \/>   $payloadLengthBin = str_split(sprintf(&#8216;%016b&#8217;, $payloadLength), 8);<br \/>   $frameHead[1] = ($masked === true)? 254: 126;<br \/>   $frameHead[2] = bindec($payloadLengthBin[0]);<br \/>   $frameHead[3] = bindec($payloadLengthBin[1]);<br \/>   } else {<br \/>   $frameHead[1] = ($masked === true)? $payloadLength + 128: $payloadLength;<br \/>   }<\/p>\n<p>  \/\/ convert frame-head to string:<br \/>   foreach (array_keys($frameHead) as $i) {<br \/>   $frameHead[$i] = chr($frameHead[$i]);<br \/>   }<br \/>   if ($masked === true) {<br \/>   \/\/ generate a random mask:<br \/>   $mask = array();<br \/>   for ($i = 0; $i &lt; 4; $i++) {<br \/>   $mask[$i] = chr(rand(0, 255));<br \/>   }<\/p>\n<p>  $frameHead = array_merge($frameHead, $mask);<br \/>   }<br \/>   $frame = implode(&#187;, $frameHead);<\/p>\n<p>  \/\/ append payload to frame:<br \/>   for ($i = 0; $i &lt; $payloadLength; $i++) {<br \/>   $frame .= ($masked === true)? $payload[$i] ^ $mask[$i % 4]: $payload[$i];<br \/>   }<\/p>\n<p>  return $frame;<br \/>  }<\/p><\/div>\n<\/div>\n<h4>\u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u043e\u0432<\/h4>\n<p>  \u0418\u0442\u0430\u043a, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0432\u0441\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f.<br \/>  \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043a\u043e\u0434 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e http \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 handshake, decode \u0438 encode \u0438\u0437 \u0432\u0442\u043e\u0440\u043e\u0439 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u043e\u0432.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041f\u0440\u0438\u043c\u0435\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u043e\u0432<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"php\">#!\/usr\/bin\/env php &lt;?php  $socket = stream_socket_server(&quot;tcp:\/\/0.0.0.0:8000&quot;, $errno, $errstr);  if (!$socket) {     die(&quot;$errstr ($errno)\\n&quot;); }  $connects = array(); while (true) {     \/\/\u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u043f\u0440\u043e\u0441\u043b\u0443\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0441\u043e\u043a\u0435\u0442\u043e\u0432:     $read = $connects;     $read []= $socket;     $write = $except = null;      if (!stream_select($read, $write, $except, null)) {\/\/\u043e\u0436\u0438\u0434\u0430\u0435\u043c \u0441\u043e\u043a\u0435\u0442\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f (\u0431\u0435\u0437 \u0442\u0430\u0439\u043c\u0430\u0443\u0442\u0430)         break;     }      if (in_array($socket, $read)) {\/\/\u0435\u0441\u0442\u044c \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435         \/\/\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u043c \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c \u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u0435:         if (($connect = stream_socket_accept($socket, -1)) && $info = handshake($connect)) {             $connects[] = $connect;\/\/\u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438             onOpen($connect, $info);\/\/\u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439         }         $connects[] = $connect;\/\/\u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438         unset($read[ array_search($socket, $read) ]);     }      foreach($read as $connect) {\/\/\u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u0432\u0441\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f         $data = fread($connect, 100000);          if (!$data) { \/\/\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0431\u044b\u043b\u043e \u0437\u0430\u043a\u0440\u044b\u0442\u043e             fclose($connect);             unset($connects[ array_search($connect, $connects) ]);             onClose($connect);\/\/\u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439             continue;         }          onMessage($connect, $data);\/\/\u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439     } }  fclose($server);  function handshake($connect) {     $info = array();      $line = fgets($connect);     $header = explode(' ', $line);     $info['method'] = $header[0];     $info['uri'] = $header[1];      \/\/\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u0438\u0437 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f     while ($line = rtrim(fgets($connect))) {         if (preg_match('\/\\A(\\S+): (.*)\\z\/', $line, $matches)) {             $info[$matches[1]] = $matches[2];         } else {             break;         }     }      $address = explode(':', stream_socket_get_name($connect, true)); \/\/\u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0430\u0434\u0440\u0435\u0441 \u043a\u043b\u0438\u0435\u043d\u0442\u0430     $info['ip'] = $address[0];     $info['port'] = $address[1];      if (empty($info['Sec-WebSocket-Key'])) {         return false;     }      \/\/\u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u0430     $SecWebSocketAccept = base64_encode(pack('H*', sha1($info['Sec-WebSocket-Key'] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));     $upgrade = &quot;HTTP\/1.1 101 Web Socket Protocol Handshake\\r\\n&quot; .         &quot;Upgrade: websocket\\r\\n&quot; .         &quot;Connection: Upgrade\\r\\n&quot; .         &quot;Sec-WebSocket-Accept:$SecWebSocketAccept\\r\\n\\r\\n&quot;;     fwrite($connect, $upgrade);      return $info; }  function encode($payload, $type = 'text', $masked = false) {     $frameHead = array();     $payloadLength = strlen($payload);      switch ($type) {         case 'text':             \/\/ first byte indicates FIN, Text-Frame (10000001):             $frameHead[0] = 129;             break;          case 'close':             \/\/ first byte indicates FIN, Close Frame(10001000):             $frameHead[0] = 136;             break;          case 'ping':             \/\/ first byte indicates FIN, Ping frame (10001001):             $frameHead[0] = 137;             break;          case 'pong':             \/\/ first byte indicates FIN, Pong frame (10001010):             $frameHead[0] = 138;             break;     }      \/\/ set mask and payload length (using 1, 3 or 9 bytes)     if ($payloadLength &gt; 65535) {         $payloadLengthBin = str_split(sprintf('%064b', $payloadLength), 8);         $frameHead[1] = ($masked === true) ? 255 : 127;         for ($i = 0; $i &lt; 8; $i++) {             $frameHead[$i + 2] = bindec($payloadLengthBin[$i]);         }         \/\/ most significant bit MUST be 0         if ($frameHead[2] &gt; 127) {             return array('type' =&gt; '', 'payload' =&gt; '', 'error' =&gt; 'frame too large (1004)');         }     } elseif ($payloadLength &gt; 125) {         $payloadLengthBin = str_split(sprintf('%016b', $payloadLength), 8);         $frameHead[1] = ($masked === true) ? 254 : 126;         $frameHead[2] = bindec($payloadLengthBin[0]);         $frameHead[3] = bindec($payloadLengthBin[1]);     } else {         $frameHead[1] = ($masked === true) ? $payloadLength + 128 : $payloadLength;     }      \/\/ convert frame-head to string:     foreach (array_keys($frameHead) as $i) {         $frameHead[$i] = chr($frameHead[$i]);     }     if ($masked === true) {         \/\/ generate a random mask:         $mask = array();         for ($i = 0; $i &lt; 4; $i++) {             $mask[$i] = chr(rand(0, 255));         }          $frameHead = array_merge($frameHead, $mask);     }     $frame = implode('', $frameHead);      \/\/ append payload to frame:     for ($i = 0; $i &lt; $payloadLength; $i++) {         $frame .= ($masked === true) ? $payload[$i] ^ $mask[$i % 4] : $payload[$i];     }      return $frame; }  function decode($data) {     $unmaskedPayload = '';     $decodedData = array();      \/\/ estimate frame type:     $firstByteBinary = sprintf('%08b', ord($data[0]));     $secondByteBinary = sprintf('%08b', ord($data[1]));     $opcode = bindec(substr($firstByteBinary, 4, 4));     $isMasked = ($secondByteBinary[0] == '1') ? true : false;     $payloadLength = ord($data[1]) & 127;      \/\/ unmasked frame is received:     if (!$isMasked) {         return array('type' =&gt; '', 'payload' =&gt; '', 'error' =&gt; 'protocol error (1002)');     }      switch ($opcode) {         \/\/ text frame:         case 1:             $decodedData['type'] = 'text';             break;          case 2:             $decodedData['type'] = 'binary';             break;          \/\/ connection close frame:         case 8:             $decodedData['type'] = 'close';             break;          \/\/ ping frame:         case 9:             $decodedData['type'] = 'ping';             break;          \/\/ pong frame:         case 10:             $decodedData['type'] = 'pong';             break;          default:             return array('type' =&gt; '', 'payload' =&gt; '', 'error' =&gt; 'unknown opcode (1003)');     }      if ($payloadLength === 126) {         $mask = substr($data, 4, 4);         $payloadOffset = 8;         $dataLength = bindec(sprintf('%08b', ord($data[2])) . sprintf('%08b', ord($data[3]))) + $payloadOffset;     } elseif ($payloadLength === 127) {         $mask = substr($data, 10, 4);         $payloadOffset = 14;         $tmp = '';         for ($i = 0; $i &lt; 8; $i++) {             $tmp .= sprintf('%08b', ord($data[$i + 2]));         }         $dataLength = bindec($tmp) + $payloadOffset;         unset($tmp);     } else {         $mask = substr($data, 2, 4);         $payloadOffset = 6;         $dataLength = $payloadLength + $payloadOffset;     }      \/**      * We have to check for large frames here. socket_recv cuts at 1024 bytes      * so if websocket-frame is &gt; 1024 bytes we have to wait until whole      * data is transferd.      *\/     if (strlen($data) &lt; $dataLength) {         return false;     }      if ($isMasked) {         for ($i = $payloadOffset; $i &lt; $dataLength; $i++) {             $j = $i - $payloadOffset;             if (isset($data[$i])) {                 $unmaskedPayload .= $data[$i] ^ $mask[$j % 4];             }         }         $decodedData['payload'] = $unmaskedPayload;     } else {         $payloadOffset = $payloadOffset - 4;         $decodedData['payload'] = substr($data, $payloadOffset);     }      return $decodedData; }  \/\/\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438:  function onOpen($connect, $info) {     echo &quot;open\\n&quot;;     fwrite($connect, encode('\u041f\u0440\u0438\u0432\u0435\u0442')); }  function onClose($connect) {     echo &quot;close\\n&quot;; }  function onMessage($connect, $data) {     echo decode($data)['payload'] . &quot;\\n&quot;; } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0412 \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043c\u043e\u0436\u043d\u043e \u043c\u0435\u043d\u044f\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 onOpen, onClose \u0438 onMessage \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430.<\/p>\n<p>  \u041f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0446\u0435\u043b\u0438 \u0434\u043e\u0441\u0442\u0438\u0433\u043d\u0443\u0442\u044b.<br \/>  \u0415\u0441\u043b\u0438 \u044d\u0442\u043e\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0432\u0430\u043c \u043f\u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u043c, \u0442\u043e \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043e\u043f\u0438\u0448\u0443 \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 (\u043e\u0434\u0438\u043d \u043c\u0430\u0441\u0442\u0435\u0440 \u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432), \u043c\u0435\u0436\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043d\u043e\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435, \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e \u0441 \u0432\u0430\u0448\u0438\u043c \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u043c \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 yii.<\/p>\n<p>  <a href=\"http:\/\/sharoid.ru\/chat.html\">\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0447\u0430\u0442 \u0441 \u0432\u044b\u0448\u0435\u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u043c\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438<\/a><\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041a\u043e\u0434 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u0447\u0430\u0442\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"php\">#!\/usr\/bin\/env php &lt;?php  class WebsocketServer {     public function __construct($config) {         $this-&gt;config = $config;     }      public function start() {         \/\/\u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 \u0441\u043e\u043a\u0435\u0442         $server = stream_socket_server(&quot;tcp:\/\/{$this-&gt;config['host']}:{$this-&gt;config['port']}&quot;, $errorNumber, $errorString);          if (!$server) {             die(&quot;error: stream_socket_server: $errorString ($errorNumber)\\r\\n&quot;);         }          list($pid, $master, $workers) = $this-&gt;spawnWorkers();\/\/\u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b          if ($pid) {\/\/\u043c\u0430\u0441\u0442\u0435\u0440             fclose($server);\/\/\u043c\u0430\u0441\u0442\u0435\u0440 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0441\u043e\u043a\u0435\u0442\u0435             $WebsocketMaster = new WebsocketMaster($workers);\/\/\u043c\u0430\u0441\u0442\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u0441\u044b\u043b\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043c\u0435\u0436\u0434\u0443 \u0432\u043e\u0440\u043a\u0435\u0440\u0430\u043c\u0438             $WebsocketMaster-&gt;start();         } else {\/\/\u0432\u043e\u0440\u043a\u0435\u0440             $WebsocketHandler = new WebsocketHandler($server, $master);             $WebsocketHandler-&gt;start();         }     }      protected function spawnWorkers() {         $master = null;         $workers = array();         $i = 0;         while ($i &lt; $this-&gt;config['workers']) {             $i++;             \/\/\u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043f\u0430\u0440\u043d\u044b\u0435 \u0441\u043e\u043a\u0435\u0442\u044b, \u0447\u0435\u0440\u0435\u0437 \u043d\u0438\u0445 \u0431\u0443\u0434\u0443\u0442 \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043c\u0430\u0441\u0442\u0435\u0440 \u0438 \u0432\u043e\u0440\u043a\u0435\u0440             $pair = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);              $pid = pcntl_fork();\/\/\u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0444\u043e\u0440\u043a             if ($pid == -1) {                 die(&quot;error: pcntl_fork\\r\\n&quot;);             } elseif ($pid) { \/\/\u043c\u0430\u0441\u0442\u0435\u0440                 fclose($pair[0]);                 $workers[$pid] = $pair[1];\/\/\u043e\u0434\u0438\u043d \u0438\u0437 \u043f\u0430\u0440\u044b \u0431\u0443\u0434\u0435\u0442 \u0432 \u043c\u0430\u0441\u0442\u0435\u0440\u0435             } else { \/\/\u0432\u043e\u0440\u043a\u0435\u0440                 fclose($pair[1]);                 $master = $pair[0];\/\/\u0432\u0442\u043e\u0440\u043e\u0439 \u0432 \u0432\u043e\u0440\u043a\u0435\u0440\u0435                 break;             }         }          return array($pid, $master, $workers);     } }  class WebsocketMaster {     protected $workers = array();     protected $clients = array();      public function __construct($workers) {         $this-&gt;clients = $this-&gt;workers = $workers;     }      public function start() {         while (true) {             \/\/\u043f\u043e\u0434\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u0432\u0441\u0435\u0445 \u0441\u043e\u043a\u0435\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c             $read = $this-&gt;clients;             \/\/$read[] = $service;              stream_select($read, $write, $except, null);\/\/\u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u0441\u043e\u043a\u0435\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c              if ($read) {\/\/\u043f\u0440\u0438\u0448\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432                 foreach ($read as $client) {                     $data = fread($client, 100000);                      if (!$data) { \/\/\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0431\u044b\u043b\u043e \u0437\u0430\u043a\u0440\u044b\u0442\u043e                         unset($this-&gt;clients[intval($client)]);                         @fclose($client);                         continue;                     }                      foreach ($this-&gt;workers as $worker) {\/\/\u043f\u0435\u0440\u0435\u0441\u044b\u043b\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u043e \u0432\u0441\u0435 \u0432\u043e\u0440\u043a\u0435\u0440\u044b                         if ($worker !== $client) {                             fwrite($worker, $data);                         }                     }                 }             }         }     } }  abstract class WebsocketWorker {     protected $clients = array();     protected $server;     protected $master;     protected $pid;      public function __construct($server, $master) {         $this-&gt;server = $server;         $this-&gt;master = $master;         $this-&gt;pid = posix_getpid();     }      public function start() {         while (true) {             \/\/\u043f\u043e\u0434\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u0432\u0441\u0435\u0445 \u0441\u043e\u043a\u0435\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c             $read = $this-&gt;clients;             $read[] = $this-&gt;server;             $read[] = $this-&gt;master;              stream_select($read, $write, $except, null);\/\/\u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u0441\u043e\u043a\u0435\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c              if (in_array($this-&gt;server, $read)) { \/\/\u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 \u0441\u043e\u043a\u0435\u0442 \u043f\u0440\u0438\u0448\u0451\u043b \u0437\u0430\u043f\u0440\u043e\u0441 \u043e\u0442 \u043d\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430                 \/\/\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u0441\u044f \u043a \u043d\u0435\u043c\u0443 \u0438 \u0434\u0435\u043b\u0430\u0435\u043c \u0440\u0443\u043a\u043e\u043f\u043e\u0436\u0430\u0442\u0438\u0435, \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u0430                 if (($client = stream_socket_accept($this-&gt;server, -1)) && $info = $this-&gt;handshake($client)) {                     $this-&gt;clients[intval($client)] = $client;                     $this-&gt;onOpen($client, $info);\/\/\u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439                 }                  \/\/\u0443\u0434\u0430\u043b\u044f\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u043d\u044b\u0439 \u0441\u043e\u043a\u0435\u0442 \u0438\u0437 \u043c\u0430\u0441\u0441\u0438\u0432\u0430, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u044d\u0442\u043e\u043c \u0446\u0438\u043a\u043b\u0435 \u0435\u0449\u0451 \u0440\u0430\u0437                 unset($read[array_search($this-&gt;server, $read)]);             }              if (in_array($this-&gt;master, $read)) { \/\/\u043f\u0440\u0438\u0448\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 \u043c\u0430\u0441\u0442\u0435\u0440\u0430                 $data = fread($this-&gt;master, 100000);                  $this-&gt;onSend($data);\/\/\u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439                  \/\/\u0443\u0434\u0430\u043b\u044f\u0435\u043c \u043c\u0430\u0441\u0442\u0435\u0440\u0430 \u0438\u0437 \u043c\u0430\u0441\u0441\u0438\u0432\u0430, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u044d\u0442\u043e\u043c \u0446\u0438\u043a\u043b\u0435 \u0435\u0449\u0451 \u0440\u0430\u0437                 unset($read[array_search($this-&gt;master, $read)]);             }              if ($read) {\/\/\u043f\u0440\u0438\u0448\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432                 foreach ($read as $client) {                     $data = fread($client, 100000);                      if (!$data) { \/\/\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0431\u044b\u043b\u043e \u0437\u0430\u043a\u0440\u044b\u0442\u043e                         unset($this-&gt;clients[intval($client)]);                         @fclose($client);                         $this-&gt;onClose($client);\/\/\u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439                         continue;                     }                      $this-&gt;onMessage($client, $data);\/\/\u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439                 }             }          }     }      protected function handshake($client) {         $info = array();          $line = fgets($client);          if (!$line) {             return false;         }          $header = explode(' ', $line);         $info['method'] = $header[0];         $info['uri'] = $header[1];          \/\/\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0437\u0430\u0433\u0430\u043b\u043e\u0432\u043a\u0438 \u0438\u0437 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f         while ($line = rtrim(fgets($client))) {             if (preg_match('\/\\A(\\S+): (.*)\\z\/', $line, $matches)) {                 $info[$matches[1]] = $matches[2];             } else {                 break;             }         }          $address = explode(':', stream_socket_get_name($client, true)); \/\/\u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0430\u0434\u0440\u0435\u0441 \u043a\u043b\u0438\u0435\u043d\u0442\u0430         $info['ip'] = $address[0];         $info['port'] = $address[1];          if (empty($info['Sec-WebSocket-Key'])) {             return false;         }          \/\/\u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u0430         $SecWebSocketAccept = base64_encode(pack('H*', sha1($info['Sec-WebSocket-Key'] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));         $upgrade = &quot;HTTP\/1.1 101 Web Socket Protocol Handshake\\r\\n&quot; .             &quot;Upgrade: websocket\\r\\n&quot; .             &quot;Connection: Upgrade\\r\\n&quot; .             &quot;Sec-WebSocket-Accept:$SecWebSocketAccept\\r\\n\\r\\n&quot;;         fwrite($client, $upgrade);          return $info;     }      protected function encode($payload, $type = 'text', $masked = false)     {         $frameHead = array();         $payloadLength = strlen($payload);          switch ($type) {             case 'text':                 \/\/ first byte indicates FIN, Text-Frame (10000001):                 $frameHead[0] = 129;                 break;              case 'close':                 \/\/ first byte indicates FIN, Close Frame(10001000):                 $frameHead[0] = 136;                 break;              case 'ping':                 \/\/ first byte indicates FIN, Ping frame (10001001):                 $frameHead[0] = 137;                 break;              case 'pong':                 \/\/ first byte indicates FIN, Pong frame (10001010):                 $frameHead[0] = 138;                 break;         }          \/\/ set mask and payload length (using 1, 3 or 9 bytes)         if ($payloadLength &gt; 65535) {             $payloadLengthBin = str_split(sprintf('%064b', $payloadLength), 8);             $frameHead[1] = ($masked === true) ? 255 : 127;             for ($i = 0; $i &lt; 8; $i++) {                 $frameHead[$i + 2] = bindec($payloadLengthBin[$i]);             }             \/\/ most significant bit MUST be 0             if ($frameHead[2] &gt; 127) {                 return array('type' =&gt; '', 'payload' =&gt; '', 'error' =&gt; 'frame too large (1004)');             }         } elseif ($payloadLength &gt; 125) {             $payloadLengthBin = str_split(sprintf('%016b', $payloadLength), 8);             $frameHead[1] = ($masked === true) ? 254 : 126;             $frameHead[2] = bindec($payloadLengthBin[0]);             $frameHead[3] = bindec($payloadLengthBin[1]);         } else {             $frameHead[1] = ($masked === true) ? $payloadLength + 128 : $payloadLength;         }          \/\/ convert frame-head to string:         foreach (array_keys($frameHead) as $i) {             $frameHead[$i] = chr($frameHead[$i]);         }         if ($masked === true) {             \/\/ generate a random mask:             $mask = array();             for ($i = 0; $i &lt; 4; $i++) {                 $mask[$i] = chr(rand(0, 255));             }              $frameHead = array_merge($frameHead, $mask);         }         $frame = implode('', $frameHead);          \/\/ append payload to frame:         for ($i = 0; $i &lt; $payloadLength; $i++) {             $frame .= ($masked === true) ? $payload[$i] ^ $mask[$i % 4] : $payload[$i];         }          return $frame;     }      protected function decode($data)     {         $unmaskedPayload = '';         $decodedData = array();          \/\/ estimate frame type:         $firstByteBinary = sprintf('%08b', ord($data[0]));         $secondByteBinary = sprintf('%08b', ord($data[1]));         $opcode = bindec(substr($firstByteBinary, 4, 4));         $isMasked = ($secondByteBinary[0] == '1') ? true : false;         $payloadLength = ord($data[1]) & 127;          \/\/ unmasked frame is received:         if (!$isMasked) {             return array('type' =&gt; '', 'payload' =&gt; '', 'error' =&gt; 'protocol error (1002)');         }          switch ($opcode) {             \/\/ text frame:             case 1:                 $decodedData['type'] = 'text';                 break;              case 2:                 $decodedData['type'] = 'binary';                 break;              \/\/ connection close frame:             case 8:                 $decodedData['type'] = 'close';                 break;              \/\/ ping frame:             case 9:                 $decodedData['type'] = 'ping';                 break;              \/\/ pong frame:             case 10:                 $decodedData['type'] = 'pong';                 break;              default:                 return array('type' =&gt; '', 'payload' =&gt; '', 'error' =&gt; 'unknown opcode (1003)');         }          if ($payloadLength === 126) {             $mask = substr($data, 4, 4);             $payloadOffset = 8;             $dataLength = bindec(sprintf('%08b', ord($data[2])) . sprintf('%08b', ord($data[3]))) + $payloadOffset;         } elseif ($payloadLength === 127) {             $mask = substr($data, 10, 4);             $payloadOffset = 14;             $tmp = '';             for ($i = 0; $i &lt; 8; $i++) {                 $tmp .= sprintf('%08b', ord($data[$i + 2]));             }             $dataLength = bindec($tmp) + $payloadOffset;             unset($tmp);         } else {             $mask = substr($data, 2, 4);             $payloadOffset = 6;             $dataLength = $payloadLength + $payloadOffset;         }          \/**          * We have to check for large frames here. socket_recv cuts at 1024 bytes          * so if websocket-frame is &gt; 1024 bytes we have to wait until whole          * data is transferd.          *\/         if (strlen($data) &lt; $dataLength) {             return false;         }          if ($isMasked) {             for ($i = $payloadOffset; $i &lt; $dataLength; $i++) {                 $j = $i - $payloadOffset;                 if (isset($data[$i])) {                     $unmaskedPayload .= $data[$i] ^ $mask[$j % 4];                 }             }             $decodedData['payload'] = $unmaskedPayload;         } else {             $payloadOffset = $payloadOffset - 4;             $decodedData['payload'] = substr($data, $payloadOffset);         }          return $decodedData;     }      abstract protected function onOpen($client, $info);      abstract protected function onClose($client);      abstract protected function onMessage($client, $data);      abstract protected function onSend($data);      abstract protected function send($data); }  \/\/\u043f\u0440\u0438\u043c\u0435\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0447\u0430\u0442\u0430 class WebsocketHandler extends WebsocketWorker {     protected function onOpen($client, $info) {\/\/\u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0438 \u0441 \u043d\u043e\u0432\u044b\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c      }      protected function onClose($client) {\/\/\u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c      }      protected function onMessage($client, $data) {\/\/\u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430         $data = $this-&gt;decode($data);         \/\/var_export($data);         \/\/\u0448\u043b\u0435\u043c \u0432\u0441\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u0438\u0448\u0435\u0442 \u043e\u0434\u0438\u043d \u0438\u0437 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432         $message = '\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c #' . intval($client) . ' (' . $this-&gt;pid . '): ' . $data['payload'];         $this-&gt;send($message);          $this-&gt;sendHelper($message);     }      protected function onSend($data) {\/\/\u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442 \u043c\u0430\u0441\u0442\u0435\u0440\u0430         $this-&gt;sendHelper($data);     }      protected function send($message) {\/\/\u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043d\u0430 \u043c\u0430\u0441\u0442\u0435\u0440, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \u0440\u0430\u0437\u043e\u0441\u043b\u0430\u043b \u0435\u0433\u043e \u043d\u0430 \u0432\u0441\u0435 \u0432\u043e\u0440\u043a\u0435\u0440\u044b         @fwrite($this-&gt;master, $message);     }      private function sendHelper($data) {         $data = $this-&gt;encode($data);         foreach ($this-&gt;clients as $client) {             @fwrite($client, $data);         }     } }  $config = array(     'host' =&gt; '0.0.0.0',     'port' =&gt; 8000,     'workers' =&gt; 16, );  $WebsocketServer = new WebsocketServer($config); $WebsocketServer-&gt;start(); <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<div class=\"clear\"><\/div>\n<\/p><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"http:\/\/habrahabr.ru\/post\/209864\/\"> http:\/\/habrahabr.ru\/post\/209864\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"content html_format\"> \t\t\t\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u0437\u0430\u0434 \u044f \u0432\u044b\u0431\u0438\u0440\u0430\u043b \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u0430\u043c\u0438. \u041d\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u0440\u0430\u0445 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430 \u044f \u043d\u0430\u0442\u044b\u043a\u0430\u043b\u0441\u044f \u043d\u0430 \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u043e \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 node.js \u0441 yii, \u0430 \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u043e \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442\u0430\u0445 \u043d\u0430 \u0445\u0430\u0431\u0440\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u043b\u0438\u0441\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f\u043c\u0438 \u043a \u0442\u043e\u043c\u0443, \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c phpdaemon.<\/p>\n<p>  \u042f \u0438\u0437\u0443\u0447\u0430\u043b \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 <a href=\"http:\/\/daemon.io\/\">phpdaemon<\/a> \u0438 <a href=\"http:\/\/socketo.me\/\">ratchet<\/a>, \u043e\u043d\u0438 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043c\u043e\u043d\u0441\u0442\u0440\u0443\u043e\u0437\u043d\u044b (\u043f\u0440\u0438\u0447\u0451\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f ratchet \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u043d\u043e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"http:\/\/wamp.ws\/\">wamp<\/a>). \u041c\u043d\u0435 \u043d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u0431\u044b\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0434\u043b\u044f \u0447\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u0438\u0445 \u043c\u043e\u043d\u0441\u0442\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u0434\u0440\u0443\u0433\u0438\u0445 \u043c\u043e\u043d\u0441\u0442\u0440\u043e\u0432. \u041f\u043e\u0447\u0438\u0442\u0430\u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u044d\u0442\u0438\u0445, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u0440\u0443\u0433\u0438\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a, \u044f \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0441\u044f \u043a\u0430\u043a \u0432\u0441\u0451 \u0443\u0441\u0442\u0440\u043e\u0435\u043d\u043e \u0438 \u043c\u043d\u0435 \u0437\u0430\u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0432\u0435\u0431\u0441\u043e\u043a\u0435\u0442-\u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 php \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e. \u042d\u0442\u043e \u043f\u043e\u043c\u043e\u0433\u043b\u043e \u043c\u043d\u0435 \u0437\u0430\u043a\u0440\u0435\u043f\u0438\u0442\u044c \u0438\u0437\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0438 \u043d\u0430\u0442\u043a\u043d\u0443\u0442\u044c\u0441\u044f \u043d\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0435 \u043a\u0430\u043c\u043d\u0438, \u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u044f \u043d\u0435 \u0438\u043c\u0435\u043b \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f.<\/p>\n<p>  \u0422\u0430\u043a \u044f \u0440\u0435\u0448\u0438\u043b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u0434\u043b\u044f \u043c\u0435\u043d\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0441 \u043d\u0443\u043b\u044f.  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-209864","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/209864","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=209864"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/209864\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=209864"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=209864"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=209864"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}