关于websocket的重复登陆问题

遇到一个难题是,重复登陆问题,比如A设备登录了,B设备登录了同样的ID,建立了socket连接,这时候A就会收不到消息了(都发到B那里了)。

为了解决这个问题,采用的方法是在B登录时,判断socket连接池里是否已有该id的socket连接,如果有则在B连接之前,先给这个id的socket发送消息,告知已在其他设备登陆,强制退出。

代码比较简单,在OnOpen方法中

if(webSocketSet.get(operatorId) != null && webSocketSet.get(operatorId).session != null){
          
   
    	statusManager.put(operatorId, "repeatLogin");
    	System.out.println("该操作员已登录,强制退出");
		JSONObject result = new JSONObject();
		result.put("message", "您已在别处登录,该设备自动退出");
		result.put("msgType",MSG_TYPE_REPEAT_LOGIN);
		result.put("recipientId",operatorId);
		if(this.OnMessage(result.toString())){
          
   
			 webSocketSet.remove(operatorId);
		}
}

但是这样存在一个问题,A收到强制退出,然后A断开连接了,但是A断开的时候,服务器端的onClose监听到这个A断开了,然后从socket连接池里remove掉这个id,这时候这个id已经是B连接着的了,因为它俩是一样的id,所以把B也带掉了。 于是解决办法是加一个标志位

private static ConcurrentHashMap<String, String> statusManager = new ConcurrentHashMap<>();

当强制登陆的时候,给这个id置为 repeatLogin

statusManager.put(operatorId, "repeatLogin");

如果是正常登录,给这个id置为firstLogin

statusManager.put(operatorId, "firstLogin");

然后在onClose中进行判断

if("firstLogin".equals(statusManager.get(operatorId))){
          
   
	webSocketSet.remove(this.operatorId);
	statusManager.remove(this.operatorId);
	System.out.println("删除成功");
	}else{
          
   
	statusManager.put(this.operatorId,"firstLogin");
}

如果是强制登陆的,也就是B用户,那就啥也不做,不remove,把A用户remove掉

// 服务器响应消息
if (jo.containsKey("senderId") && jo.getString("senderId").equals(this.operatorId)) {
          
   
	try {
          
   
		
		JSONObject messageResult = new JSONObject();
		messageResult.put("msgType", MSG_TYPE_RESPONSE);
		messageResult.put("type", SEND_MSG_RESULT_TYPE_SUCCESS);
		messageResult.put("message", "发送成功");
		AppointSending(this.operatorId, messageResult.toJSONString());
	} catch (Exception e) {
          
   
		// TODO Auto-generated catch block
		// e1.printStackTrace();
		log.error(e.getMessage());
	}
}
经验分享 程序员 微信小程序 职场和发展