众所周知,Web 应用的交互过程通常是客户端通过浏览器发出一个请求,服务器端接收请求后进行处理并返回结果给客户端,客端浏览器将信息呈现。但是对于实时性要求较高、海量并发的应用,比如金融证券的实时信息,web导航应用中地理位置获取,社交网络的实时消息推送等。

方案一:轮询,客户端用js代码每隔一定时间向服务器发送请求,这样会造成资源浪费(浪费带宽),在高并发的情况下还可能造成服务器奔溃。

方案二:基于Flash、AdobeFlash,通过socket实现数据信息交互,再利用Flash暴露的接口供js调用,但是Flash在移动互联网上的支持不好,IOS和Android都不支持Flash了。

方案三:WebSocket,2014年开始,各大应用服务器和浏览器厂商逐步统一,J2EE7也实现了WebSocket协议,无论客户端还是服务器都提供了对其的支持。

WebSocket介绍与原理

WebSocket 是 HTML5 一种新的协议。它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯,它建立在 TCP 之上,同 HTTP 一样通过 TCP 来传输数据,但是它和HTTP 最大不同是:

WebSocket 是一种双向通信协议,在基于http建立连接后,WebSocket 服务器和 browser都能主动向对方发送或接收数据,就像 Socket 一样;WebSocket 需要类似 TCP 的客户端和服务器端通过握手连接,连接成功后才能相互通信,实现长连接。

WebSocket 客户端连接报文

GET /webfin/websocket/ HTTP/1.1

Host: localhost

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Key: xqBt3ImNzJbYqRINxEFlkg==

Origin: http://localhost:8080

Sec-WebSocket-Version: 13

可以看到,客户端发起的 WebSocket 连接报文类似传统 HTTP 报文, ”Upgrade:websocket”参数值表明这是 WebSocket 类型请求, “Sec-WebSocket-Key”是 WebSocket 客户端发送的一个 base64 编码的密文, 要求服务端必须返回一个对应加密的“Sec-WebSocket-Accept”应答, 否则客户端会抛出“Error during WebSocket handshake”错误,并关闭连接。

WebSocket 服务端响应报文

HTTP/1.1 101 Switching Protocols

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Accept: K7DJLdLooIwIG/MOpvWFB3y3FE8=

“Sec-WebSocket-Accept”的值是服务端采用与客户端一致的密钥计算出来后返回客户端的, “HTTP/1.1 101 Switching Protocols”表示服务端接受 WebSocket 协议的客户端连接, 经过这样的请求-响应处理后,客户端服务端的 WebSocket 连接握手成功, 后续就可以进行 TCP 通讯了。

下载javax.websocket.jar,使用注解方式实现了一个简单的多房间聊天demo,demo只有一个服务端类和一个前端chat.html页面,打开多个chat.html页面,输入相同的房间名,进入房间后可以相互通信,不同房间不能互相通信,不同用户我用websocket的session自己分配的id来区分,因为一个用户连接到webSocket服务器就对应一个session,实际开发可以用http的session中登录的用户名来区分,连接到服务器的url中,roomName是一个路径参数,即在chat.html中获取到房间名。多房间的原理其实就是把多个用(session)放在roomName对应的set集合中,每次广播信息只在房间名对应的set集合中广播,实现房间聊天信息的隔离。

代码如下:

package webSocketTest;import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.HashSet;
import java.util.Set;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;/*** writer: holien* Time: 2017-08-01 13:00* Intent: webSocket服务器*/
@ServerEndpoint("/webSocket/chat/{roomName}")
public class WsServer {// 使用map来收集session,key为roomName,value为同一个房间的用户集合// concurrentMap的key不存在时报错,不是返回nullprivate static final Map<String, Set<Session>> rooms = new ConcurrentHashMap();@OnOpenpublic 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!");}@OnClosepublic void disConnect(@PathParam("roomName") String roomName, Session session) {rooms.get(roomName).remove(session);System.out.println("a client has disconnected!");}@OnMessagepublic void receiveMsg(@PathParam("roomName") String roomName,String msg, Session session) throws Exception {// 此处应该有html过滤msg = session.getId() + ":" + msg;System.out.println(msg);// 接收到信息后进行广播broadcast(roomName, msg);}// 按照房间名进行广播public static void broadcast(String roomName, String msg) throws Exception {for (Session session : rooms.get(roomName)) {session.getBasicRemote().sendText(msg);}}}
<!DOCTYPE html><html lang="en">
<head><meta charset="UTF-8"><title>网络聊天室</title>
</head>
<style type="text/css">.msg_board {width: 322px;height: 100px;border: solid 1px darkcyan;padding: 5px;overflow-y: scroll;// 文字长度大于div宽度时换行显示word-break: break-all;}/*set srcoll start*/::-webkit-scrollbar{width: 10px;height: 10px;background-color: #D6F2FD;}::-webkit-scrollbar-track{-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);/*border-radius: 5px;*/background-color: #D6F2FD;}::-webkit-scrollbar-thumb{height: 20px;/*border-radius: 10px;*/-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);background-color: #89D7F7;}/*set srcoll end*/
</style>
<body>
<label>房间名</label>
<input id="input_roomName" size="10" maxlength="10">
<input type="button"  value="进入聊天室" οnclick="initWebSocket()" />
<input type="button" value="退出聊天室" οnclick="closeWs()" /><br>
<div class="msg_board"></div>
<input id="input_msg" size="43" maxlength="40">
<input type="button" value="发送" οnclick="send_msg()" />
</body>
<script type="text/javascript">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 socketwebSocket = 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 + "<br>";// 让滚动块往下移动msg_board.scrollTop = msg_board.scrollTop + 40;};webSocket.onclose = function () {// 关闭 websocket,清空信息板alert("连接已关闭...");webSocket = null;document.getElementsByClassName("msg_board")[0].innerHTML = "";};}else {// 浏览器不支持 WebSocketalert("您的浏览器不支持 WebSocket!");}}
</script>
</html>

同时打开3个chat.html页面,2个页面进入名为“技术分享会”的房间,剩下一个进入名为“spring源码分析”的房间,只有相同房间的信息可以互通,截图如下:

发觉要更好的学习一种技术,得把该技术运用在具体功能实现上,这样会迫使我们去找资料和API,使得对该技术的认识更深刻...

websocket实现多房间聊天室相关推荐

  1. Nodejs+webSocket搭建多人聊天室

    NodeJs+webSocket搭建多人聊天室 准备的东西: 第一步:安装插件并且完善服务端 第二步 :搭建客户端并与服务端的通信 第三步 :添加CSS样式 第四步:总结 今天花了一个上午的时间去学习 ...

  2. rudesocket如何使用_[WebSocket入门]手把手搭建WebSocket多人在线聊天室(SpringBoot+WebS...

    前言 本文中搭建了一个简易的多人聊天室,使用了WebSocket的基础特性. 源代码来自老外的一篇好文: 本文内容摘要: 初步理解WebSocket的前后端交互逻辑 手把手使用 SpringBoot ...

  3. 教你从零开始用WebSocket打造一个IM聊天室

    之前我们在 IM即时聊天室(一):WebSocket 和 IM即时聊天室(二): Socket.io + Node.js 两篇文章中介绍了搭建一个IM的所需的技术栈和通信原理.那在这篇文章里我们就来详 ...

  4. 使用Node+websocket实现简易1v1聊天室(前端+服务器)

    使用Node+websocket实现简易1v1聊天室(前端+服务器) 前提: 安装好node环境~~~ 可使用 node -v 和 npm -v 查看是否装好 实现逻辑: 用户A 用户B 服务器 用户 ...

  5. SpringBoot入门建站全系列(二十七)WebSocket做简单的聊天室

    SpringBoot入门建站全系列(二十七)WebSocket做简单的聊天室 一.概述 WebSocket 是一种网络通信协议.RFC6455 定义了它的通信标准. WebSocket 是 HTML5 ...

  6. SpringBoot WebSocket之多人聊天室实现

    SpringBoot WebSocket之多人聊天室实现 WebSocket简介 什么是WebSocket? 为什么使用WebSocket? WebSocket的技术特点: WebSocket的技术优 ...

  7. IM即时通信多房间聊天室仿微信聊天(二)

    IM即时通信多房间聊天室仿微信聊天(服务器自定义处理客户端消息) 在IM即时通信多房间聊天室仿微信聊天(一)中我们已经搭建了基本的通信架构,接下来重点就是如何在自己的后台接收并处理客户端用户的消息了 ...

  8. html5 websocket java 聊天室_如何利用WebSocket实现网页版聊天室

    花了将近一周的时间终于完成了利用WebSocket完成网页版聊天室这个小demo,期间还走过了一段"看似弯曲"的道路,但是我想其实也不算是弯路吧,因为你走过的路必将留下你的足迹.这 ...

  9. IM即时通信多房间聊天室仿微信聊天(四)

    聊天记录的保存和展示 IM即时通信多房间聊天室仿微信聊天(一) IM即时通信多房间聊天室仿微信聊天(二) IM即时通信多房间聊天室仿微信聊天(三) 聊天消息的保存我们直接在服务端接收到客户端发送的消息 ...

  10. html 聊天室模版,WebSocket+HTML5实现在线聊天室

    centos6.8 我之前在系统上安装了php7还有swoole扩展可以用命令查看扩展有没有装好php -i|grep swoole  (没装的直接看我之前文章吧,或者留言我告诉你怎么装)git cl ...

最新文章

  1. 排名前 16 的 Java 工具类
  2. 怎么把圆角变直角_明式圆角柜的还原(下)——信民木工DIY达人大赛作品
  3. matlab length_《Matlab - Robotics System Toolbox》学习笔记(2)
  4. NLP入门竞赛,搜狗新闻文本分类
  5. kernel vim阅读 设置tags的标签
  6. 文本类文件与VS关联-实践
  7. Trie UVALive 7192 Chip Factory (15长春J)
  8. SQL进阶教程 | 史上最易懂SQL教程 5小时零基础成长SQL大师
  9. VTK:可视化之ProgrammableGlyphFilter
  10. 算法:删除顺序表中重复的元素
  11. update core.php,WordPress更新失败-这通常是由于文件权限不一致所致。:wp-admin/includes/update-core.php...
  12. Redis性能基准测试
  13. g++编译支持c++11
  14. Google Maps API 进级:GoogleMaps中显示画中画
  15. Excel表格数据生成sql插入语句
  16. 免费申请国外免费域名超详细教程
  17. wps复选框怎么设置,wps表格中如何插入复选框?
  18. 微信支付接口调用问题(android正常,iphone调不起)
  19. 洗头冲水时冲下好些头发,我是要秃了吗?
  20. 如何在word里里面打勾

热门文章

  1. mac nmap 的下载
  2. 《动手学深度学习》学习笔记(五)-几种常见的卷积神经网络整理。
  3. 计算机网络 - 练习(三十二)
  4. Linux磁盘列阵(RAID),包括RAID详解、Linux磁盘列阵和mdadm命令的相关操作
  5. 比较lowB的Excel初始使用,
  6. 开题报告(1.研究目标)
  7. leetcode剑指Offer2
  8. 第46届EC-Final总结
  9. 详谈双亲委派机制(面试常问)
  10. hosts文件导致无法网页观看视频