IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> webSocket简单应用(三、带房间的聊天室编写) -> 正文阅读

[网络协议]webSocket简单应用(三、带房间的聊天室编写)

制作背景为老师和学生交流,但是交流的范围为班级的某一个任课老师和本班的学生,执行的操作是老师向学生询问是否听懂了,学生进行回复。这是一个项目中的一部分,主要用于线上教学时的学生回应。

WebSocketRoom配置类

@Slf4j
public class WebSocketRoom {
    public static Map<String, ConcurrentHashMap<String, Session>> rooms = new ConcurrentHashMap();
    public static void close(String roomId,String sessionId) throws IOException {//sessionId就是account
        log.info("{}从{}房间断开了链接",sessionId,roomId);
        Map<String, Session> sessions=rooms.get(roomId);//获取当前房间的信息
        for (String account : sessions.keySet()) {
            Session session = sessions.get(account);//获取当前hashmap中的value值
            if (session.getId().equals(sessionId)) {
                sessions.remove(account);//如果当前池中有key对应的value值,则进行清除操作
                break;
            }
        }
    }

    public static void sendMessage(String roomId,String account, String message) {//一对一发送,用于学生回复老师是否听懂
        log.info("在房间{}中,{}发送消息{}",roomId,account,message);
        rooms.get(roomId).get(roomId).getAsyncRemote().sendText(message);//获取需要发送的用户,并发送信息
    }

    public static void sendMessage(String roomId,String message) {//对当前所有的链接进行发送,用于老师向学生提问是否听懂
        for (String sessionId : rooms.get(roomId).keySet()) {
            log.info("已经向"+sessionId+"发送消息"+message);
            rooms.get(roomId).get(sessionId).getAsyncRemote().sendText(message);//获取需要发送的用户,并发送信息
        }
    }
    public static String sendMessage(String roomId) {//获取当前房间所有的用户
        String allMember="";
        for (String account : rooms.get(roomId).keySet()) {
            if(allMember=="")
                allMember=account;
            else
            allMember=allMember+","+account;//获取用户账号并拼接
        }
        return  allMember;
    }
}

其实和第一个wesocket配置类相似,只不过是在操作前先要找到对应房间号的map,之后再进行其他的操作,配备上房间内的群发和一对一发送。这里面需要注意ConcurrentHashMap要声明为静态变量。每个用户的发送信息的前提是知道接收者的session地址是什么,这就需要一个公共的存储区域,方便去寻找。所以声明为static类型(静态变量也称为类变量,属于类对象所有,位于方法区,为所有对象共享,共享一份内存,一旦值被修改,则其他对象均对修改可见)这要就可以保证能够拿到正确的数据了,同时方法也声明为static类型,用于操作链接池。

这里面定了不同入参的sendMessage用于群发和一对一发送

WebSocketServiceImp类的编写

@Slf4j
@Service
@Component
@ServerEndpoint("/webSocketRoom/{account}/{roomId}")
@DependsOn("springContextUtils")
public class WebSocketRoomServiceImpl {
    /** 记录当前在线连接数 */
//    private static AtomicInteger onlineCount = new AtomicInteger(0);
    private Session session;
   

    //为这个变量添加set方法
    public static void setApplicationContext(ApplicationContext applicationContext) {
        WebSocketRoomServiceImpl.applicationContext = applicationContext;
    }
    @OnOpen
    public void onOpen(Session session, @PathParam("account") String account,@PathParam("roomId") String roomId) throws IOException {
        if(WebSocketRoom.rooms.get(roomId)==null&&account.equals(roomId)){//如果房间号和账号时相同,说明是老师账号,则创建房间
            ConcurrentHashMap<String, Session> sessions = new ConcurrentHashMap<>();//创建新的连接池
            WebSocketRoom.rooms.put(roomId,sessions);
        }else if(WebSocketRoom.rooms.get(roomId)==null&&!account.equals(roomId))//如果房间号不存在且账号和房间号不一致则关闭连接
        {
            log.info("{}加入的{}房间不存在",account,roomId);
            this.onClose(session,account,roomId);
            return;
        }

        WebSocketRoom.rooms.get(roomId).put(account, session);//加入用户到连接池中
        log.info("有账号加入:{},当前在线人数为:{}", account, WebSocketRoom.rooms.get(roomId).size());
//        String nowNumber=roomId+"当前在线人数"+WebSocketRoom.rooms.get(roomId).size();
//        String nowNumber= WebSocketRoom.sendMessage(roomId);
        log.info("当前所有的用户:"+WebSocketRoom.sendMessage(roomId));
        this.onMessage(roomId,account,WebSocketRoom.sendMessage(roomId));//发送当前加入的账号
    }

    @OnClose
    public void onClose(Session session,@PathParam("account") String account,@PathParam("roomId") String roomId) throws IOException {
        if(WebSocketRoom.rooms.get(roomId)==null){
            session.close();//关闭当前用户链接
            return;
        }
        log.info("有账号退出:{},当前在线人数为:{}", account, WebSocketRoom.rooms.get(roomId).size());
        WebSocketRoom.close(roomId,session.getId());//从链接池中删除用户信息
        session.close();//关闭当前用户链接
        log.info("当前所有的用户:"+WebSocketRoom.sendMessage(roomId));
        this.onMessage(roomId,account,WebSocketRoom.sendMessage(roomId));//发送当前加入的账号
        if(WebSocketRoom.rooms.get(roomId).size()==0)
        {
            log.info("{}房间已经销毁",roomId);
            WebSocketRoom.rooms.remove(roomId);
        }
    }
    @OnError
    public void onError(Throwable t) throws Throwable {
        log.error("webScoketRoom报错: " + t.toString());
    }


    @OnMessage
    public void onMessage(@PathParam("roomId") String roomId,@PathParam("account") String account,String message){
        message=account+":"+message;
        if(roomId.equals(account)){
            log.info("{}执行了一对多发送操作{}",account,roomId);
            WebSocketRoom.sendMessage(roomId,message);//发送消息群发
        }
        else{
            log.info("{}执行了一对一发送操作{}",account,roomId);
            WebSocketRoom.sendMessage(roomId,account,message);//学生向老师发送消息
        }
    }
    public void send(Session toSession,String message){
        try {
            log.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);
            toSession.getBasicRemote().sendText(message);
        } catch (Exception e) {
            log.error("服务端发送消息给客户端失败:{}", e);
        }
    }

}

首先是@OnOpen注解,他的意思是在链接建立的时候调用的方法。我们在这个方法中对用户信息进行操作,因为环境是老师和学生,那么能够创建班级聊天室的的应该是老师。先判断房间号在连接池中有没有,如果有则加入。如果没有则判断房间号和用户账号是否一致,如果一致则认为是老师账号,先将房间加入到链接池中,在将老师的账号加入到链接池中。

之后是@OnMessage,这个注解是对接受到的消息进行处理,因为操作要求的原因,我们需要判断当前账号是否为老师账号,如果是则执行群发操作对班级中所有的学生都发消息,如果是学生则执行一对一操作用于学生回答老师的询问

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-08-06 10:11:58  更:2021-08-06 10:12:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/5 0:13:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码