美文网首页
swoole同时连接 tcp http WebSocket三端数

swoole同时连接 tcp http WebSocket三端数

作者: 骑着大象去上班 | 来源:发表于2019-10-21 17:51 被阅读0次

    服务器代码

    <?php
    
    use Swoole\WebSocket\Server;
    
    class Test
    {
        public $ws;
        public $redis;
    
        public function __construct()
        {
    
            Co::set(['enable_preemptive_scheduler' => 0]);
            $this->ws = new Server('0.0.0.0', 9501, SWOOLE_PROCESS, SWOOLE_SOCK_TCP);
            $Config = [
                'open_http_protocol' => true,
            ];
            $this->ws->set($Config);
            $this->ws->on('open', [$this, 'onOpen']);
            $this->ws->on('message', [$this, 'onMessage']);
            $this->ws->on('WorkerStart', [$this, 'onWorkerStart']);
            $this->ws->on('request', [$this, 'onRequest']);
            $this->ws->on('close', [$this, 'onClose']);
    
            $serv = $this->ws->addlistener('0.0.0.0', 9503, SWOOLE_SOCK_TCP);
            $serv->set([]);
            $serv->on('receive', [$this, 'onReceive']);
        }
    
        public function onWorkerStart()
        {
            $this->redis = new Swoole\Coroutine\Redis();
            $this->redis->connect('127.0.0.1', '6379');
            $this->redis->auth('123456');
            //清空绑定关系
            $this->redis->del('user_fd');
            $this->redis->del('device_user');
            $this->redis->del('device_fd');
        }
    
    
        /**打开webscokt连接
         * @param $ws
         * @param $request
         */
        public function onOpen($ws, $request)
        {
            $ws->push($request->fd, "hello, welcome\n");
    
        }
    
        /**websockt收到数据回调
         * @param $ws
         * @param $frame
         * @return bool
         */
        public function onMessage($ws, $frame)
        {
    
            $data = json_decode($frame->data, true);
            $user_id = $data['user_id'] ?? null;
            $device_id = $data['device_id'] ?? null;
            if (!$user_id || !$device_id) {
                $this->ws->push($frame->fd, "Parameter error");
                return false;
            }
            $this->redis->hset('user_fd', $user_id, $frame->fd);
            $this->redis->hset('device_user', $device_id, $user_id);
            $this->ws->push($frame->fd, "server: {$frame->data}");
        }
    
        public function onClose($ws, $fd)
        {
            echo "client-{$fd} is closed\n";
    
        }
    
        /**http请求回调
         * @param $request
         * @param $response
         */
        public function onRequest($request, $response)
        {
            $post_data = $request->post;
            $device_cmd = $post_data['cmd'] ?? null;
            $device_id = $post_data['device_id'] ?? null;
            $device_fd = $this->redis->hget('device_fd', $device_id);
    
            $user_id = $this->redis->hget('device_user', $device_id);
            $user_fd = $this->redis->hget('user_fd', $user_id);
            if ($user_fd) $this->ws->push($user_fd, $device_cmd);
    
            //发送数据到tcp服务
            if ($device_fd) {
                $client = new \Swoole\Coroutine\Client(SWOOLE_SOCK_TCP);
                $client->set(['max_coroutine' => 5,]);
                if (!$client->connect('127.0.0.1', 9503, 0.5)) {
                    exit("connect failed. Error: {$client->errCode}\n");
                }
                $str = json_encode(['device_fd' => $device_fd, 'device_cmd' => $device_cmd]);
                $client->send($str . "\r\n");
    //        echo $client->recv();
                $client->close();
            }
            $response->header("Content-Type", "text/html; charset=utf-8");
            $response->end("<h1>OK. #" . rand(1000, 9999) . "</h1>");
        }
    
    
        /**tcp接收数据回调
         * @param $serv
         * @param $fd
         * @param $threadId
         * @param $data
         */
        public function onReceive($serv, $fd, $threadId, $data)
        {
            $data = json_decode($data, true);
            $device_id = $data['device_id'] ?? null;
            $device_fd = $data['device_fd'] ?? null;
            $device_cmd = $data['device_cmd'] ?? null;
            //绑定设备关系
            if ($device_id) $this->redis->hset('device_fd', $device_id, $fd);
            //发送到设备数据
            if ($device_fd) $serv->send($device_fd, $device_cmd);
    
        }
    
        public function start()
        {
            $this->ws->start();
        }
    }
    
    $model = new Test();
    $model->start();
    

    web前端代码

    <!DOCTYPE HTML>
    <html>
       <head>
       <meta charset="utf-8">
       <title>测试</title>
        
          <script type="text/javascript">
           
        
                   
                   // 打开一个 web socket
                   var ws = new WebSocket("ws://127.0.0.1:9501");
                    
                   ws.onopen = function()
                   {
                    var str='{"user_id":1,"device_id":1}';
                        ws.send(str);
                          console.log('已链接');
                   };
                    
                   ws.onmessage = function (evt) 
                   { 
                      var received_msg = evt.data;
                     console.log(evt.data);
                   };
                    
                   ws.onclose = function()
                   { 
                      // 关闭 websocket
                        console.log('已关闭');
                   };
              
          </script>
            
       </head>
       <body>
          
       </body>
    </html>
    

    测试,我们用tcp与WebSocket分别连接上服务器,然后通过http发送数据,然后在tcp与WebSocket都能收到数据
    postman发送数据


    image.png

    tcp端


    image.png

    WebSocket端


    image.png

    相关文章

      网友评论

          本文标题:swoole同时连接 tcp http WebSocket三端数

          本文链接:https://www.haomeiwen.com/subject/ecxxvctx.html