java实现websocket server/client

最近在项目中有一个场景,在内网的应用需要接受外网应用的指令。有两种解决方案:

1.内网应用轮询外网应用,http请求指令

2.内网应用与外网应用之间建立websocket长连接

记录一下websocket server/client的java实现

一、websocket server

@Configuration
public class WebSocketConfig extends Configurator
{
    /**
     * 日志
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketConfig.class);

    /**
     * 首先要注入ServerEndpointExporter,这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint。
     * 要注意,如果使用独立的servlet容器,而不是直接使用springboot的内置容器,就不要注入ServerEndpointExporter,因为它将由容器自己提供和管理。
     *
     * @return ServerEndpointExporter
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter()
    {
        return new ServerEndpointExporter();
    }

    @Override
    public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request,
                                HandshakeResponse response)
    {
        /* 如果没有监听器,那么这里获取到的HttpSession是null */
        StandardSessionFacade ssf = (StandardSessionFacade)request.getHttpSession();
        if (ssf != null)
        {
            HttpSession httpSession = (HttpSession)request.getHttpSession();
            // 关键操作
            sec.getUserProperties().put("sessionId", httpSession.getId());
            LOGGER.debug("获取到的SessionID:" + httpSession.getId());
        }
    }

}
@Component
@ServerEndpoint(value = "/ws/{userId}")
public class WebSocketServer
{
    /**
     * 日志
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketServer.class);

    // 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;

    // concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
    private static ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();

    // 保存允许建立连接的id
    private static List<String> idList = Lists.newArrayList();

    private String id = "";

    // 与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;

    /**
     * <关闭连接>
     *
     * @param userId userId
     * @throws
     */
    public void closeConn(String userId)
    {
        // 关闭连接
        try
        {
            WebSocketServer socket = webSocketMap.get(userId);
            if (null != socket)
            {
                if (socket.session.isOpen())
                {
                    socket.session.close();
                }
            }
        }
        catch (IOException e)
        {
            LOGGER.error("error, cause: ", e);
        }
        webSocketMap.remove(userId);
        idList.remove(userId);
    }

    /**
     * <连接/注册时去重>
     *
     * @param userId userId
     * @throws
     */
    public void conn(String userId)
    {
        // 去重
        if (!idList.contains(userId))
        {
            idList.add(userId);
        }
    }

    /**
     * <获取注册在websocket进行连接的id>
     *
     * @return 结果
     * @throws
     */
    public static List<String> getIdList()
    {
        return idList;
    }

    /**
     * <初始化方法>
     *
     * @throws
     */
    @PostConstruct
    public void init()
    {
        try
        {
            /**
             * TODO 这里的设计是在项目启动时从DB或者缓存中获取注册了允许建立连接的id
             */
            // TODO 初始化时将刚注入的对象进行静态保存

        }
        catch (Exception e)
        {
            // TODO 项目启动错误信息
            LOGGER.error("error, cause: ", e);
        }
    }
你可以使用 JavaWebSocketClient 类来实现 WebSocket 客户端。下面是一个简单的示例代码: ```java import java.net.URI; import java.net.http.HttpClient; import java.net.http.WebSocket; import java.util.concurrent.CompletionStage;import java.util.concurrent.CompletableFuture; public class WebSocketClient { public static void main(String[] args) { HttpClient client = HttpClient.newHttpClient(); WebSocket webSocket = client.newWebSocketBuilder() .buildAsync(URI.create("ws://localhost:8080/ws"), new WebSocketListener()) .join(); // 发送消息到服务器 webSocket.sendText("Hello, Server!", true); // 关闭 WebSocket 连接 webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "Client is closing connection"); } } class WebSocketListener implements WebSocket.Listener { @Override public void onOpen(WebSocket webSocket) { System.out.println("Connected to the server"); } @Override public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) { System.out.println("Received message from server: " + data); return CompletableFuture.completedFuture(null); } @Override public CompletionStage<?> onClose(WebSocket webSocket, int statusCode, String reason) { System.out.println("Disconnected from the server: " + reason); return CompletableFuture.completedFuture(null); } @Override public void onError(WebSocket webSocket, Throwable error) { System.err.println("An error occurred: " + error.getMessage()); } } ``` 在上面的示例中,我们使用 Java 11 引入的 `java.net.http` 包中的 `HttpClient` 和 `WebSocket` 类。首先,我们创建一个 `HttpClient` 对象,并使用 `newWebSocketBuilder()` 方法创建一个 WebSocket 客户端。通过传入服务器的 URI 和一个实现了 `WebSocket.Listener` 接口的自定义监听器对象,我们可以异步地建立 WebSocket 连接。然后,我们可以使用 `sendText()` 方法向服务器发送文本消息,并使用 `sendClose()` 方法关闭 WebSocket 连接。 在自定义监听器中,我们实现了几个回调方法:`onOpen()` 在连接建立时调用,`onText()` 在接收到服务器发送的文本消息时调用,`onClose()` 在连接关闭时调用,`onError()` 在发生错误时调用。在这些方法中,我们可以编写自己的逻辑来处理不同的事件。 请注意,以上代码仅为一个基本示例,实际应用中可能需要根据具体需求进行修改和完善。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值