WebSocket实现多房间聊天室

WebSocket简介

WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。

当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。

聊天室的实现

最近在项目中要实现一个聊天功能,所以就想到了使用WebSocket,此聊天室是类似QQ聊天形式,有头像加文字,自己发送的消息和别人的消息可以很明显区分。下载javax.websocket.jar使用注解方式实现了一个简单的多房间聊天demo,通过打开多个index.html页面,输入相同的房间名,进入房间后可以相互通信,不同房间不能互相通信,不同用户通过websocket的session自己分配的id来区分,自己的头像和别人的头像使用两张图片区分,实际开发可以使用用户名和用户的头像来区分。连接到服务器的url中,roomName是一个路径参数,即在index.html中获取到房间名。多房间的原理其实就是把多个用(session)放在roomName对应的set集合中,每次广播信息只在房间名对应的set集合中广播,实现房间聊天信息的隔离。


服务器端代码

@ServerEndpoint("/webSocket/chat/{roomName}")
public class WsServer {

    // 使用map来收集session,key为roomName,value为同一个房间的用户集合
    // concurrentMap的key不存在时报错,不是返回null
    private static final Map<String, Set<Session>> rooms = new ConcurrentHashMap();

    @OnOpen
    public void connect(@PathParam("roomName") String roomName, Session session) throws Exception {
        // 将session按照房间名来存储,将各个房间的用户隔离
        if (!rooms.containsKey(roomName)) {
            // 创建房间不存在时,创建房间
            Set<Session> room = new HashSet<>();
            // 添加用户
            room.add(session);
            rooms.put(roomName, room);
        } else {
            // 房间已存在,直接添加用户到相应的房间
            rooms.get(roomName).add(session);
        }
        System.out.println("a client has connected!");
    }

    @OnClose
    public void disConnect(@PathParam("roomName") String roomName, Session session) {
        rooms.get(roomName).remove(session);
        System.out.println("a client has disconnected!");
    }

    @OnMessage
    public void receiveMsg(@PathParam("roomName") String roomName,
                           String msg, Session session) throws Exception {

        //创建时间
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        Date date =new Date();
        String time = simpleDateFormat.format(date);
        String message;
        //可以在此保存数据到数据库

        for (Session session1 : rooms.get(roomName)) {
            //判断是否发送给自己
            if(session1.equals(session)) {
                //发送给自己
                message = "<div class='chat-message-right'><img class='img-circle' src='/img/1.jpg'  style='width:48px;height: 48px;'><div class='message'><a class='message-author'> "+session1.getId()+"</a><span class='message-date'> "+time+" </span><span class='message-content'>"+msg+"</span></div></div>";
            }else {
                //发送给别人
                message = "<div class='chat-message-left'><img class='img-circle' src='/img/2.jpg'  style='width:48px;height: 48px;'><div class='message'><a class='message-author'> "+session1.getId()+"</a><span class='message-date'> "+time+" </span><span class='message-content'>"+msg+"</span></div></div>";
            }
            //发送
            session1.getBasicRemote().sendText(message);

        }
    }
前台页面代码
<!DOCTYPE html>
<html>

	<head>

		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
		<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
		<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
		<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
		<script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
		<title>私信界面</title>

		<!-- Bootstrap -->
		<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
		<link href="css/main.css" rel="stylesheet">

		<script>

			$(document).ready(function(){
				$("#quxiaobtn").click(function(){
					$("#text").val('');
				});
				
			});



		<!-- 聊天js -->
            var webSocket;

            function send_msg() {
                if (webSocket != null) {
                    var input_msg = document.getElementById("input_msg").value.trim();
                    if (input_msg == "") {
                        return;
                    }
                    webSocket.send(input_msg);
                    // 清除input框里的信息
                    document.getElementById("input_msg").value = "";
                } else {
                    alert("您已掉线,请重新进入聊天室...");
                }
            };

            function closeWs() {
                webSocket.close();
            };

            function initWebSocket() {
                var roomName = document.getElementById("input_roomName").value;
                // 房间名不能为空
                if (roomName == null || roomName == "") {
                    alert("请输入房间名");
                    return;
                }
                if ("WebSocket" in window) {
//            alert("您的浏览器支持 WebSocket!");
                    if (webSocket == null) {
                        var url = "ws://localhost:8080/webSocket/chat/" + roomName;
                        // 打开一个 web socket
                        webSocket = new WebSocket(url);
                    } else {
                        alert("您已进入聊天室...");
                    }

                    webSocket.onopen = function () {
                        alert("已进入聊天室,畅聊吧...");
                    };

                    webSocket.onmessage = function (evt) {
                        var msg_board = document.getElementsByClassName("msg_board")[0];
                        var received_msg = evt.data;
                        var old_msg = msg_board.innerHTML;
                        msg_board.innerHTML  = old_msg + received_msg ;
                        // 让滚动块往下移动
                        msg_board.scrollTop = msg_board.scrollHeight;
                    };

                    webSocket.onclose = function () {
                        // 关闭 websocket,清空信息板
                        alert("连接已关闭...");
                        webSocket = null;
                        document.getElementsByClassName("msg_board")[0].innerHTML = "";
                    };
                }
                else {
                    // 浏览器不支持 WebSocket
                    alert("您的浏览器不支持 WebSocket!");
                }
            }
		</script>

	</head>

	<!--背景色-->

	<body class="gray-bg">
		<header class="clearfix">
			<!-- 头部 -->

			<nav class="navbar navbar-default" role="navigation">
				<div class="container-fluid">
					<div class="navbar-header">

						<a class="navbar-brand" href="#">XXX聊天室</a>
					</div>
				</div>
			</nav>
		</header>
		<!--整体布局-->
		    
		<label>房间名</label>
		<input id="input_roomName" style="width: 10em" type="text"  placeholder="房间号">
		<input class="btn btn-default" type="button" value="进入聊天室" οnclick="initWebSocket()">
		<input class="btn btn-default" type="button" value="退出聊天室" οnclick="closeWs()">
		<div id="zhongjian">
			<div class="wrapper wrapper-content animated fadeInRight">
				<div class="row">
					<div class="col-sm-12">
						<div class="ibox chat-view ">
							<div class="ibox-title">
								<small class="pull-right text-muted" style="color: #fff;">最新消息:2018-06-21 </small> 聊天窗口
							</div>
							<div class="ibox-content col-lg-12">
								<div class="row">
									<div class="col-md-12 ">
										<div id="msg_board" class="chat-discussion msg_board">
										</div>
									</div>
								</div>
								<div class="row">
									<div class="col-sm-12">
										<div class="chat-message-form">

											<div class="form-group">

												<textarea id="input_msg" class="form-control message-input" name="message" placeholder="输入消息内容"></textarea>

												<div class="buttongroup" style="float: right;">
												
													<input id="quxiaobtn" type="reset" class="btn btn-default" value="取消" />
												  
												<input id="btn"  type="button" οnclick="send_msg()" class="btn btn-default" value="确定" />
												</div>
											</div>
										</div>
									</div>
								</div>
							</div>
						</div>
					</div>
				</div>
			</div>
		</div>
		</div>
	</body>

</html>

效果




源码下载:https://github.com/shikuLi/ChatRoom

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值