За последние 24 часа нас посетили 24219 программистов и 1641 робот. Сейчас ищут 873 программиста ...

Чат с блек-джеком и вёбсокетами

Тема в разделе "Прочие вопросы по PHP", создана пользователем Freakmeister, 16 апр 2015.

  1. Freakmeister

    Freakmeister Активный пользователь

    С нами с:
    20 дек 2009
    Сообщения:
    888
    Симпатии:
    5
    Может кто-нибудь подкинуть готовый проверенный вариант? Все решения, что я нашёл в гугле - косячат. У меня завёлся всего один чат - этот. Но он почему-то дропает соединение постоянно. А ещё я пока не разобрался как запустить его через консоль в фоновом режиме, чтоб я мог закрыть консоль-то...
     
  2. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    Re: Чат с вёбсокетами и рилтаймом

    амерсанд добавить в конце))) или через инит/системви запускать

    Добавлено спустя 1 минуту 18 секунд:
    Re: Чат с блек-джеком и вёбсокетами
    а и ноухап еще
     
  3. Freakmeister

    Freakmeister Активный пользователь

    С нами с:
    20 дек 2009
    Сообщения:
    888
    Симпатии:
    5
    Что-то вёбсокеты это какая-то прожорливая фигня по-моему. Пробую этот скрипт, у меня сервер уже два раза вешался от нагрузки на проц. Не проще ли будет сделать чатик с setInterval в JS на клиентской стороне? Чтоб сервер опрашивался всеми клиентами раз в секунду например.
     
  4. rodent90

    rodent90 Новичок

    С нами с:
    26 мар 2015
    Сообщения:
    533
    Симпатии:
    37
    О! Тогда это
    произайдет еще быстрее.
    WebSocket + еще и север сокет, что - то бешенство какое - то. И зачем это?
    Ведь браузер же может просто смотреть файлик и обновлять его, нахера еще и серв убивать сокетами?) когда сервер уже знает что пользователь онлайн и т.д.!?))
     
  5. Freakmeister

    Freakmeister Активный пользователь

    С нами с:
    20 дек 2009
    Сообщения:
    888
    Симпатии:
    5
    Там опять был скрипт кривой походу. Я сейчас взял за основу гугловский скрипт, он сервер не вешает. Мозг вынес, но завёл его. Вот готовый чат, можете пользовать, кому надо:

    server.php:
    Код (PHP):
    1. #!/php -q
    2. <?php  /*  >php -q server.php  */
    3.  
    4.  
    5. $master  = WebSocket("red-squadron.ru",9010);
    6. $sockets = array($master);
    7. $users   = array();
    8. $debug   = true;
    9.  
    10. while(true){
    11.   $changed = $sockets;
    12.   if (!isset($write)) {
    13.     $write = NULL;
    14.   }
    15.   if (!isset($except)) {
    16.     $except = NULL;
    17.   }
    18.   socket_select($changed,$write,$except,NULL);
    19.   foreach($changed as $socket){
    20.     if($socket==$master){
    21.       $client=socket_accept($master);
    22.       if($client<0){ console("socket_accept() failed"); continue; }
    23.       else{ connect($client); }
    24.     }
    25.     else{
    26.       $bytes = @socket_recv($socket,$buffer,2048,0);
    27.       if($bytes==0){ disconnect($socket); }
    28.       else{
    29.         $user = getuserbysocket($socket);
    30.         if(!$user->handshake){ dohandshake($user,$buffer); }
    31.         else{ process($user,$buffer); }
    32.       }
    33.     }
    34.   }
    35. }
    36.  
    37. //---------------------------------------------------------------
    38. function process($user,$msg){
    39.   global $users;
    40.   $action = unwrap($msg);
    41.   
    42.   switch($action){
    43.     case "PING" :
    44.       say("< ".$action);
    45.       send($user->socket,"PONG");
    46.     break;
    47.     default:
    48.       $action = json_decode($action);
    49.       if (($action->name) and ($action->message) and ($action->color)) {
    50.         $msg = '<span style="color:#'.$action->color.'">'.$action->name."</span>: ".$action->message;
    51.         say("< ".$action->name.": ".$action->message);
    52.         foreach ($users as $u) {
    53.           send($u->socket, $msg);
    54.         }
    55.       } else {
    56.         $msg = "Got unknown command.";
    57.         say("< ".$msg);
    58.         send($user->socket, $msg);
    59.       }
    60.     break;
    61.   }
    62. }
    63.  
    64. function send($client,$msg){
    65.   $msg = wrap($msg);
    66.   $sent = socket_write($client, $msg);
    67. }
    68.  
    69. function WebSocket($address,$port){
    70.   $master=socket_create(AF_INET, SOCK_STREAM, SOL_TCP)     or die("socket_create() failed");
    71.   socket_set_option($master, SOL_SOCKET, SO_REUSEADDR, 1)  or die("socket_option() failed");
    72.   socket_bind($master, $address, $port)                    or die("socket_bind() failed");
    73.   socket_listen($master,20)                                or die("socket_listen() failed");
    74.   echo "Server Started : ".date('Y-m-d H:i:s')."\n";
    75.   echo "Master socket  : ".$master."\n";
    76.   echo "Listening on   : ".$address." port ".$port."\n\n";
    77.   return $master;
    78. }
    79.  
    80. function connect($socket){
    81.   global $sockets,$users;
    82.   $user = new User();
    83.   $user->id = uniqid();
    84.   $user->socket = $socket;
    85.   array_push($users,$user);
    86.   array_push($sockets,$socket);
    87.   console($socket." CONNECTED!");
    88. }
    89.  
    90. function disconnect($socket){
    91.   global $sockets,$users;
    92.   $found=null;
    93.   $n=count($users);
    94.   for($i=0;$i<$n;$i++){
    95.     if($users[$i]->socket==$socket){ $found=$i; break; }
    96.   }
    97.   if(!is_null($found)){ array_splice($users,$found,1); }
    98.   $index = array_search($socket,$sockets);
    99.   socket_close($socket);
    100.   console($socket." DISCONNECTED!");
    101.   if($index>=0){ array_splice($sockets,$index,1); }
    102. }
    103.  
    104. function dohandshake($user,$buffer){
    105.   console("\nRequesting handshake...");
    106.   console($buffer);
    107.   list($resource,$host,$origin,$key) = getheaders($buffer);
    108.   console("Handshaking...");
    109.  
    110. $upgrade  = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
    111.             "Upgrade: WebSocket\r\n" .
    112.             "Connection: Upgrade\r\n" .
    113.             "Sec-WebSocket-Accept: ".base64_encode(sha1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true))."\r\n".
    114.             "\r\n";
    115.   socket_write($user->socket,$upgrade);
    116.  
    117.   $user->handshake=true;
    118.   console($upgrade);
    119.   console("Done handshaking...");
    120.   return true;
    121. }
    122.  
    123. function getheaders($req){
    124.   $r=$h=$o=$key1=$key2=$data=null; 
    125.   if(preg_match("/GET (.*) HTTP/"   ,$req,$match)){ $r=$match[1]; }
    126.   if(preg_match("/Host: (.*)\r\n/"  ,$req,$match)){ $h=$match[1]; }
    127.   if(preg_match("/Origin: (.*)\r\n/",$req,$match)){ $o=$match[1]; }
    128.   if(preg_match("/Sec-WebSocket-Key: (.*)\r\n/",$req,$match)){ $key1=$match[1]; }
    129.   //if(preg_match("/\r\n(.*?)\$/",$req,$match)){ $data=$match[1]; }
    130.   return array($r,$h,$o,$key1);
    131. }
    132.  
    133. function getuserbysocket($socket){
    134.   global $users;
    135.   $found=null;
    136.   foreach($users as $user){
    137.     if($user->socket==$socket){ $found=$user; break; }
    138.   }
    139.   return $found;
    140. }
    141.  
    142. function     say($msg=""){ echo $msg."\n"; }
    143. function    wrap($msg=""){
    144. $length=strlen($msg);
    145. $header=chr(0x81).chr($length);
    146. $msg=$header.$msg;
    147. return $msg;
    148. }
    149. function  unwrap($msg=""){
    150. {
    151. $firstMask=     bindec("10000000");
    152. $secondMask=    bindec("01000000");//im not doing anything with the rsvs since we arent negotiating extensions...
    153. $thirdMask=     bindec("00100000");
    154. $fourthMask=    bindec("00010000");
    155. $firstHalfMask= bindec("11110000");
    156. $secondHalfMask=bindec("00001111");
    157. $payload="";
    158. $firstHeader=ord(($msg[0]));
    159. $secondHeader=ord($msg[1]);
    160. $key=Array();
    161. $fin=(($firstHeader & $firstMask)?1:0);
    162. $rsv1=$rsv2=$rsv3=0;
    163. $opcode=$firstHeader & (~$firstHalfMask);//TODO: make the opcode do something. it extracts it but the program just assumes text;
    164. $masked=(($secondHeader & $firstMask) !=0);
    165. $length=$secondHeader & (~$firstMask);
    166. $index=2;
    167. if($length==126)
    168. {
    169. $length=ord($msg[$index])+ord($msg[$index+1]);
    170. $index+=2;
    171. }
    172. if($length==127)
    173. {
    174. $length=ord($msg[$index])+ord($msg[$index+1])+ord($msg[$index+2])+ord($msg[$index+3])+ord($msg[$index+4])+ord($msg[$index+5])+ord($msg[$index+6])+ord($msg[$index+7]);
    175. $index+=8;
    176. }
    177. if($masked)
    178. {
    179. for($x=0;$x<4;$x++)
    180. {
    181. $key[$x]=ord($msg[$index]);
    182. $index++;
    183. }
    184. }
    185. echo $length."\n";
    186. for($x=0;$x<$length;$x++)
    187. {
    188. $msgnum=ord($msg[$index]);
    189. $keynum=$key[$x % 4];
    190. $unmaskedKeynum=$msgnum $keynum;
    191. $payload.=chr($unmaskedKeynum);
    192. $index++;
    193. }
    194.  
    195. if($fin!=1)
    196. {
    197. return $payload.processMsg(substr($msg,$index));
    198. }
    199. return $payload;
    200. }
    201. }
    202. function console($msg=""){ global $debug; if($debug){ echo $msg."\n"; } }
    203.  
    204. class User{
    205.   var $id;
    206.   var $socket;
    207.   var $handshake;
    208. }
    209.  
    210. ?>
    index.php (клиент):
    Код (Text):
    1. <html>
    2. <head>
    3. <title>WebSocket</title>
    4.  
    5. <style>
    6.  html,body{font:normal 0.9em arial,helvetica;}
    7.  #log {width:440px; height:200px; border:1px solid #7F9DB9; overflow:auto;}
    8.  #msg {width:330px;}
    9. </style>
    10. <script>
    11.  
    12. var socket;
    13.  
    14. function init(){
    15.   var host = "ws://red-squadron.ru:9010/plugins/chat/server.php";
    16.   try{
    17.     socket = new WebSocket(host);
    18.     log('WebSocket - status '+socket.readyState);
    19.     socket.onopen    = function(msg){ log("Welcome - status "+this.readyState); };
    20.     socket.onmessage = function(msg){
    21.         if (msg.data != "PONG") {
    22.             log(msg.data);
    23.         }
    24.     };
    25.     socket.onclose   = function(msg){ log("Disconnected - status "+this.readyState); };
    26.   }
    27.   catch(ex){ log(ex); }
    28.   $("msg").focus();
    29. }
    30.  
    31. function send(){
    32. var txt,msg,namee,colorr;
    33.   txt = $("msg");
    34.   msg = txt.value;
    35.   if(!msg){ alert("Message can not be empty"); return; }
    36.   txt.value="";
    37.   txt.focus();
    38.  
    39.   namee =  $("name").value;
    40.   colorr =  $("color").value;
    41.  
    42.     try {
    43.         var msg = {
    44.             message: msg,
    45.             name: namee,
    46.             color: colorr
    47.         };
    48.         socket.send(JSON.stringify(msg));
    49.         //log('Sent: '+msg);
    50.     } catch(ex){ log(ex); }
    51. }
    52.  
    53. // Utilities
    54. function $(id){ return document.getElementById(id); }
    55. function log(msg){ $("log").innerHTML+="<br>"+msg; }
    56. function onkey(event){ if(event.keyCode==13){ send(); } }
    57. </script>
    58.  
    59. </head>
    60. <body onload="init()">
    61.  
    62. <?php
    63. $colors = array('007AFF','FF7000','FF7000','15E25F','CFC700','CFC700','CF1100','CF00BE','F00');
    64. $color = array_rand($colors);
    65. $color = $colors[$color];
    66. ?>
    67.  
    68.  <div id="log"></div>
    69.  <input id="msg" type="textbox" onkeypress="onkey(event)" disabled/>
    70.  <input type="hidden" name="name" id="name" maxlength="60" value="Test"  />
    71.  <input type="hidden" name="color" id="color" maxlength="6" value="<?php echo $color; ?>"  />
    72.  <button id="send-btn" onclick="send()" disabled>Send</button>
    73. </body>
    74. </html>
     
  6. Zuldek

    Zuldek Старожил

    С нами с:
    13 май 2014
    Сообщения:
    2.381
    Симпатии:
    344
    Адрес:
    Лондон, Тисовая улица, дом 4, чулан под лестницей
    Вот третий раз открываю и не буду. Ну чего мучить то себя, ставьте node c socket.io и наслаждайтесь готовым решением с серверным кодом в 40 строк.
     
  7. Freakmeister

    Freakmeister Активный пользователь

    С нами с:
    20 дек 2009
    Сообщения:
    888
    Симпатии:
    5
    Это кстати временное решение, я собираюсь переезжать на Node.js. Пока просто никак, надо много всего переделать и изучить саму ноду ещё. Решил вот пока прикрутить чат на скорую руку.
     
  8. Zuldek

    Zuldek Старожил

    С нами с:
    13 май 2014
    Сообщения:
    2.381
    Симпатии:
    344
    Адрес:
    Лондон, Тисовая улица, дом 4, чулан под лестницей
    Ну конкретно для этой простой задачи чего вам там надо изучать? 3 объекта и по 2 метода для них?
    Вот какой-то чатик писал в демонстрационных целях насколько помню:
    http://www.filedropper.com/chat_2
     
  9. Freakmeister

    Freakmeister Активный пользователь

    С нами с:
    20 дек 2009
    Сообщения:
    888
    Симпатии:
    5
    Ну так, мне это надо встроить в пхп-страницу пока.) Почему-то решил, что так будет проще.