WebSocket是一种网络传输协议,位于OSI模型的应用层。可在单个TCP连接上进行全双工通信,能更好的节省服务器资源和带宽并达到实时通讯。
客户端和服务端只需完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。
二、为什么使用WebSocket最主要的原因:解决了HTTP协议中不适合于实时通信的问题
在HTTP2.0出现以前,HTTP协议属于半双工协议,也就是说,在同一时刻数据只能单向流动,客户端向服务器发送请求,然后服务器响应请求。随着 Web 的发展,用户对于 Web 的实时推送要求也越来越高。为了能够及时获取服务器的变化,HTTP2.0新增了轮询、长轮询以及流化技术,提供了近乎实时的通信,但它们也涉及HTTP请求和响应首标,包含了许多附加和不必要的首标数据与延迟,增加了服务器的压力。
而WebSocket是独立的、创建在TCP上的协议,WebSocket链接一旦建立,即可进行双向的实时通信。同时,WebSocket协议与HTTP协议有良好的兼容性,默认端口也是80和443,握手阶段采用HTTP协议,因此能通过各种HTTP代理服务器。
三、WebSocket使用场景 1、单播(Unicast)单播是客户端与服务器之间的“一对一”的连接。是在一个单个的发送者和一个接收者之间通过进行的通信。应用于私信私聊等场景。
2、广播(Broadcast)广播是服务器与客户端“一对所有”的连接方式。广播意味着服务器向每一个成员都投递一份数据包,不论这些主机是否乐于接收该数据包。应用于发布游戏公告等场景。
3、组播(Multicast)组播是在服务端和客户端之间实现“一对一组”的连接方式。服务器可以向某些用户发送特定信息。应用于多人聊天室等场景。
四、Springboot集成WebSocket以广播为例,场景为游戏公告
1、前置准备- 开发工具:idea开发工具包:jdk1.8
1. 导入依赖
org.springframework.boot spring-boot-starter-websocketorg.webjars webjars-locatororg.webjars sockjs-client1.0.2 org.webjars stomp-websocket2.3.3 org.webjars bootstrap3.3.7 org.webjars jquery3.1.0
2. 新建软件包websocket
新建启动类Application.java
package websocket;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
System.out.println("启动成功");
}
}
3. 在websocket下新建软件包config
config包下新建类WebSocketConfig.java
package websocket.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/endpoint-websocket").setAllowedOrigins("*").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic", "/chat");
registry.setApplicationDestinationPrefixes("/app");
}
}
4. 在websocket下新建软件包controller
controller包下新建GameController,java
package websocket.controller;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
import websocket.entity.InMessage;
import websocket.entity.OutMessage;
@Controller
public class GameController {
@MessageMapping("/v1/chat")
@SendTo("/topic/game_chat")
public OutMessage gameInfo(InMessage message){
return new OutMessage(message.getContent());
}
}
5. 在websocket下新建软件包entity
entity包下新建InMessage.java
package websocket.entity;
import java.util.Date;
public class InMessage {
private String from;
private String to;
private String content;
private Date time;
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
}
entity包下新建OutMessage.java
package websocket.entity;
import java.util.Date;
public class OutMessage {
private String from;
private String content;
private Date time = new Date();
public OutMessage(){}
public OutMessage(String content){
this.content = content;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
}
3、前端代码
在resources下新建static.v1目录,在v1目录下:
1. 新建admin.html
Hello WebSocket
| 游戏公告内容 |
|---|
2. 新建index.html
Hello WebSocket
| 游戏公告内容 |
|---|
3. 新建app.js
var stompClient = null;
function setConnected(connected) {
$("#connect").prop("disabled", connected);
$("#disconnect").prop("disabled", !connected);
if (connected) {
$("#conversation").show();
}
else {
$("#conversation").hide();
}
$("#notice").html("");
}
function connect() {
var socket = new SockJS('/endpoint-websocket'); //连接上端点(基站)
stompClient = Stomp.over(socket); //用stom进行包装,规范协议
stompClient.connect({}, function (frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/topic/game_chat', function (result) {
console.info(result)
showContent(JSON.parse(result.body));
});
});
}
function disconnect() {
if (stompClient !== null) {
stompClient.disconnect();
}
setConnected(false);
console.log("Disconnected");
}
function sendName() {
stompClient.send("/app/v1/chat", {}, JSON.stringify({'content': $("#content").val()}));
}
function showContent(body) {
$("#notice").append("" + body.content + " "+new Date(body.time).toLocaleString()+" ");
}
$(function () {
$("form").on('submit', function (e) {
e.preventDefault();
});
$( "#connect" ).click(function() { connect(); });
$( "#disconnect" ).click(function() { disconnect(); });
$( "#send" ).click(function() { sendName(); });
});
4. 新建main.css
body {
background-color: #f5f5f5;
}
#main-content {
max-width: 940px;
padding: 2em 3em;
margin: 0 auto 20px;
background-color: #fff;
border: 1px solid #e5e5e5;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
五、测试
1、运行Application,在浏览器地址栏输入 localhost:8080/v1/admin.html,进入管理员界面
2、新建浏览器界面,在浏览器地址栏输入 localhost:8080/v1/index.html,进入用户界面
3、分别点击Connect按钮建立连接
4、管理员输入公告内容,点击发布后,用户收到实时信息!



