Netty创建TCP服务端

本文详细介绍了如何使用Netty框架创建TCP服务器,包括创建EventLoopGroup、配置ServerBootstrap、建立ChannelInitializer以及启动服务的过程。示例代码展示了HelloServerHandler如何处理客户端数据并返回响应。
摘要由CSDN通过智能技术生成
服务端

Netty的服务器其中之一便是TCP服务器。想要创建TCP服务器你必须:

  • 创建一个EventLoopGroup
  • 创建和配置ServerBootstrap
  • 创建一个ChannelInitializer
  • 启动服务器

下面是一个完整的使用Netty创建TCP服务器的代码例子:

EventLoopGroup group = new NioEventLoopGroup();

try{
    ServerBootstrap serverBootstrap = new ServerBootstrap();
    serverBootstrap.group(group);
    serverBootstrap.channel(NioServerSocketChannel.class);
    serverBootstrap.localAddress(new InetSocketAddress("localhost", 9999));

    serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
        protected void initChannel(SocketChannel socketChannel) throws Exception {
            socketChannel.pipeline().addLast(new HelloServerHandler());
        }
    });
    ChannelFuture channelFuture = serverBootstrap.bind().sync();
    channelFuture.channel().closeFuture().sync();
} catch(Exception e){
    e.printStackTrace();
} finally {
    group.shutdownGracefully().sync();
}

上面代码中的过程被分解为更小的步骤,并在接下来的部分中单独描述。

创建EventLoopGroup

创建Netty TCP服务端的第一步是创建EventLoopGroup。因为我们的例子中使用了Java NIO,所以我们创建了NioEventLoopGroup。下面是创建EventLoopGroupde的代码:

EventLoopGroup group = new NioEventLoopGroup();
创建和配置ServerBootstrap

创建Netty TCP服务端的第二部是创建并配置ServerBootstrap。下面是相关代码:

ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(group);
serverBootstrap.channel(NioServerSocketChannel.class);
serverBootstrap.localAddress(new InetSocketAddress("localhost", 9999));

第一步是创建一个ServerBootstrap实例。

第二步是将EventLoopGroup设置到ServerBootstrap实例中。

第三步是将NioServerSocketChannel类的实例设置到ServerBootstrap实例中。这是非常必要的,因为例子中使用NioEventLoopGroup。

第四步是将本地IP地址或者域名和TCP端口号设置到ServerBootstrap实例中。用于Netty服务器的启动。

创建ChannelInitializer

第三步引导Netty TCP服务器是创建ChannelInitializer并将它附加到ServerBootstrap实例中。ChannelInitializer所有的TCP入站的socket连接。

创建并添加ChannelInitializer如下代码:

serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        socketChannel.pipeline().addLast(new HelloServerHandler());
    }
});

Netty的ChannelInitializer类是一个抽象类。每当TCP服务器接受新的TCP连接时,它的方法initChannel()被调用。正如你所看到的,它会添加一个新的HelloServerHandler(一个ChannelHandler)到每个新的SocketChannel中。也可能在所有新的SocketChannel实例中重用相同的ChannelHandler,而不是这里每次都要创建一个新的。

正如你所看见的,ServerBootstrap使用childHandler()方法将ChannelInitializer添加到ServerBootstrap中。

启动服务

引导一个Netty TCP服务器的最后一步就是启动服务器了。下面的代码完成了TCP服务器的启动:

ChannelFuture channelFuture = serverBootstrap.bind().sync();

serverBootstrap.bind()方法返回一个ChannelFuture,可以用于知道服务器绑定的完成(绑定到本地地址和TCP端口)。通过调用ChannelFuture的sync()方法,主线程在继续操作之前,会创建一个直到服务器启动的等待。顺便说一下,sync()方法同样会返回一个ChannelFuture。

HelloServerHandler

HelloServerHandler通过ChannelInitializer被添加到每个SocketChannel中,它是用来处理从客户端接受到的数据的组件。下面是HelloServerHandler的示例代码:

public class HelloServerHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf inBuffer = (ByteBuf) msg;

        String received = inBuffer.toString(CharsetUtil.UTF_8);
        System.out.println("Server received: " + received);

        ctx.write(Unpooled.copiedBuffer("Hello " + received, CharsetUtil.UTF_8));
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)
                .addListener(ChannelFutureListener.CLOSE);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}

每当从SocketChannel接收到数据时,就会调用channelRead()方法。正如你在代码中所看到的,每当客户端向服务端发送数据,channelRead()方法都会返回带有"Hello+"的响应。

当没有更多数据从SocketChannel读取数据时,调用channelReadComplete()方法。

如果在接收或发送来自SocketChannel的数据时抛出异常,则调用exceptionCaught()方法。在这里,您可以决定应该发生什么,比如关闭连接,或者响应错误代码等等。

原文链接:http://tutorials.jenkov.com/netty/netty-tcp-server.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值