Example #1
0
 function server_loop()
 {
     while (true) {
         $read_fds = $this->fds;
         $write = $exp = null;
         if (stream_select($read_fds, $write, $exp, null)) {
             foreach ($read_fds as $socket) {
                 $socket_id = (int) $socket;
                 if ($socket_id == $this->server_socket_id) {
                     if ($client_socket_id = parent::accept()) {
                         $this->fds[$client_socket_id] = $this->client_sock[$client_socket_id];
                         $this->protocol->onConnect($this, $client_socket_id, 0);
                     }
                 } else {
                     $data = Stream::read($socket, $this->buffer_size);
                     if ($data !== false) {
                         $this->protocol->onReceive($this, $socket_id, 0, $data);
                     } else {
                         $this->close($socket_id);
                     }
                 }
             }
         }
     }
 }
Example #2
0
 /**
  * 向任意 worker 进程或者 task 进程发送消息
  *
  * 和 swoole 不同的是, 它支持服务器集群下向任意集群去投递数据
  *
  * @param     $data
  * @param int $workerId
  * @param int $serverId
  * @return bool
  */
 public function sendMessage($data, $workerId, $serverId = -1)
 {
     if ($serverId === -1) {
         return $this->server->sendMessage($data, $workerId);
     } else {
         $client = Clusters\Client::getClient($serverId, $workerId, true);
         if (!$client) {
             return false;
         }
         return $client->sendData('msg', $data, 'Task');
     }
 }
Example #3
0
 public function onReceive($server, $fd, $fromId, $data)
 {
     /**
      * @var \Swoole\Server $server
      */
     $tmp = @msgpack_unpack($data);
     if ($tmp && is_object($tmp)) {
         $data = $tmp;
         unset($tmp);
         if ($data instanceof \stdClass) {
             if ($data->bind) {
                 # 绑定进程ID
                 $server->bind($fd, $data->id);
                 return;
             }
             if ($key = \MyQEE\Server\Register\Client::$host->key) {
                 # 需要解密
                 $data = \MyQEE\Server\RPC\Server::decryption($data, $key);
                 # 解密失败
                 if (!$data) {
                     return;
                 }
             }
             $eof = \MyQEE\Server\RPC\Server::$EOF;
             switch ($data->type) {
                 case 'task':
                 case 'taskWait':
                     $rs = Server::$workerTask->onTask($server, $data->id, $data->wid, $data->data, $data->sid);
                     if ($rs !== null || $data->type === 'taskWait') {
                         # 执行 Finish
                         $rsData = new \stdClass();
                         $rsData->id = $data->id;
                         $rsData->data = $rs;
                         $rsData->wname = $data->wname;
                         if ($key) {
                             # 加密数据
                             $rsData = \MyQEE\Server\RPC\Server::encrypt($rsData, $key) . $eof;
                         } else {
                             # 格式化数据
                             $rsData = msgpack_pack($rsData) . $eof;
                         }
                         $server->send($fd, $rsData, $fromId);
                     }
                     break;
             }
         }
     } else {
         Server::$instance->warn("task server get error msgpack data length: " . strlen($data));
         Server::$instance->debug($data);
         $this->server->close($fd);
     }
 }
Example #4
0
 public function start($dryRun = false)
 {
     $port = $this->choosePort();
     $this->sendCommand('status', $port, $error);
     // @codeCoverageIgnoreStart
     if (!$error) {
         $this->cliOutput('error', 'Service already started');
         return false;
     }
     // @codeCoverageIgnoreEnd
     $this->prepareServiceAwareComponents();
     $this->debug and $this->prepareDebugObservers();
     if (!$dryRun) {
         $this->initSwoole();
         $this->swoole->start();
     }
     return true;
 }
Example #5
0
 /**
  * 添加的自定义端口服务
  */
 protected function initSockets()
 {
     foreach (self::$config['sockets'] as $key => $setting) {
         if (in_array(strtolower($key), ['main', 'task', 'api', 'manager', 'registerserver'])) {
             self::warn("自定义端口服务关键字不允许是 Main, Task, API, Manager, RegisterServer, 已忽略配置, 请修改配置 sockets.{$key}.");
             continue;
         }
         foreach ((array) $setting['link'] as $st) {
             $opt = $this->parseSockUri($st);
             $listen = self::$server->listen($opt->host, $opt->port, $opt->type);
             if (!isset(self::$workers[$key])) {
                 self::$workers[$key] = $key;
             }
             # 设置参数
             $listen->set($this->getSockConf($key));
             # 设置回调
             $this->setListenCallback($key, $listen, $opt);
             $this->info("add listen: {$st}");
         }
     }
 }
Example #6
0
 /**
  * 向任意 worker 进程或者 task 进程发送消息
  *
  * 和 swoole 不同的是, 它支持服务器集群下向任意集群去投递数据
  *
  * @param        $data
  * @param int    $workerId
  * @param int    $serverId
  * @param string $serverGroup
  * @return bool
  */
 public function sendMessage($data, $workerId, $serverId = -1, $serverGroup = null)
 {
     if ($serverId < 0 || Server::$clustersType === 0 || $this->serverId === $serverId && null === $serverGroup) {
         # 没有指定服务器ID 或者 本服务器 或 非集群模式
         if ($this->name !== 'Main') {
             $obj = new \stdClass();
             $obj->_sys = true;
             $obj->name = $this->name;
             $obj->sid = Server::$serverId;
             $obj->data = $data;
             $data = $obj;
         }
         return $this->server->sendMessage($data, $workerId);
     } else {
         $client = Clusters\Client::getClient($serverGroup, $serverId, $workerId, true);
         if (!$client) {
             return false;
         }
         return $client->sendData('msg', $data, $this->name);
     }
 }
Example #7
0
 /**
 * 发送响应
 * @param $client_id
 * @param \Swoole\Response $response
 * @return unknown_type
 */
 function response($client_id, $response)
 {
     if (!isset($response->head['Date'])) {
         $response->head['Date'] = gmdate("D, d M Y H:i:s T");
     }
     if (!isset($response->head['Server'])) {
         $response->head['Server'] = self::SOFTWARE;
     }
     if (!isset($response->head['KeepAlive'])) {
         $response->head['KeepAlive'] = 'off';
     }
     if (!isset($response->head['Connection'])) {
         $response->head['Connection'] = 'close';
     }
     if (!isset($response->head['Content-Length'])) {
         $response->head['Content-Length'] = strlen($response->body);
     }
     $out = $response->head();
     $out .= $response->body;
     $this->server->send($client_id, $out);
 }
Example #8
0
 function __construct($host, $port, $timeout = 30)
 {
     parent::__construct($host, $port, $timeout = 30);
 }
Example #9
0
 /**
  * 收到信息
  *
  * @param \Swoole\Server $server
  * @param $fd
  * @param $fromId
  * @param $data
  */
 public function onReceive($server, $fd, $fromId, $data)
 {
     $data = trim($data);
     if ($data === '') {
         return;
     }
     /**
      * @var \Swoole\Server $server
      */
     $tmp = @msgpack_unpack($data);
     if (is_object($tmp) && $tmp instanceof \stdClass) {
         $rpc = static::$defaultRPC;
         if ($tmp->rpc) {
             if (preg_match('#^[\\\\0-9a-z]+$#i', $tmp->rpc)) {
                 $rpc = $tmp->rpc;
             }
         }
         /**
          * @var RPC $rpc
          */
         $key = $rpc::_getRpcKey();
         if ($key) {
             # 解密数据
             $tmp = self::decryption($tmp, $key, $rpc);
             if (false === $tmp) {
                 # 数据错误
                 $server->send($fd, '{"type":"close","code":0,"msg":"decryption fail."}' . static::$EOF);
                 $server->close($fd, $fromId);
                 \MyQEE\Server\Server::$instance->debug("register server decryption error, data: " . substr($data, 0, 256) . (strlen($data) > 256 ? '...' : ''));
                 return;
             }
         }
         $data = $tmp;
         unset($tmp);
         if ('bind' === $data->type) {
             if ($this->server->setting['dispatch_mode'] === 5 && is_int($data->id)) {
                 # 支持 worker 绑定
                 $this->server->bind($fd, $data->id);
             }
             return;
         }
         $data->rpc = $rpc;
         if (in_array($this->server->setting['dispatch_mode'], [1, 3]) && ($workerNum = $this->server->setting['worker_num']) > 1) {
             # 服务器是轮循或抢占模式, 每次请求的可能不是同一个 worker
             $workerId = $fd % $workerNum;
             if ($workerId !== $this->server->worker_id) {
                 # 发送给对应的进程去处理
                 $obj = new \stdClass();
                 $obj->type = 'call';
                 $obj->fd = $fd;
                 $obj->fromId = $fromId;
                 $obj->data = $data;
                 $this->sendMessage($data, $workerId);
                 return;
             }
         }
         # 执行RPC调用
         $this->call($fd, $fromId, $data);
     } else {
         \MyQEE\Server\Server::$instance->warn("rpc get error msgpack data: " . substr($data, 0, 256) . (strlen($data) > 256 ? '...' : ''));
         $this->server->close($fd, $fromId);
         return;
     }
 }
Example #10
0
 function daemonize()
 {
     $this->server->daemonize();
 }
Example #11
0
 function task($task, $dstWorkerId = -1, $callback = null)
 {
     $this->server->task($task, $dstWorkerId = -1, $callback);
 }
Example #12
0
 function setProtocol($protocol)
 {
     parent::setProtocol($protocol);
 }
Example #13
0
<?php

use Swoole\Server;
$serv = new Server("127.0.0.1", 9501);
$serv->on('receive', function (Server $serv, $fd, $from_id, $data) {
    echo "[#" . $serv->worker_id . "]\tClient[{$fd}]: {$data}\n";
    if ($serv->send($fd, "hello\n") == false) {
        echo "error\n";
    }
});
$serv->start();
Example #14
0
 function task($task, $dstWorkerId = -1)
 {
     $this->server->task($task, $dstWorkerId = -1);
 }