netty 搭建 ssl websocket 服務器,使用 protobuf 通訊

被 Apple_Sa 的栗子坑的不行,決定本身寫個教程以供將來的本身參考

證書

從阿里雲申請證書獲得以下幾個文件java

clipboard.png

須要先用 openssl.pfx 轉成 .keynode

openssl pkcs12 -in server.pfx -nocerts -nodes -out server.key

提示須要輸入密碼,密碼在 pfx-password.txt 文件裏。
最終須要 2149826361xxxx.pem 文件和 server.key 文件服務器

netty服務器

Server.javaapp

File file = new File("2149826361xxxx.pem");
File key = new File("server.key");
try {
    SslContext sslCtx = SslContextBuilder.forServer(file, key).build();
    open(sslCtx);
} catch (SSLException e) {
    e.printStackTrace();
}
private void open(SslContext sslCtx) {
    EventLoopGroup bossGroup = new NioEventLoopGroup();
    EventLoopGroup workerGroup = new NioEventLoopGroup();
    try {
        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new Initializer(sslCtx))
                .option(ChannelOption.SO_BACKLOG, 1024)
                .childOption(ChannelOption.SO_KEEPALIVE, true);

        ChannelFuture ch = b.bind(port).sync();
        ch.channel().closeFuture().sync();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}

Initializer.javaide

public class Initializer extends ChannelInitializer<NioSocketChannel> {
    private final SslContext sslCtx;
    public Initializer (SslContext sslCtx) {
        this.sslCtx = sslCtx;
    }
    protected void initChannel(NioSocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast(sslCtx.newHandler(ch.alloc()));
        pipeline.addLast(new HttpServerCodec());
        pipeline.addLast(new HttpObjectAggregator(65536));
        pipeline.addLast(new ChunkedWriteHandler());
        pipeline.addLast(new WebSocketServerCompressionHandler());
        pipeline.addLast(new WebSocketServerProtocolHandler("/chat", null, true, 1024 * 10));
        pipeline.addLast(new MessageToMessageDecoder<WebSocketFrame>() {
            @Override
            protected void decode(ChannelHandlerContext ctx, WebSocketFrame frame, List<Object> objs) throws Exception {
                ByteBuf buf = frame.content();
                objs.add(buf);
                buf.retain();
            }
        });
        pipeline.addLast(new MessageToMessageEncoder<MessageLiteOrBuilder>() {
            @Override
            protected void encode(ChannelHandlerContext ctx, MessageLiteOrBuilder msg, List<Object> out) throws Exception {
                ByteBuf result = null;
                if (msg instanceof MessageLite) {
                    result = wrappedBuffer(((MessageLite) msg).toByteArray());
                }
                if (msg instanceof MessageLite.Builder) {
                    result = wrappedBuffer(((MessageLite.Builder) msg).build().toByteArray());
                }
                WebSocketFrame frame = new BinaryWebSocketFrame(result);
                out.add(frame);
            }
        });
        pipeline.addLast(new ProtobufDecoder(ReqPB.PBdata.getDefaultInstance()));
        pipeline.addLast(new ProtoHandler());
    }
}

ProtoHandler.javaoop

public class ProtoHandler extends SimpleChannelInboundHandler<ReqPB.PBdata> {
    private static Logger log = Logger.getLogger(ProtoHandler.class);

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ReqPB.PBdata msg) {
        log.info("收到消息:" + msg);
    }
    
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("斷開連接");
        super.channelInactive(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
       log.info("連接異常");
    }
}
相關文章
相關標籤/搜索