基于Netty实现安全认证的WebSocket(wss)客户端

1.Netty服务端

服务端代码参考【基于Netty实现安全认证的WebSocket(wss)服务端-CSDN博客

2.Netty客户端

客户端代码参考【基于Netty实现WebSocket客户端-CSDN博客】中两种都可以;这里用的是第一种。

新增SslHandler的代码:

java 复制代码
SslContext sslCtx = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();
...
pipeline.addLast(sslCtx.newHandler(sc.alloc(), webSocketURL.getHost(), webSocketURL.getPort()));

服务端地址的协议头调整为wss

java 复制代码
final URI webSocketURL = new URI("wss://127.0.0.1:7070/helloWs");

完整的客户端代码如下:

java 复制代码
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
import io.netty.handler.codec.http.websocketx.WebSocketClientProtocolHandler;
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import io.netty.handler.stream.ChunkedWriteHandler;
import lombok.extern.slf4j.Slf4j;

import java.net.URI;
import java.util.concurrent.CountDownLatch;

/**
 * https://blog.csdn.net/a1053765496/article/details/130701218
 * 基于Netty快速实现WebSocket客户端,不手动处理握手
 */
@Slf4j
public class SimpleWssClient {

    final CountDownLatch latch = new CountDownLatch(1);

    public static void main(String[] args) throws Exception {
        SimpleWssClient client = new SimpleWssClient();
        client.test();
    }

    public void test() throws Exception {
        Channel dest = dest();
        latch.await();
        dest.writeAndFlush(new TextWebSocketFrame("CountDownLatch完成后发送的消息"));
    }

    public Channel dest() throws Exception {
        final URI webSocketURL = new URI("wss://127.0.0.1:7070/helloWs");

        EventLoopGroup group = new NioEventLoopGroup();
        SslContext sslCtx = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();
        Bootstrap boot = new Bootstrap();
        boot.option(ChannelOption.SO_KEEPALIVE, true)
            .option(ChannelOption.TCP_NODELAY, true)
            .group(group)
            .handler(new LoggingHandler(LogLevel.INFO))
            .channel(NioSocketChannel.class)
            .handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel sc) throws Exception {
                    ChannelPipeline pipeline = sc.pipeline();
                    pipeline.addLast(sslCtx.newHandler(sc.alloc(), webSocketURL.getHost(), webSocketURL.getPort()));
                    pipeline.addLast(new HttpClientCodec());
                    pipeline.addLast(new ChunkedWriteHandler());
                    pipeline.addLast(new HttpObjectAggregator(64 * 1024));
                    pipeline.addLast(new WebSocketClientProtocolHandler(WebSocketClientHandshakerFactory
                        .newHandshaker(webSocketURL, WebSocketVersion.V13, null, false, new DefaultHttpHeaders())));
                    pipeline.addLast(new SimpleChannelInboundHandler<TextWebSocketFrame>() {

                        @Override
                        protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg)
                            throws Exception {
                            System.err.println(" 客户端收到消息======== " + msg.text());
                        }

                        @Override
                        public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
                            if (WebSocketClientProtocolHandler.ClientHandshakeStateEvent.HANDSHAKE_COMPLETE
                                .equals(evt)) {
                                log.info(ctx.channel().id().asShortText() + " 握手完成!");
                                latch.countDown();
                                send(ctx.channel());
                            }
                            super.userEventTriggered(ctx, evt);
                        }
                    });

                }
            });

        ChannelFuture cf = boot.connect(webSocketURL.getHost(), webSocketURL.getPort()).sync();

        return cf.channel();
    }

    public static void send(Channel channel) {
        final String textMsg = "握手完成后直接发送的消息";

        if (channel != null && channel.isActive()) {
            TextWebSocketFrame frame = new TextWebSocketFrame(textMsg);
            channel.writeAndFlush(frame).addListener((ChannelFutureListener) channelFuture -> {
                if (channelFuture.isDone() && channelFuture.isSuccess()) {
                    log.info("     ================= 发送成功.");
                } else {
                    channelFuture.channel().close();
                    log.info("     ================= 发送失败. cause = " + channelFuture.cause());
                    channelFuture.cause().printStackTrace();
                }
            });
        } else {
            log.error("消息发送失败! textMsg = " + textMsg);
        }
    }

}

参考:利用netty开发webScoketClient(支持wss协议,客户端、服务端心跳实现)_websocketclient-CSDN博客

相关推荐
异常君2 小时前
Netty Reactor 线程模型详解:构建高性能网络应用的关键
java·后端·netty
次元4 小时前
初识Netty的奇经八脉
netty
南客先生8 小时前
马架构的Netty、MQTT、CoAP面试之旅
java·mqtt·面试·netty·coap
异常君3 天前
一文吃透 Netty 处理粘包拆包的核心原理与实践
java·后端·netty
猫吻鱼4 天前
【Netty4核心原理】【全系列文章目录】
netty
用户90555842148055 天前
AdaptiveRecvByteBuAllocator 源码分析
netty
菜菜的后端私房菜6 天前
深入剖析 Netty 中的 NioEventLoopGroup:架构与实现
java·后端·netty
码熔burning9 天前
【Netty篇】Channel 详解
netty·nio·channel
Pitayafruit16 天前
📌 Java 工程师进阶必备:Spring Boot 3 + Netty 构建高并发即时通讯服务
spring boot·后端·netty
猫吻鱼18 天前
【Netty4核心原理④】【简单实现 Tomcat 和 RPC框架功能】
netty