关于Websocket
Websocket的基本概念
Websocket是一个“应用层协议”,和HTTP地位是对等的。都是基于传输层的TCP实现的一个广泛被使用的应用层协议。这个协议可以实现服务器主动给客户端推送数据这样的功能。
websocket报文格式
简单了解一下Websocket的报文格式:
FIN表示是否要关闭websocket。在应用层要通过Websocket的FIN来触发TCP的FIN。与TCP的FIN是两码事。
RSV保留位:三个保留位。现在还不用,以后可能有用。
opcode操作码:描述了当前这个websocket数据帧,是起到啥作用的。比如取值为0x1表示是个文本数据,取值为0x2表示是个二进制数据。
MASK表示是否开启掩码操作。掩码操作主要是为了避免“缓冲区溢出”。
payload length:就是载荷。也就是数据报上要携带的具体数据。
payload length 有三种模式:
1)7 bit 2)16bit 3)64bit
最初的7bit的payload length < 126,此时是模式1。如果7bit的值是126,此时是模式2,16bit生效。如果7bit的值是127,此时是模式3,64个bit生效了。
websocket的握手过程
在浏览器与服务器开始建立连接的时候,还是先发送HTTP请求,这个HTTP请求中会带有一些特殊的header。connection:表示连接升级。即将应用层协议升级成websocket。服务器会返回一个响应,响应中带有是否同意升级的header。
后续websocket连接就建立好了,接下来就使用websocket进行数据传输了。
注:HTTP响应中的状态码101,表示”协议切换“。“websocket是基于HTTP协议来实现的”这种说法是错误的。
基于Websocket编写代码
在Java中有两种方式来使用websocket:
1.使用tomcat提供的原生websocket api。
2.使用Spring提供的websocket api.
接下来基于Spring的websocket api编写代码:
首先要在pom.xml文件中引入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
接下来编写服务器代码:
1)创建一个类作为WebSocketHandler
@Component
public class TestWebSocketAPI extends TextWebSocketHandler {
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
//这个方法会在webscoket连接建立之后,被自动调用
System.out.println("TestAPI 连接成功");
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
//这个方法是在websocket收到消息的时候,被自动调用的
System.out.println("TestAPI 收到消息:" +message.toString());
//session是个会话,里面就记录了通信双方是谁.(session中就持有了websocket的通信连接)
session.sendMessage(message);
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
//这个方法是在连接出现异常的时候,被自动调用的
System.out.println("TestAPI 连接异常");
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
//这个方法是在连接正常关闭后,被自动调用的
System.out.println("TestAPI 连接关闭");
}
继承TextWebSocketHandler后,就可以重写一些方法.
2)把上述类的实例,注册到spring里面,配置路由
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Autowired
private TestWebSocketAPI testWebSocketAPI;
@Autowired
private WebSocketController webSocketController;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
//通过这个方法,把刚才创建好的Hanlder类给注册到具体的路径上
//此时当浏览器,websocket的请求路径是"/test" 的时候,就会调用到TestWebSocketAPI这个类里的方法
//registry.addHandler(testWebSocketAPI,"/test");
registry.addHandler(webSocketController,"/WebSocketMessage")
//通过注册这个特定的http拦截器,就可以把用户给HttpSession中添加的Attribute键值对
//往WebSocketSession 里也添加一份
.addInterceptors(new HttpSessionHandshakeInterceptor());
}
}
客户端的代码编写:
//编写js使用websocket的代码
//创建一个websocket示例
let websocket = new Websocket("ws://127.0.0.1:8080/test");
//给这个websocket注册上一些回调函数
websocket.onopen = function(){
//连接建立完成后,就会自动执行案例
console.log("websocket 连接成功");
}
websocket.onclose = function(){
//连接断开后,自动执行到
console.log("websocket 连接断开");
}
websocket.onerror = function(){
//连接异常时,自动执行到
console.log("websocket 连接异常");
}
websocket.onmessage = function(e){
//收到消息时,自动执行到
console.log("websocket 收到消息" + e.data);
}
let messageInput = document.querySelector('#message');
let sendButton = document.querySelector('#send-button');
sendButton.onclick = function(){
console.log("websocket 发送消息" + messageInput.value);
websocket.send(messageInput.value);
}
以上,关于Websocket,希望对你有所帮助。