关于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文件中引入依赖:

XML 复制代码
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-websocket</artifactId>
 </dependency>

接下来编写服务器代码:

1)创建一个类作为WebSocketHandler

java 复制代码
@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里面,配置路由

java 复制代码
@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());

    }
}

客户端的代码编写:

javascript 复制代码
//编写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,希望对你有所帮助。

相关推荐
精明的身影12 分钟前
网络计划WebApp求解:融合Python与AI决策的项目管理系统
网络·python·web app
姚不倒1 小时前
F5 SSL Profile 证书卸载深入篇
运维·网络协议·负载均衡·ssl·f5
Let's Chat Coding1 小时前
对称密钥认证:主机和设备共享同一把密钥
运维·服务器·网络
技术不好的崎鸣同学4 小时前
[极客大挑战 2019]EasySQL 思路及解法
网络·安全·web安全
Web极客码4 小时前
跨国网络抖动下的 AI 爬虫流调优:我如何用 Claude 打造“智能退避”资讯清洗管道
网络·人工智能·爬虫
念何架构之路5 小时前
moby-http-api-server
网络·网络协议·http
namexingyun5 小时前
Scaling Law bug实战启示:从“虚胖“到“精瘦“的算力效率革命
开发语言·网络·人工智能·bug·ai编程
阿拉斯攀登5 小时前
NAT 穿透详解:STUN / TURN / ICE
运维·服务器·网络·webrtc·nat
云栖梦泽在5 小时前
原生 IP、机房 IP、住宅 IP、广播 IP 有何不同?从网络身份到 ASN 识别的技术科普
网络·网络协议·tcp/ip·性能优化
宠友信息5 小时前
资源权限与钱包流水在即时通讯源码后端架构中的设计
java·spring boot·redis·websocket·缓存