Java调用WebSocket的服务端和客户端

服务端实现

原生注解

  • 导入依赖文件
  • 需要一个配置类
  • 一个Server类
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-websocket</artifactId>
 </dependency>

// 配置类
@Configuration
@EnableWebSocket
public class WSConfig {

    @Bean
    public ServerEndpointExporter serverEndpoint() {
        return new ServerEndpointExporter();
    }
}
 
// Server 类
@ServerEndpoint("/ws")
@Component
public class WsServerEndpoint {

    @OnOpen
    public void onOpen(Session session) {
        System.out.println("链接成功");
    }

    @OnClose
    public void onClose(Session session) {
        System.out.println("链接关闭");
    }

    @OnMessage
    public void onMessage(Session session, String text) throws IOException {
        System.out.println("收到消息:" + text);
        session.getBasicRemote().sendText("hello world");
    }
}

Spring封装中导入WebSocket

  • 导入依赖
  • 创建 handler
  • 创建 interceptor
  • 创建 配置类
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
// handler 类

package com.go.WebSocketDemo;

import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;

/**
 * @author husky
 * @data 2022/7/11
 * @filename WebSocketHandler
 */
@Component
public class MyWebSocketHandler implements WebSocketHandler {

    /**
     * 建立连接
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        // 缓存用户信息: userInfo
        System.out.println("hello  user");
    }

    /**
     * 接收消息
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {


    }

    /**
     * 发生错误
     * @param session
     * @param exception
     * @throws Exception
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {


        // 清除用户缓存信息
    }

    /**
     * 关闭连接
     * @param session
     * @param closeStatus
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {


        // 清除用户缓存信息
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
}

// interceptor

package com.go.WebSocketDemo;

import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;

import java.util.Map;

/**
 * @author husky
 * @data 2022/7/11
 * @filename MyWebSocketInterceptors
 */
@Component
public class MyWebSocketInterceptors implements HandshakeInterceptor {
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        // TODO
        System.out.println("hello hands");
        /*
        处可以做一些处理,例如校验连接中的参数,保存连接用户信息等,
        用户信息等有用信息可存储在 Map<String, Object> attributes 中,
        在 handler 中可使用 WebSocketSession.getAttributes() 方法取出相应的数据。

         */

        返回 false 会导致连接失败
        return true; // [1]
    }

    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {

    }
}

// 配置类
package com.go.WebSocketDemo.Config;

import com.go.WebSocketDemo.MyWebSocketHandler;
import com.go.WebSocketDemo.MyWebSocketInterceptors;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

import javax.annotation.Resource;
import javax.websocket.server.ServerEndpoint;
import java.nio.channels.ServerSocketChannel;

/**
 * @author husky
 * @data 2022/7/8
 * @filename WebSocketConfig
 *
 * websocket 的配置类
 *
 */

@Configuration
@EnableWebSocket
// @Service
public class WebSocketConfig implements WebSocketConfigurer {

    // @Bean
    // public ServerEndpointExporter serverEndpointExporter() {
    //     return new ServerEndpointExporter();
    // }
    @Resource
    // MyWebSocketHandler defaultHandler;
    WebSocketHandler defaultHandler;
    @Resource
    MyWebSocketInterceptors defaultInterceptors;

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        System.out.println("hello  work");
        registry
                .addHandler(defaultHandler, "ws") // todo  [2]
                .addInterceptors(defaultInterceptors) // todo  [3]
                .setAllowedOrigins("*"); // 解决跨域问题 [4]
    }
}




客户端实现

  • 导入依赖
  • 创建 client
  • 建立链接
<dependency>
    <groupId>org.java-websocket</groupId>
    <artifactId>Java-WebSocket</artifactId>
    <version>1.5.3</version>
</dependency>
package com.go.client;

import java.net.URI;
// import com.alibaba.fastjson.JSONObject;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *  websocket客户端监听类
 * @author 。
 */
public class BaseWebsocketClient extends WebSocketClient {

    private static Logger logger = LoggerFactory.getLogger(BaseWebsocketClient.class);

    public BaseWebsocketClient(URI serverUri) {
        super(serverUri);
    }

    @Override
    public void onOpen(ServerHandshake serverHandshake) {
        logger.info(">>>>>>>>>>>websocket open");

    }

    @Override
    public void onMessage(String s) {
        logger.info(">>>>>>>>>> websocket message");
        System.out.println(s);

    }

    @Override
    public void onClose(int i, String s, boolean b) {
        logger.info(">>>>>>>>>>>websocket close");
    }

    @Override
    public void onError(Exception e) {
        logger.error(">>>>>>>>>websocket error {}",e);
    }


}
public class main {
    public static void main(String[] args) {
        try {
            BaseWebsocketClient myClient = new BaseWebsocketClient(new URI("ws://127.0.0.1:8080/ws"));
            myClient.connect();
            while (!myClient.getReadyState().equals(ReadyState.OPEN)) {
                System.out.println("连接中。。。");
                Thread.sleep(1000);
            }
            // 连接成功往websocket服务端发送数据
            JSONObject object = new JSONObject();
            object.put("message", "success连接");
            myClient.send("是我啊");
            System.out.println("...");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • 3
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
在SpringBoot项目中,可以使用Spring WebSocket模块来实现websocket服务端。在接收到客户端发送的Sec-WebSocket-Key后,服务端需要经过一系列的处理才能返回Sec-WebSocket-Accept。 以下是一个示例代码: ```java import org.springframework.stereotype.Component; import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.AbstractWebSocketHandler; import org.springframework.web.socket.server.HandshakeInterceptor; import org.springframework.web.socket.server.support.DefaultHandshakeHandler; import javax.websocket.server.ServerEndpointConfig; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Base64; import java.util.Map; @Component public class WebSocketConfig extends AbstractWebSocketHandler { // 服务端接收到客户端发送的Sec-WebSocket-Key后,需要经过一系列的处理才能返回Sec-WebSocket-Accept @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { String key = session.getAttributes().get("key").toString(); String secWebSocketAccept = generateSecWebSocketAccept(key); session.sendMessage(new TextMessage(secWebSocketAccept)); } // 生成Sec-WebSocket-Accept的方法 private String generateSecWebSocketAccept(String key) { String guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; String keyConcat = key + guid; try { MessageDigest md = MessageDigest.getInstance("SHA-1"); md.update(keyConcat.getBytes()); byte[] byteDigest = md.digest(); byte[] accept = Base64.getEncoder().encode(byteDigest); return new String(accept, "UTF-8"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return null; } } // 配置WebSocket @Configuration @EnableWebSocket public class WebSocketConfig extends WebSocketConfigurer { @Autowired private WebSocketConfig webSocketHandler; @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(webSocketHandler, "/ws").addInterceptors(new HandshakeInterceptor() { @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { String key = request.getHeaders().get("Sec-WebSocket-Key").get(0); attributes.put("key", key); return true; } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) { } }).setHandshakeHandler(new DefaultHandshakeHandler() { @Override protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map<String, Object> attributes) { return new WebSocketPrincipal(); } }); } } ``` 在上述代码中,`WebSocketConfig`类继承自`AbstractWebSocketHandler`,并且实现了`afterConnectionEstablished`方法,该方法会在websocket连接建立后自动被调用。在该方法中,可以获取到客户端发送的Sec-WebSocket-Key,并且调用`generateSecWebSocketAccept`方法生成Sec-WebSocket-Accept并返回给客户端。 `generateSecWebSocketAccept`方法的实现中,需要将Sec-WebSocket-Key与一个GUID进行拼接,然后使用SHA-1算法进行加密,并使用Base64编码后返回,具体的实现可以参考上述代码。 在`WebSocketConfig`类中,还需要注册WebSocket处理器,并且添加一个握手拦截器,在握手拦截器中可以获取到客户端发送的Sec-WebSocket-Key,并将其保存到attributes中,以便在`afterConnectionEstablished`方法中使用。同时,在握手拦截器中需要返回true,表示握手成功。 至此,客户端发送Sec-WebSocket-Key后,服务端可以返回Sec-WebSocket-Accept了。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值