您当前的位置: 首页 >  websocket

【03】

暂无认证

  • 3浏览

    0关注

    196博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

webSocket多线程推送出错

【03】 发布时间:2020-07-17 10:25:59 ,浏览量:3

错误信息

webSocket多线程推送出错,报错信息为The remote endpoint was in state [TEXT_PARTIAL_WRITING]

错误原因

两个方法有可能同时执行,当方法1或者方法2遍历到某一个session并且调用sendMessage发送消息的时候,另外一个方法也正好也在使用相同的session发送另外一个消息(同一个session消息发送冲突了,也就是说同一个时刻,多个线程向一个socket写数据冲突了),就会报上面的异常。

解决方案

采用的是将session存入2个数组,数组A放置空闲session,数组B存放忙碌中的session。何为忙碌?当前session进行send发送信息还没结束即为忙碌。

在发送信息时判断当前session是忙碌状态还是空闲状态:

如为空闲,直接执行发送并且把当前session在空闲(A)中移除,并把它放入忙碌(B)的数组中,当执行完成,将空闲的session从忙碌(B)中移除,并且存入空闲(A)数组中。

如为忙碌,则跳过发送,延迟递归调用本身发送方法,延迟后执行再作判断是当前session是否忙碌,递归直到空闲再发送这则数据

代码实现 声明静态变量集合用于存放空闲以及忙碌的session
 // 记录空闲Session集合
    private static CopyOnWriteArraySet idle = new CopyOnWriteArraySet();
    // 记录正在使用中Session集合,value为Future,表示使用情况
    private static ConcurrentHashMap busy = new ConcurrentHashMap();
发送数据
// 新增Session
    public static void open(Session session) {
        idle.add(session);
    }

    // 关闭Session
    public static void close(Session session) {
        idle.remove(session);
        busy.remove(session);
    }

    // 使用session发送消息
    public static void send(Session session, SocketMessage message, Integer timeout) throws InterruptedException {
        if (timeout 客户端上线时操作 
@OnOpen
    public void onOpen(Session session,@PathParam("param")String socketUserId) {
         System.out.println("有新的客户端连接了: "+session.getId());
        open(session);
    }
移除session->客户端掉线时操作
@OnClose
    public void onClose(Session session) {
        System.out.println("用户" + session.getId() + "离线");
        close(session);
    }
使用发送消息
try {
	send(session, "大家好,我是零三,很高兴认识大家,我的网址是web03.cn", 3000);
} catch (InterruptedException e) {
	e.printStackTrace();
}
总结

此方法可以很有效的解决低并发问题,这只是一种解决方案,当然可能有更优的解决方法,交给多线程的同步机制去执行,因为我个人用多线程无法实现,所以使用当前下策

关注
打赏
1657344724
查看更多评论
0.0385s