WebSocket入门,java中如何使用WebSocket

WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需完成一次握手,两者之间就可以直接创建持久性的连接,并进行双向数据传输。

WebSocket定义

WebSocket是独立的,创建在TCP上的协议。

WebSocket通过HTTP/1.1协议的101状态码进行握手

为了创建WebSocket连接,需要通过浏览器发出请求,之后服务器进行回应,这个过程称为"握手"

基于浏览器定时发送请求,然后由服务器返回最新的数据给客户端浏览器,这种传统模式,需要浏览器不断发送请求,HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,这样会浪费很多的带宽资源。在这种情况下,HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时的通讯。

WebSocket优缺点

不支持无连接: WebSocket 是一种持久化的协议,这意味着连接不会在一次请求之后立即断开。这是有利的,因为它消除了建立连接的开销,但是也可能导致一些资源泄漏的问题。 不支持广泛: WebSocket 是 HTML5 中的一种标准协议,虽然现代浏览器都支持,但是一些旧的浏览器可能不支持 WebSocket。 需要特殊的服务器支持: WebSocket 需要服务端支持,只有特定的服务器才能够实现 WebSocket 协议。这可能会增加系统的复杂性和部署的难度。 数据流不兼容: WebSocket 的数据流格式与 HTTP 不同,这意味着在不同的网络环境下,WebSocket 的表现可能会有所不同。

原文链接:WebSocket(看这一篇就够了)-优快云博客

WebSocket通信流程

1.浏览器发起http请求,,请求建立webSocket连接

2.服务器响应同意协议更改

3.相互发送数据

Java实现WebSocket的方式

基于注解实现

  • 引入SpringBoot中webSocket的启动器

  • 编写配置类,注入ServerEndpointExporter组件

  • 创建服务端消息监听类 并使用@ServerEndPoint标识类,标识这是一个webSocket的服务点

  • @OnOpen连接成功

  • @OnClose连接关闭

  • @OnMessage收到消息状态

@ServerEndpoint("/wsServer")
@Slf4j
@Component
public class WsServer {
​
    private static Map<String,Session> sessionMap=new HashMap<>();
    //客户端连接服务端时触发
    @OnOpen
    public void onOpen(Session session){
        log.debug("客户端连接服务端...");
        sessionMap.put(session.getId(),session);
    }
​
    //客户端向服务端发送消息时触发
    public String onMessage(String text){
        log.debug("接收到客户端消息+"+text);
        return  text;
    }
​
    //客户端发送关闭连接时触发
    @OnClose
    public void onClose(Session session){
        log.debug("客户端关闭连接");
        sessionMap.remove(session.getId());
    }
​
    //服务端主动发送消息
    @Scheduled(fixedRate = 2000)
    public void sendMsg() throws IOException {
        //向所有连接的客户端发送消息
        Set<Map.Entry<String, Session>> entries = sessionMap.entrySet();
        for (Map.Entry<String, Session> entry : entries) {
            entry.getValue().getBasicRemote().sendText("hello webSocket");
        }
    }
}

基于spring提供的接口和类实现

  • 和注解方式一样,需要引入webSocket的启动器

  • 编写webSocket服务断点类,继承Spring提供的AbstractWebSocketHandler抽象类,重写其中的方法。

    @Component
    @Slf4j
    public class WebSocketListener extends AbstractWebSocketHandler {
        private Map<String, WebSocketSession> sessionMap=new HashMap<>();
    ​
        //连接建立后触发
        @Override
        public void afterConnectionEstablished(WebSocketSession session) throws Exception {
    ​
            super.afterConnectionEstablished(session);
            log.debug(session.getId()+":连接建立成功");
            sessionMap.put(session.getId(), session);
        }
    ​
        //接收消息后触发
        @Override
        protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
            super.handleTextMessage(session, message);
            log.debug("收到"+session.getId()+"发送的消息,消息内容:"+message.getPayload());
        }
    ​
        //连接关闭后触发
        @Override
        public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
            super.afterConnectionClosed(session, status);
            log.debug("关闭连接...");
            if(session.isOpen()){
                sessionMap.remove(session.getId());
            }
        }
    ​
        //服务端主动发送消息
        @Scheduled(fixedRate = 2000)
        public void sendMsg() throws IOException {
            //向所有连接的客户端发送消息
            log.debug("客户端发送消息");
            Set<Map.Entry<String, WebSocketSession>> entries = sessionMap.entrySet();
            for (Map.Entry<String, WebSocketSession> entry : entries) {
                entry.getValue().sendMessage(new TextMessage("hello websocket"));
            }
        }
    }
  • 自定义拦截器类继承自spring提供的HttpSessionHandshakeInteceptor抽象类,添加握手前后的操作

@Component
@Slf4j
public class MyInteceptorHandler extends HttpSessionHandshakeInterceptor {
​
    //握手前
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        log.debug("握手前...");
        return super.beforeHandshake(request, response, wsHandler, attributes);
    }
​
    //握手后
    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {
        log.debug("握手后");
        super.afterHandshake(request, response, wsHandler, ex);
    }
}

  • 编写配置类实现自WebSocketConfigure接口,注册上面自定义实现类。

@Configuration
@EnableWebSocket
public class MyWebSocketConfigure implements WebSocketConfigurer {
​
    @Autowired
    private WebSocketListener webSocketListener;
​
    @Autowired
    private  MyInteceptorHandler inteceptorHandler;
​
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(webSocketListener,"/webSocket2")
                .addInterceptors(inteceptorHandler)
                .setAllowedOrigins("*");
    }
}

WebSocket常见应用场景

1.弹幕:每个客户端发送消息到服务器,由服务器统一整理后发回客户端

2.消息实时提醒:后端主动推送新的变动至客户端

3.聊天功能

4.在线游戏

所有和客户端需要实时获取服务端数据时的场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值