客户端连接上来后,在没有超时的情况下,同一个客户端又发起了一个连接,如何判断是否存在旧连接,然后把旧连接踢掉,如果通过循环判断,如果客户端连接有很多的话,在onMessage做这个循环,感觉不合理,有没有什么好的方法能实现
在onWorkerStart里跑timer https://www.workerman.net/doc/workerman/faq/heartbeat.html
是这样的,心跳30秒,但是客户端在30秒内又发了一次连接过来,老的连接还没到30秒心跳条件,所以不会踢出去,所以如果客户端再发次连接过来,就有2个连接了,所以必须把老的连接踢掉,不然就会有问题
在三次握手的时候根据客户端分配一个UUID, 在客户端首次连接通过验证的时候把ID添加进UUID,在跑timer的时候去遍历就可以操作了。
现在就是不想去遍历呀,如果连上来的客户端有很多,去做遍历查询再踢出去,效率太低了
那就在每次连接验证过ID后去检查UUID里是否存在连接,存在则close,否则添加当前ID进UUID
每次连接验证过ID后去检查UUID里是否存在连接?这个怎么检查,onMessage的时候,才确定设备编号,3次握手,其实还不知道设备编号是多少,我看了下手册onConnect时只能获取IP和端口,我是觉得再这个位置去做检查的,但是感觉做不到
也就是说再次connect时,你要确定出之前这个客户端有没有connect,哪一个connect
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 } } }
是不是可以这样理解,onMessage里面,就算已经连接了的,只要先unset($worker->uidConnections[$connection->uid])连接,再重新$worker->uidConnections[$connection->uid] = $connection;也是可以的
不行,unset 只是把映射的uidConnections咔嚓了,实际连接还是存在的,必须->close()才算关闭连接。
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。
isset($worker->uidConnections[$uid])
实际上数组遍历也很快,1万个元素的数组遍历一次也就0.0001秒。
同一个客户端发起了两次连接,得到的uid不一样吧?
uid是客户端发给服务端的,一样不一样看客户端业务逻辑。就物联网设备而言,设备id是不变的,连多少次都是同一个设备id
所以说onConnect时,无法准确的检测出是否是同一个客户端
只能在onmessage里验证
onConnect是tcp三次握手,只能获取到设备的出口ip和端口,其它信息获取不到。如果每台设备的出口ip或者设备端口不一样,也可以判断是不是同一个客户端。
在onWorkerStart里跑timer
https://www.workerman.net/doc/workerman/faq/heartbeat.html
是这样的,心跳30秒,但是客户端在30秒内又发了一次连接过来,老的连接还没到30秒心跳条件,所以不会踢出去,所以如果客户端再发次连接过来,就有2个连接了,所以必须把老的连接踢掉,不然就会有问题
在三次握手的时候根据客户端分配一个UUID, 在客户端首次连接通过验证的时候把ID添加进UUID,在跑timer的时候去遍历就可以操作了。
现在就是不想去遍历呀,如果连上来的客户端有很多,去做遍历查询再踢出去,效率太低了
那就在每次连接验证过ID后去检查UUID里是否存在连接,存在则close,否则添加当前ID进UUID
每次连接验证过ID后去检查UUID里是否存在连接?这个怎么检查,onMessage的时候,才确定设备编号,3次握手,其实还不知道设备编号是多少,我看了下手册onConnect时只能获取IP和端口,我是觉得再这个位置去做检查的,但是感觉做不到
也就是说再次connect时,你要确定出之前这个客户端有没有connect,哪一个connect
是不是可以这样理解,onMessage里面,就算已经连接了的,只要先unset($worker->uidConnections[$connection->uid])连接,再重新$worker->uidConnections[$connection->uid] = $connection;也是可以的
不行,unset 只是把映射的uidConnections咔嚓了,实际连接还是存在的,必须->close()才算关闭连接。
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秒。
同一个客户端发起了两次连接,得到的uid不一样吧?
uid是客户端发给服务端的,一样不一样看客户端业务逻辑。就物联网设备而言,设备id是不变的,连多少次都是同一个设备id
所以说onConnect时,无法准确的检测出是否是同一个客户端
只能在onmessage里验证
onConnect是tcp三次握手,只能获取到设备的出口ip和端口,其它信息获取不到。如果每台设备的出口ip或者设备端口不一样,也可以判断是不是同一个客户端。