如何判断同一个客户端连接是不是旧连接

test123456

客户端连接上来后,在没有超时的情况下,同一个客户端又发起了一个连接,如何判断是否存在旧连接,然后把旧连接踢掉,如果通过循环判断,如果客户端连接有很多的话,在onMessage做这个循环,感觉不合理,有没有什么好的方法能实现

499 3 1
3个回答

army
  • test123456 2023-05-15

    是这样的,心跳30秒,但是客户端在30秒内又发了一次连接过来,老的连接还没到30秒心跳条件,所以不会踢出去,所以如果客户端再发次连接过来,就有2个连接了,所以必须把老的连接踢掉,不然就会有问题

  • army 2023-05-15

    在三次握手的时候根据客户端分配一个UUID, 在客户端首次连接通过验证的时候把ID添加进UUID,在跑timer的时候去遍历就可以操作了。

  • test123456 2023-05-15

    现在就是不想去遍历呀,如果连上来的客户端有很多,去做遍历查询再踢出去,效率太低了

  • army 2023-05-15

    那就在每次连接验证过ID后去检查UUID里是否存在连接,存在则close,否则添加当前ID进UUID

  • test123456 2023-05-15

    每次连接验证过ID后去检查UUID里是否存在连接?这个怎么检查,onMessage的时候,才确定设备编号,3次握手,其实还不知道设备编号是多少,我看了下手册onConnect时只能获取IP和端口,我是觉得再这个位置去做检查的,但是感觉做不到

  • 小W 2023-05-15

    也就是说再次connect时,你要确定出之前这个客户端有没有connect,哪一个connect

army
private array $linkList = array();
 /**
     * 客户端连接时(三次握手)
     * @param TcpConnection $c
     * @param               $httpBuffer
     * @return void
     */
    public function connect(TcpConnection $c, $httpBuffer): void
    {
        if (!in_array($_SERVER['HTTP_ORIGIN'], Army::$Config['ALLOW_ORIGIN'])) {
            $c->close();
        }
        $c->uuid = md5($httpBuffer);
        //向客户端发送检测指令,让客户端上传token等进行首次uuid绑定
         .....
    }
   //onMessage
    public function run(TcpConnection $c, $request): void
    {
        //客户端请求带上token
        .....
        //验证司机token为userID
        $driverID = DriverToken::get($driverToken, $sid);
        //将本次连接放入linkList
        if ($driverID > 0 && isset($c->uuid)) {
            if (!isset($this->linkList[$c->uuid][$driverID])) {
                $this->linkList[$c->uuid][$driverID] = $c;//首次
            }else{
               //如果该用户已经连接操作
                $this->linkList[$c->uuid][$driverID]->close(); //关闭连接
                unset($this->linkList[$c->uuid][$driverID] );//移除
                $this->linkList[$c->uuid][$driverID] = $c;//重新把本次连接放入linkList
            }
        }
   }
  • test123456 2023-05-16

    是不是可以这样理解,onMessage里面,就算已经连接了的,只要先unset($worker->uidConnections[$connection->uid])连接,再重新$worker->uidConnections[$connection->uid] = $connection;也是可以的

  • army 2023-05-18

    不行,unset 只是把映射的uidConnections咔嚓了,实际连接还是存在的,必须->close()才算关闭连接。

walkor

https://www.workerman.net/doc/workerman/faq/send-data-to-client.html#WorkerMan%E4%B8%AD%E5%A6%82%E4%BD%95%E5%90%91%E6%9F%90%E4%B8%AA%E7%89%B9%E5%AE%9A%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%8F%91%E9%80%81%E6%95%B0%E6%8D%AE

参考手册例子
判断是否有旧连接,用isset($worker->uidConnections[$uid])来判断。这里$uid可以看作是设备id。

实际上数组遍历也很快,1万个元素的数组遍历一次也就0.0001秒。

  • 小W 2023-05-16

    同一个客户端发起了两次连接,得到的uid不一样吧?

  • walkor 2023-05-16

    uid是客户端发给服务端的,一样不一样看客户端业务逻辑。就物联网设备而言,设备id是不变的,连多少次都是同一个设备id

  • 小W 2023-05-16

    所以说onConnect时,无法准确的检测出是否是同一个客户端

  • 小W 2023-05-16

    只能在onmessage里验证

  • walkor 2023-05-16

    onConnect是tcp三次握手,只能获取到设备的出口ip和端口,其它信息获取不到。如果每台设备的出口ip或者设备端口不一样,也可以判断是不是同一个客户端。

🔝