Esempio n. 1
0
 /**
  * 有消息时触发该方法
  * @param int $client_id 发消息的client_id
  * @param string $message 消息
  * @return void
  */
 public static function onMessage($client_id, $message)
 {
     $message = substr($message, 4);
     //解析传输的数据
     $cmd = new PbCmd();
     try {
         $cmd->parseFromString($message);
     } catch (Exception $ex) {
         return $ex->getMessage();
     }
     //接收参数
     $obj = $cmd->getObj();
     $method = $cmd->getMethod();
     $params = $cmd->getParams();
     //统计数据
     $class = substr($obj, 8);
     StatisticClient::tick($class, $method);
     try {
         //处理业务逻辑
         $instance = new $obj();
         $buffer = $instance->{$method}($params);
         StatisticClient::report($class, $method, 1, 0, 'successful');
     } catch (Exception $ex) {
         $pbResult = new PbResult();
         $pbResult->setCode($ex->getCode());
         $pbResult->setMsg($ex->getMessage());
         $buffer = $pbResult->SerializeToString();
         $total_length = 4 + strlen($buffer);
         $buffer = pack('N', $total_length) . $buffer;
         StatisticClient::report($class, $method, 0, $ex->getCode(), $ex->getMessage());
     }
     echo 'Login_Woker' . PHP_EOL;
     return Gateway::sendToCurrentClient($buffer);
 }
Esempio n. 2
0
 /**
  * 有消息时触发该方法
  * @param int $client_id 发消息的client_id
  * @param string $message 消息
  * @return void
  */
 public static function onMessage($client_id, $message)
 {
     $message_data = TextProtocol::decode($message);
     // **************如果没有$_SESSION['name']说明没有设置过用户名,进入设置用户名逻辑************
     if (empty($_SESSION['name'])) {
         $_SESSION['name'] = TextProtocol::decode($message);
         Gateway::sendToCurrentClient("chat room login success, your client_id is {$client_id}, name is {$_SESSION['name']}\r\nuse client_id:words send message to one user\r\nuse words send message to all\r\n");
         // 广播所有用户,xxx come
         return GateWay::sendToAll(TextProtocol::encode("{$_SESSION['name']}[{$client_id}] come"));
     }
     // ********* 进入聊天逻辑 ****************
     // 判断是否是私聊
     $explode_array = explode(':', $message, 2);
     // 私聊数据格式 client_id:xxxxx
     if (count($explode_array) > 1) {
         $to_client_id = (int) $explode_array[0];
         GateWay::sendToClient($client_id, TextProtocol::encode($_SESSION['name'] . "[{$client_id}] said said to [{$to_client_id}] :" . $explode_array[1]));
         return GateWay::sendToClient($to_client_id, TextProtocol::encode($_SESSION['name'] . "[{$client_id}] said to You :" . $explode_array[1]));
     }
     // 群聊
     return GateWay::sendToAll(TextProtocol::encode($_SESSION['name'] . "[{$client_id}] said :" . $message));
 }
Esempio n. 3
0
 /**
  * 此链接的用户没调用GateWay::notifyConnectionSuccess($uid);前(即没有得到验证),都触发onConnect
  * 已经调用GateWay::notifyConnectionSuccess($uid);的用户有消息时,则触发onMessage
  * @param string $message 一般是传递的账号密码等信息
  * @return void
  */
 public static function onConnect($message)
 {
     /*
      * 通过message验证用户,并获得uid。
      * 一般流程这里$message应该包含用户名 密码,然后根据用户名密码从数据库中获取uid
      * 这里只是根据时间戳生成uid,高并发下会有小概率uid冲突
      */
     $uid = self::checkUser($message);
     // 不合法踢掉
     if (!$uid) {
         // 踢掉
         return GateWay::kickCurrentUser(TextProtocol::encode('uid非法'));
     }
     $_SESSION['name'] = TextProtocol::decode($message);
     // [这步是必须的]合法,记录uid到gateway通信地址的映射
     GateWay::storeUid($uid);
     // [这步是必须的]发送数据包到address对应的gateway,确认connection成功
     GateWay::notifyConnectionSuccess($uid);
     Gateway::sendToCurrentUid("\nchart room login success, your uid is {$uid}, name is {$_SESSION['name']}\nuse uid:words send message to one user\nuse words send message to all\n");
     // 广播所有用户,xxx come
     GateWay::sendToAll(TextProtocol::encode("{$_SESSION['name']}[{$uid}] come"));
 }
Esempio n. 4
0
 /**
  * 有消息时
  * @param int $uid
  * @param string $message
  */
 public static function onMessage($uid, $message)
 {
     // $message len < 7 可能是ping包,断开连接的包等暂时忽略
     if (strlen($message) < 7) {
         return;
     }
     $message = WebSocket::decode($message);
     // 广播路线
     Gateway::sendToAll(WebSocket::encode(pack('CVVVC', 2, 1, 1, $uid, 0) . substr($message, 1)));
 }
Esempio n. 5
0
 /**
  * 处理请求
  * @see Man\Core.SocketWorker::dealProcess()
  */
 public function dealProcess($recv_buffer)
 {
     $pack = new GatewayProtocol($recv_buffer);
     Context::$client_ip = $pack->header['client_ip'];
     Context::$client_port = $pack->header['client_port'];
     Context::$local_ip = $pack->header['local_ip'];
     Context::$local_port = $pack->header['local_port'];
     Context::$socket_id = $pack->header['socket_id'];
     Context::$client_id = $pack->header['client_id'];
     $_SERVER = array('REMOTE_ADDR' => Context::$client_ip, 'REMOTE_PORT' => Context::$client_port, 'GATEWAY_ADDR' => Context::$local_ip, 'GATEWAY_PORT' => Context::$local_port, 'GATEWAY_CLIENT_ID' => Context::$client_id);
     if ($pack->ext_data != '') {
         $_SESSION = Context::sessionDecode($pack->ext_data);
     } else {
         $_SESSION = null;
     }
     // 备份一次$pack->ext_data,请求处理完毕后判断session是否和备份相等,不相等就更新session
     $session_str_copy = $pack->ext_data;
     $cmd = $pack->header['cmd'];
     $interface = isset(self::$interfaceMap[$cmd]) ? self::$interfaceMap[$cmd] : $cmd;
     StatisticClient::tick(__CLASS__, $interface);
     try {
         switch ($cmd) {
             case GatewayProtocol::CMD_ON_GATEWAY_CONNECTION:
                 Login::onGatewayConnect(Context::$client_id);
                 break;
             case GatewayProtocol::CMD_ON_MESSAGE:
                 Login::onMessage(Context::$client_id, $pack->body);
                 break;
             case GatewayProtocol::CMD_ON_CLOSE:
                 Login::onClose(Context::$client_id);
                 break;
         }
         StatisticClient::report(__CLASS__, $interface, 1, 0, '');
     } catch (\Exception $e) {
         $msg = 'client_id:' . Context::$client_id . "\tclient_ip:" . Context::$client_ip . "\n" . $e->__toString();
         StatisticClient::report(__CLASS__, $interface, 0, $e->getCode() > 0 ? $e->getCode() : 201, $msg);
     }
     $session_str_now = $_SESSION !== null ? Context::sessionEncode($_SESSION) : '';
     if ($session_str_copy != $session_str_now) {
         Gateway::updateSocketSession(Context::$socket_id, $session_str_now);
     }
     Context::clear();
 }
Esempio n. 6
0
 /**
  * websocket协议握手
  * @param string $message
  */
 public static function checkHandshake($message)
 {
     // WebSocket 握手阶段
     if (0 === strpos($message, 'GET')) {
         // 解析Sec-WebSocket-Key
         $Sec_WebSocket_Key = '';
         if (preg_match("/Sec-WebSocket-Key: *(.*?)\r\n/", $message, $match)) {
             $Sec_WebSocket_Key = $match[1];
         }
         $new_key = base64_encode(sha1($Sec_WebSocket_Key . "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true));
         // 握手返回的数据
         $new_message = "HTTP/1.1 101 Switching Protocols\r\n";
         $new_message .= "Upgrade: websocket\r\n";
         $new_message .= "Sec-WebSocket-Version: 13\r\n";
         $new_message .= "Connection: Upgrade\r\n";
         $new_message .= "Sec-WebSocket-Accept: " . $new_key . "\r\n\r\n";
         // 发送数据包到客户端 完成握手
         Gateway::sendToCurrentClient($new_message);
         return true;
     } elseif (trim($message) === '<policy-file-request/>') {
         $policy_xml = '<?xml version="1.0"?><cross-domain-policy><site-control permitted-cross-domain-policies="all"/><allow-access-from domain="*" to-ports="*"/></cross-domain-policy>' . "";
         Gateway::sendToCurrentClient($policy_xml);
         return true;
     }
     return false;
 }
Esempio n. 7
0
 /**
  * 有消息时
  * @param int $uid
  * @param string $message
  */
 public static function onMessage($uid, $message)
 {
     if (WebSocket::isClosePacket($message)) {
         Gateway::kickUid($uid, '');
         self::onClose($uid);
         return;
     }
     $message = WebSocket::decode($message);
     // debug
     echo "client:{$_SERVER['REMOTE_ADDR']}:{$_SERVER['REMOTE_PORT']} gateway:{$_SERVER['GATEWAY_ADDR']}:{$_SERVER['GATEWAY_PORT']} socketid:{$_SERVER['GATEWAY_SOCKET_ID']} uid:{$uid} onMessage:" . $message . "\n";
     $message_data = json_decode($message, true);
     if (!$message_data) {
         return;
     }
     switch ($message_data['type']) {
         // 用户登录 message格式: {type:login, name:xx} ,添加到用户,广播给所有用户xx进入聊天室
         case 'login':
             // 存储当前用户到用户列表
             self::addUserToList($uid, htmlspecialchars($message_data['name']));
             // 获取用户列表
             $user_list = self::getUserList();
             // 整理用户列表以便显示
             $all_users = array();
             if ($user_list) {
                 foreach ($user_list as $tmp_uid => $name) {
                     $all_users[] = array('uid' => $tmp_uid, 'name' => $name);
                 }
             }
             // 发送给当前用户 内容是用户列表 message: {type:user_list, user_list:xxxx}
             Gateway::sendToUid($uid, WebSocket::encode(json_encode(array('type' => 'user_list', 'user_list' => $all_users))));
             // 转播给所有用户,xx进入聊天室 message {type:login, uid:xx, name:xx}
             Gateway::sendToAll(WebSocket::encode(json_encode(array('type' => 'login', 'uid' => $uid, 'name' => htmlspecialchars($message_data['name']), 'time' => date('Y-m-d H:i:s')))));
             return;
             // 用户发言 message: {type:say, to_uid:xx, content:xx}
         // 用户发言 message: {type:say, to_uid:xx, content:xx}
         case 'say':
             // 私聊
             if ($message_data['to_uid'] != 'all') {
                 $new_message = array('type' => 'say', 'from_uid' => $uid, 'to_uid' => $message_data['to_uid'], 'content' => nl2br(htmlspecialchars($message_data['content'])), 'time' => date('Y-m-d :i:s'));
                 echo 'here';
                 return Gateway::sendToUid($message_data['to_uid'], WebSocket::encode(json_encode($new_message)));
             }
             // 向大家说
             $new_message = array('type' => 'say', 'from_uid' => $uid, 'to_uid' => 'all', 'content' => nl2br(htmlspecialchars($message_data['content'])), 'time' => date('Y-m-d :i:s'));
             return Gateway::sendToAll(WebSocket::encode(json_encode($new_message)));
     }
 }
 /**
  * 处理请求
  * @see Man\Core.SocketWorker::dealProcess()
  */
 public function dealProcess($recv_str)
 {
     $pack = new GatewayProtocol($recv_str);
     Context::$client_ip = $pack->header['client_ip'];
     Context::$client_port = $pack->header['client_port'];
     Context::$local_ip = $pack->header['local_ip'];
     Context::$local_port = $pack->header['local_port'];
     Context::$socket_id = $pack->header['socket_id'];
     Context::$uid = $pack->header['uid'];
     $_SERVER = array('REMOTE_ADDR' => Context::$client_ip, 'REMOTE_PORT' => Context::$client_port, 'GATEWAY_ADDR' => Context::$local_ip, 'GATEWAY_PORT' => Context::$local_port, 'GATEWAY_SOCKET_ID' => Context::$socket_id);
     if ($pack->ext_data != '') {
         $_SESSION = Context::sessionDecode($pack->ext_data);
     } else {
         $_SESSION = null;
     }
     // 备份一次$pack->ext_data,请求处理完毕后判断session是否和备份相等
     $session_str_copy = $pack->ext_data;
     $cmd = $pack->header['cmd'];
     StatisticClient::tick();
     $module = __CLASS__;
     $interface = isset(self::$interfaceMap[$cmd]) ? self::$interfaceMap[$cmd] : 'null';
     $success = 1;
     $code = 0;
     $msg = '';
     try {
         switch ($cmd) {
             case GatewayProtocol::CMD_ON_GATEWAY_CONNECTION:
                 call_user_func_array(array('Event', 'onGatewayConnect'), array());
                 break;
             case GatewayProtocol::CMD_ON_CONNECTION:
                 call_user_func_array(array('Event', 'onConnect'), array($pack->body));
                 break;
             case GatewayProtocol::CMD_ON_MESSAGE:
                 call_user_func_array(array('Event', 'onMessage'), array(Context::$uid, $pack->body));
                 break;
             case GatewayProtocol::CMD_ON_CLOSE:
                 call_user_func_array(array('Event', 'onClose'), array(Context::$uid));
                 break;
         }
     } catch (\Exception $e) {
         $success = 0;
         $code = $e->getCode() > 0 ? $e->getCode() : 500;
         $msg = 'uid:' . Context::$uid . "\tclient_ip:" . Context::$client_ip . "\n" . $e->__toString();
     }
     $session_str_now = $_SESSION !== null ? Context::sessionEncode($_SESSION) : '';
     if ($session_str_copy != $session_str_now) {
         Gateway::updateSocketSession(Context::$socket_id, $session_str_now);
     }
     Context::clear();
     StatisticClient::report($module, $interface, $success, $code, $msg);
 }