代码地址:https://gitee.com/alleniverrui/web-socket-simple-group-chat.git
WebSocket 简介
如果说ajax像手机发短信一样,发送信息,获取信息,那么websocket技术则是打电话这样。WebSocket要达到的目的是让用户不需要刷新浏览器就可以获得实时更新。
在WebSocket以前你可能会使用ajax进行轮询(包括现在有些没有集成WebSocket的软件),这就造成了服务器的多重压,大量消耗服务器带宽和资源。
面对这种状况,HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽并实现真正意义上的实时推送。
WebSocket协议本质上是一个基于TCP的协议,它由通信协议和编程API组成,WebSocket能够在浏览器和服务器之间建立双向连接, 以基于事件的方式,赋予浏览器实时通信能力。既然是双向通信,就意味着服务器端和客户端可以同时发送并响应请求,而不再像HTTP的请求和响应。
应用场景:
- 显示网站在线人数
- 群聊单聊
- 管理员像所有在线用户传递消息
WebSocket 事件
事件 | 描述 |
---|---|
Socket.onopen | 连接建立时触发 |
Socket.onmessage | 客户端接收服务端数据时触发 |
Socket.onerror | 通信发生错误时触发 |
Socket.onclose | 连接关闭时触发 |
WebSocket 方法
方法 | 描述 |
---|---|
Socket.send() | 使用连接发送数据 |
Socket.close() | 关闭连接 |
群聊聊天室构建
效果浏览
所需依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- websocket 相关依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>1.5.10.RELEASE</version>
</dependency>
<!-- 日志-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- 引入fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.7</version>
</dependency>
创建配置类
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
服务层(处理客户端消息)
@Component
@ServerEndpoint("/websocket")
@Slf4j
public class WebSocketService {
/**
* 初始在线人数
*/
private static int online_num = 0;
/**
* 线程安全的socket集合
*/
private static CopyOnWriteArraySet<WebSocketService> webSocketSet = new CopyOnWriteArraySet<>();
/**
* 会话
*/
private Session session;
@OnOpen
public void onOpen(Session session) throws IOException {
this.session = session;
webSocketSet.add(this);
addOnlineCount();
log.info("有链接加入,当前人数为:{}",getOnlineNum());
synchronized(session) {
this.session.getBasicRemote().sendText(getOnlineNum());
}
}
@OnClose
public void onClose(){
webSocketSet.remove(this);
subOnlineCount();
log.info("有链接关闭,当前人数为:{}",getOnlineNum());
}
@OnMessage
public void onMessage(String message,Session session) throws IOException {
log.info("来自客户端的消息:{}",message);
for (WebSocketService websocketService : webSocketSet) {
synchronized(websocketService.session) {
websocketService.session.getAsyncRemote().sendText(message);
}
}
}
public synchronized String getOnlineNum(){
return "当前在线人数:"+WebSocketService.online_num+"";
}
public synchronized int subOnlineCount(){
return WebSocketService.online_num--;
}
public synchronized int addOnlineCount(){
return WebSocketService.online_num++;
}
}
前端部分
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>WebSocket简单群聊</title>
</head>
<body>
WebSocket简单群聊 <button onclick="closeWebSocket()">关闭连接</button><br/> 输入你的昵称 <input id="name" type="text"/> <br>
<marquee>welcome</marquee>
<input id="text" type="text"/>
<button onclick="send()">发送消息</button>
<hr/>
<hr/>
<div id="message" style=" overflow:scroll; width:100vw; height:100vh;margin:auto;"></div>
</body>
<script type="text/javascript">
var websocket = null;
//判断当前浏览器是否支持WebSocket
if ('WebSocket' in window) {
//localhost改成自己IP网
websocket = new WebSocket("ws://127.0.0.1:9099/websocket");
}
else {
alert('当前浏览器 Not support websocket')
}
//连接发生错误的回调方法
websocket.onerror = function () {
setMessageInnerHTML("WebSocket连接发生错误");
};
//连接成功建立的回调方法
websocket.onopen = function () {
setMessageInnerHTML("WebSocket连接成功");
}
//接收到消息的回调方法
websocket.onmessage = function (event) {
setMessageInnerHTML(event.data);
}
//连接关闭的回调方法
websocket.onclose = function () {
setMessageInnerHTML("WebSocket连接关闭");
}
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {
closeWebSocket();
}
//将消息显示在网页上
function setMessageInnerHTML(innerHTML) {
document.getElementById('message').innerHTML += innerHTML + '<br/>';
}
//关闭WebSocket连接
function closeWebSocket() {
websocket.close();
}
//发送消息
function send() {
var message = document.getElementById('text').value;
var name = document.getElementById('name').value;
websocket.send(name+":"+message);
document.getElementById('text').value="";
}
</script>