layim即使通讯框架只能两个浏览器之间单向通讯问题

项目场景:

毕业设计作品:

项目场景:两个浏览器之间通信


问题描述

只能一个浏览器发到另一个浏览器:

两个浏览器分别登陆用户,打开框架自带的通信窗口,但是只能单向通信


原因分析:

原理分析:一定要一字一句读懂

通信窗口所在页面每次刷新都会建立一个websocket连接,而后端代码就会不断保存新的连接,由于保存websocketsession使用HashMap以用户id为key保存的,所以后端session不断在map里面刷新,session.send的时候保存的websocketsession与浏览器的session不一致,所以就发不过去,但都有一个共同点,两个浏览器都能发送数据给服务器,就只是其中一个session.isOpen()判断为false,发不了数据,说是关闭状态。其实所谓的关闭状态就是后端已经保存了这个对应userId的websocketsession,但是你浏览器可能由于种种原因(session保存的设计原因,我就是)导致服务端与客户端的session不一致,所以就找不到这个session,也就认为是关闭状态了。


解决方案:

具体解决方案:服务端demo设计根据业务需求

解决的核心:维持连个浏览器的session和服务器HashMap保存的分别一样。这里就有人会想出一种很暴力的方法:不管登录与否,我就在某一次保存websocketsession,而且针对每个userId我只保存一次,同时保证浏览器只能创建一次websocket连接,不管用什么方式去实现这个操作。但是,我踩坑了,因为我也的确这么做。不能这样做的原因是,websocket设计之初的理念就是每个连接默认都是只能发一次消息,直到有新连接创建并且连接上去,否则就会阻塞。这就是阻塞模式。还有一个原因就是我的服务端是单线程。如果这么做的话两个浏览器就只能各自发送一次数据而已。同时,也与websocket设计理念相违背。因此,我们不能去违背框架设计理念开发,而是顺从天意,既然页面刷新就不断创建新连接,那么我们就在服务端设计存websocketSession的规则保持每次页面刷新后就在服务端同步这个session即可。还有一个办法就是单线程不行就多线程,具体如何下期分享。

前端代码:

socket = new WebSocket('ws://localhost:8080/myHandler?myid='+currentUserId);

后端代码:

//部分片段1
//消息处理类
@Component
public class MyHandler extends TextWebSocketHandler {
    @Autowired
    private RedisTemplate redisTemplate;
    // 在线用户列表
    public volatile static  Map<String, WebSocketSession> userSocketSessionMap = new HashMap<String, WebSocketSession>();
    public volatile static  Map<String, String>  loginedUser= new HashMap<String, String>();

    // 用户连接成功 就被调用
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        //获取传来的登录用户的id
        String currentUserId = session.getUri().toString().split("=")[1];
        if (!currentUserId.equals("undefined") && !StringUtils.isEmpty(currentUserId)) {
            userSocketSessionMap.put(currentUserId, session);
        }
        String webSocketSessionUserId = (String)redisTemplate.opsForValue().get("webSocketSessionUserId");
        int size = userSocketSessionMap.size();
       /* if (!StringUtils.isEmpty(webSocketSessionUserId)
                && (size < 2 )
                && (!userSocketSessionMap.containsKey(webSocketSessionUserId))
        ) {
            //保存对应的WebSocketSession
            userSocketSessionMap.put(webSocketSessionUserId, session);
            loginedUser.put(webSocketSessionUserId , "");
        }*/
        System.err.println("用户连接成功");
    }

//部分片段2
 if(session.isOpen()){
                        System.out.println("回复消息");
                        System.out.println(message.getPayload());
                        session.sendMessage(message);
                    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fire king

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值