Quickly build springboot websocket client

I. Introduction

WebSocket is a protocol provided by HTML5 for full-duplex communication on a single TCP connection.

The WebSocket protocol defined by HTML5 can better save server resources and bandwidth, and enable more real-time communication.

The WebSocket protocol defined by HTML5 can better save server resources and bandwidth, and enable more real-time communication.

The browser sends a request to the server to establish a WebSocket connection through JavaScript. After the connection is established, the client and the server can exchange data directly through the TCP connection.

2. Quickly build the server side of the springboot-websocket project

1 import dependencies

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>

2 Create a configuration class

@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

3 Create a WebSocketServer service class to receive data

The common annotations of websocket are only these 5

  • @ServerEndpoint pay attention to the context path, websocket connection address

  • @OnMessage will only be called when the websocket is loaded for the first time, and the life cycle is only once

  • @OnClose will only be called when the websocket connection is closed, and the life cycle is only once

  • Every time @OnMessage receives information, it will be called, and the call is more frequent

  • Called when an error occurs @OnError

/**
 * 类似RequestMapping的地址
 * ws://localhost:8080/ws/000001
 */
@ServerEndpoint("/ws/{uuid}")
@Component
public class WebSocketServer {

    private Session session; //客户端会话
    
    //存放每个客户端的连接会话
    public static ConcurrentHashMap<String,WebSocketServer> clients = new ConcurrentHashMap<>();
    
    //开启连接
    //存入连接回话中
    @OnOpen
    public void onOpen(Session session, @PathParam( "uuid") String uuid){
        System.out.println("当前的uuid为:"+uuid);
        this.session = session;
        clients.put(uuid,this);
    }

    //发送消息
    @OnMessage
    public void OnMessage(String msg, @PathParam( "uuid") String uuid){
        System.out.println("当前的uuid为:"+uuid);
        System.out.println("收到消息: "+msg);
    }

    //关闭连接
    @OnClose
    public void onClose(@PathParam( "uuid") String uuid){
        System.out.println("当前的uuid为:"+uuid);
        System.out.println("关闭socket连接"+uuid);
        clients.remove(uuid);
    }
    //发生异常的情况
    @OnError
    public void onError(Throwable error) {
        error.printStackTrace();
    }
    
}

4 Start the project

3. Generally, the front end is the client and the back end is the server.

Front-end client, I don’t know, I need Baidu myself, hahaha

4. Build java-websocket client

This case is just to tell you that you can use java to build a client

4.1 Dependencies

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.java-websocket</groupId>
            <artifactId>Java-WebSocket</artifactId>
            <version>1.3.5</version>
        </dependency>

4.2 Client code

@Component
public class WebSocketConfig {
 
    @Bean
    public WebSocketClient webSocketClient() {
        try {
                WebSocketClient webSocketClient = new WebSocketClient(new URI("ws://localhost:8081/ws/000001"),new Draft_6455()) {
                @Override
                public void onOpen(ServerHandshake handshakedata) {
                    System.out.println("ws 连接成功");
                }
 
                @Override
                public void onMessage(String message) {
                    System.out.println("ws 收到消息"+message);
 
                }
 
                @Override
                public void onClose(int code, String reason, boolean remote) {
                    System.out.println("ws 退出");
                }
 
                @Override
                public void onError(Exception ex) {
                    System.out.println("连接错误"+ex.getMessage());
                }
            };
            webSocketClient.connect();
            return webSocketClient;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
 
}

4.3 Code for sending messages

@SpringBootApplication
@RestController
public class SpringbootWebsocketClientApplication {


    @Autowired
    private WebSocketClient webSocketClient;

    public static void main(String[] args) {
        SpringApplication.run(SpringbootWebsocketClientApplication.class, args);
    }


    @RequestMapping("/get")
    public String send(){
        webSocketClient.send("我是ws客户端,你好!!!");
        return "发送成功";
    }

}

4.4 Results

4.5 The server receives the message

当前的uuid为:000001
收到消息: 我是ws客户端,你好!!!

5. Websocket transmits header information, the front - end and back-end solutions of the protocol header token

  1. js websocket pass token

The websocket protocol borrows the HTTP protocol during the handshake phase, but there is no way to modify the request header in the JavaScript websocket API.

1.1 Based on the protocol header

The websocket request header can contain the attribute Sec-WebSocket-Protocol , which is a custom sub-protocol. It is sent from client to server and back from server to client acknowledgment sub-protocol. We can use this property to add tokens.

var token='fasdfadfasdfa'

var  ws = new WebSocket("ws://" + url+ "/webSocketServer",[token]);
  1. Take out the parameters of the websocket protocol header in the background

2.1 Take out the token

token = ((HttpServletRequest) servletRequest).getHeader("Sec-WebSocket-Protocol");

2.2 Pay attention to big pits

If the token parameter is passed, the token response must also be included when the backend responds! Otherwise, the front end cannot receive the data!

You can use servlet filters to do it

@Order(1)
@Component
@WebFilter(filterName = "WebsocketFilter", urlPatterns = "/home/*")
public class WebsocketFilter implements Filter {
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        String token = ((HttpServletRequest) servletRequest).getHeader("Sec-WebSocket-Protocol");

        response.setHeader("Sec-WebSocket-Protocol",token);

        filterChain.doFilter(servletRequest, servletResponse);
    }
 
    @Override
    public void destroy() {
 
    }
}

6. End

websocket最伟大之处在于服务器和客户端可以在给定的时间范围内的任意时刻,相互推送信息。 浏览器和服务器只需要要做一个握手的动作,在建立连接之后,服务器可以主动传送数据给客户端,客户端也可以随时向服务器发送数据。

第一、WebSocket是HTML5中的协议,支持持久连接;而Http协议不支持持久连接。

第二、首先,Websocket是一个持久化的协议,相对于HTTP这种非持久的协议来说

HTTP的生命周期通过 Request 来界定,也就是一个 Request 一个 Response ,那么在 HTTP1.0 中,这次HTTP请求就结束了。

在HTTP1.1中进行了改进,使得有一个keep-alive,也就是说,在一个HTTP连接中,可以发送多个Request,接收多个Response。但是请记住 Request = Response , 在HTTP中永远是这样,也就是说一个request只能有一个response。而且这个response也是被动的,不能主动发起。

第三、传统的http请求,其并发能力都是依赖同时发起多个TCP连接访问服务器实现的(因此并发数受限于浏览器允许的并发连接数),而websocket则允许我们在一条ws连接上同时并发多个请求,即在A请求发出后A响应还未到达,就可以继续发出B请求。由于TCP的慢启动特性(新连接速度上来是需要时间的),以及连接本身的握手损耗,都使得websocket协议的这一特性有很大的效率提升。

第四、http协议的头部太大,且每个请求携带的几百上千字节的头部大部分是重复的,很多时候可能响应都远没有请求中的header空间大。如此多无效的内容传递是因为无法利用上一条请求内容,websocket则因为复用长连接而没有这一问题。

第五、当需要实现客户端刷新消息时,传统方案往往通过定时ajax请求实现,实际上对多数用户多数时间下这些请求都是无意义了,并且非常占用资源,websocket资源占用就小很多

Guess you like

Origin blog.csdn.net/qq_39706515/article/details/130064394