maven的依赖,我们如下:
- <dependencies>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.10</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty-all</artifactId>
- <version>4.0.21.Final</version>
- </dependency>
- </dependencies>
我们先写Netty器端的ChannelHandler,我们命名Netty的服务端的处理器为:HelloWorldServerHandler,继承于ChannelInboundHandlerAdapter,《Netty in Action》中介绍过,我们不需要使每一个inboundChannel继承于ChannelInboundHandler,这样会需要我们实现ChannelInboundHandler中的所有接口,在一般的channel中我们没有必要这样做,这样只会增加我们的额外的工作量,我们只需要继承ChannelInboundHandlerAdapter,继承它的适配就可以了,我们需要实现几个特别重要的方法,例如读取的方法channelRead和异常处理的方法exceptionCaught,源码如下:
- package com.lyncc.netty.hello;
-
- import io.netty.channel.ChannelHandlerContext;
- import io.netty.channel.ChannelInboundHandlerAdapter;
-
- public class HelloWorldServerHandler extends ChannelInboundHandlerAdapter{
-
-
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
- System.out.println("server channelRead..");
- System.out.println(ctx.channel().remoteAddress()+"->Server :"+ msg.toString());
- ctx.write("server write"+msg);
- ctx.flush();
- }
-
- @Override
- public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
- cause.printStackTrace();
- ctx.close();
- }
-
- }
接下来我们就要写Netty的服务器端了,书中写的很清楚,我们需要写一个ServerBootstrap,ServerBootstrap的写法是现在比较流行的流式编程法,我们需要指定它的transports,是NIO还是OIO,还需要指定端口号,最最重要的是安装server端的处理器,也就是我们之前写的HelloWorldServerHandler,还有一些Option的配置,这里只是用到,以后我们一起分析这些Option的作用,写server端还有一点需要注意,就是需要关闭连接,释放线程资源,源码如下:
- package com.lyncc.netty.hello;
-
- import io.netty.bootstrap.ServerBootstrap;
- import io.netty.channel.ChannelFuture;
- import io.netty.channel.ChannelInitializer;
- import io.netty.channel.ChannelOption;
- import io.netty.channel.EventLoopGroup;
- import io.netty.channel.nio.NioEventLoopGroup;
- import io.netty.channel.socket.SocketChannel;
- import io.netty.channel.socket.nio.NioServerSocketChannel;
- import io.netty.handler.codec.string.StringDecoder;
- import io.netty.handler.codec.string.StringEncoder;
-
- import java.net.InetSocketAddress;
-
- public class HelloWorldServer {
-
- private int port;
-
- public HelloWorldServer(int port) {
- this.port = port;
- }
-
- public void start(){
- EventLoopGroup bossGroup = new NioEventLoopGroup(1);
- EventLoopGroup workerGroup = new NioEventLoopGroup();
- try {
- ServerBootstrap sbs = new ServerBootstrap().group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port))
- .childHandler(new ChannelInitializer<SocketChannel>() {
-
- protected void initChannel(SocketChannel ch) throws Exception {
-
- ch.pipeline().addLast("decoder", new StringDecoder());
- ch.pipeline().addLast("encoder", new StringEncoder());
- ch.pipeline().addLast(new HelloWorldServerHandler());
- };
-
- }).option(ChannelOption.SO_BACKLOG, 128)
- .childOption(ChannelOption.SO_KEEPALIVE, true);
-
- ChannelFuture future = sbs.bind(port).sync();
-
- System.out.println("Server start listen at " + port );
- future.channel().closeFuture().sync();
- } catch (Exception e) {
- bossGroup.shutdownGracefully();
- workerGroup.shutdownGracefully();
- }
- }
-
- public static void main(String[] args) throws Exception {
- int port;
- if (args.length > 0) {
- port = Integer.parseInt(args[0]);
- } else {
- port = 8080;
- }
- new HelloWorldServer(port).start();
- }
- }
如法炮制,客户端的handler,我们依旧命名为HelloWorldClientHandler,也是继承于ChannelInboundHandlerAdapter
- package com.lyncc.netty.hello;
-
- import io.netty.channel.ChannelHandlerContext;
- import io.netty.channel.ChannelInboundHandlerAdapter;
-
- public class HelloWorldClientHandler extends ChannelInboundHandlerAdapter{
-
-
- @Override
- public void channelActive(ChannelHandlerContext ctx) {
- System.out.println("HelloWorldClientHandler Active");
- }
-
- @Override
- public void channelRead(ChannelHandlerContext ctx, Object msg) {
- System.out.println("HelloWorldClientHandler read Message:"+msg);
- }
-
-
- @Override
- public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
- cause.printStackTrace();
- ctx.close();
- }
-
- }
客户端我们需要写一个Bootstrap,也需要指定客户端的处理器,我们这里在客户端和服务器端都加了编码和解码两个String类型的译码器,这样的例子也算比较完整的hello world的例子了,完整的代码如下:
- package com.lyncc.netty.hello;
-
- import io.netty.bootstrap.Bootstrap;
- import io.netty.channel.ChannelFuture;
- import io.netty.channel.ChannelInitializer;
- import io.netty.channel.ChannelOption;
- import io.netty.channel.ChannelPipeline;
- import io.netty.channel.EventLoopGroup;
- import io.netty.channel.nio.NioEventLoopGroup;
- import io.netty.channel.socket.SocketChannel;
- import io.netty.channel.socket.nio.NioSocketChannel;
- import io.netty.handler.codec.string.StringDecoder;
- import io.netty.handler.codec.string.StringEncoder;
-
- public class HelloWorldClient {
-
- static final String HOST = System.getProperty("host", "127.0.0.1");
- static final int PORT = Integer.parseInt(System.getProperty("port", "8080"));
- static final int SIZE = Integer.parseInt(System.getProperty("size", "256"));
-
- public static void main(String[] args) throws Exception {
-
-
- EventLoopGroup group = new NioEventLoopGroup();
- try {
- Bootstrap b = new Bootstrap();
- b.group(group)
- .channel(NioSocketChannel.class)
- .option(ChannelOption.TCP_NODELAY, true)
- .handler(new ChannelInitializer<SocketChannel>() {
- @Override
- public void initChannel(SocketChannel ch) throws Exception {
- ChannelPipeline p = ch.pipeline();
- p.addLast("decoder", new StringDecoder());
- p.addLast("encoder", new StringEncoder());
- p.addLast(new HelloWorldClientHandler());
- }
- });
-
- ChannelFuture future = b.connect(HOST, PORT).sync();
- future.channel().writeAndFlush("Hello Netty Server ,I am a common client");
- future.channel().closeFuture().sync();
- } finally {
- group.shutdownGracefully();
- }
- }
-
- }
我们打开HelloWorldServer的代码,运行main函数,eclipse的控制台打印信息如下:

说明服务器已经成功运行,在8080端口监听了
我们再打开HelloWorldClient代码,同样运行main函数。控制台打印信息如下:

第一行是HelloWorldClientHandler该处理器的channelActive的方法打印的输出,第二行是channelRead方法的输出,这个输出是服务器端写入的,返回给客户端的
我们再回头看服务器端,此时服务器的HelloWorldServerHandler的channelRead的方法应该打印从客户端收到的信息了

好了,到此为止,Netty的服务器端和客户端就完全搭建完毕了,我们做到了客户端发送信息,服务器端接收且把收到的信息原样返回给客户端了