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("连接异常");
    }
}
相关文章
相关标签/搜索