Netty学习——Netty简单的服务器客户端通信

                Netty简单的服务器客户端通信


        Netty是一个基于Java NIO的异常网络通信框架。Netty充分利用了Java NIO异常的特点,减少了线程资源的消耗,并且还对缓冲做了复用,大大节约了内存。无论是方便、轻量还是安全方面,Netty在Java网络编程框架中都是首屈一指的,基于Netty进行二次开发网络应用相当的方便,无数的个人企业应用已经证实了这一点。  
       下面是最经典的服务器客户端通信实例:
package study.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
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;

public class NettyEchoServer {
	public static void main(String[] args) {
		EventLoopGroup bossGroup = new NioEventLoopGroup();
		EventLoopGroup workerGroup = new NioEventLoopGroup();
		ServerBootstrap bootstrap = new ServerBootstrap();
		bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
				.option(ChannelOption.SO_BACKLOG, 1024).childHandler(new ChildChannelHandler());
		ChannelFuture future = bootstrap.bind(8888);
		try {
			future.channel().closeFuture().sync();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			bossGroup.shutdownGracefully();
			workerGroup.shutdownGracefully();
		}
	}

	private static class EchoChannelHandler extends ChannelHandlerAdapter {

		@Override
		public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
			ByteBuf buffer = (ByteBuf) msg;
			byte[] bts = new byte[buffer.readableBytes()];
			buffer.readBytes(bts);
			String str = new String(bts, "utf-8");
			System.out.println("server receive:" + str);
		}

		@Override
		public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
			ctx.flush();
		}

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

	}

	private static class ChildChannelHandler extends ChannelInitializer<SocketChannel> {

		@Override
		protected void initChannel(SocketChannel ch) throws Exception {
			ch.pipeline().addLast(new EchoChannelHandler());
		}

	}
}
package study.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
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.NioSocketChannel;

public class NettyEchoClient {
	public static void main(String[] args) {
		EventLoopGroup group = new NioEventLoopGroup();
		Bootstrap bootstrap = new Bootstrap();
		bootstrap.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true)
				.handler(new ChannelInitializer<SocketChannel>() {

					@Override
					protected void initChannel(SocketChannel ch) throws Exception {
						ch.pipeline().addLast(new EchoClientHandler());
					}
				});
		ChannelFuture future = bootstrap.connect("localhost", 8888);
		try {
			future.channel().closeFuture().sync();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			group.shutdownGracefully();
		}

	}

	private static class EchoClientHandler extends ChannelHandlerAdapter {
		private ByteBuf msgBuf;

		public EchoClientHandler() {
			byte[] msgBts = "please connect".getBytes();
			msgBuf = Unpooled.buffer(msgBts.length);
			msgBuf.writeBytes(msgBts);
		}

		public void channelActive(ChannelHandlerContext ctx) throws Exception {
			ctx.writeAndFlush(msgBuf);
		}

		@Override
		public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

		}
	}
}
       在NettyEchoServer的main方法中,首先创建了两个EventLoopGroup,然后创建一个服务器起动器ServerBootstrap,注册channel的类型是NioServerSocketChannel,NioServerSocketChannel就相当于NIO中的ServerSocketChannel,然后将ServerBootstrap绑定到端口8888,获取Channel的closeFuture,调用同步方法,这里主线程就阻塞在这里,而后台线程就开始监听连接。在前面还将ServerBootstrap的childHandler设置成一个ChildChannelHandler对象,ChildChannelHandler实际上就是一个Channel的初始化器,也就相当于如果有一个连接到来,就会创建一个SocketChannel,Channel初始化器就会对这个SocketChannel进行处理。在这个Channel初始化器的初始化方法中,调用了ch.pipeline().addLast(new EchoChannelHandler())方法,这里其实是给这个连接的SocketChannel的处理队列中添加一个处理器,也就是代码中的pipeLine,在这个pipeLine的末尾添加,这样,当SocketChannel有事件发生时,就可以回调处理器的响应方法了。这就是Netty基于事件回调的机制。然后EchoChannelHandler继承于ChannelHandlerAdapter,重写了channelRead,channelReadComplete以及exceptionCaught方法,channelRead就是SocketChannel的读事件回调,这样,就可以在读事件回调方法中写相应逻辑了,上面的代码中是直接把Buffer中的数据读取出来并打印到控制器。
      客户端的代码也类似,创建一个EventLoopGroup,然后创建一个客户端的启动器,启动器注册NioSocketChannel,然后注册初始化器,这个初始化器就是当连接到服务器时就会产生一个SocketChannel,在初始化方法中,给这个SocketChannel的处理队列中添加处理器,这个处理器也相当于一个监听器,监听到SocketChannel的事件。在处理器中的channelActive方法中,这个方法表示连接完成,上面的代码是向代码器写了一个字符串,服务器就可以在SocketChannel的处理器的channelRead回调方法中得到这个字符串。
     由于Netty把NIO封装得很方便,所以上面的代码看起来非常简洁,这也是为什么Netty这么受欢迎的一部分原因。方便简洁与高效是一个框架的根本。用Nety可以很方便的实现一些网络业务功能,可以用Netty二次开发一个通信协议,更加一步可以实现一个服务器程序。Netty把Java NIO封装得我们可以不去关注网络异步通信的低层实现,而去关心我们要实现的业务功能。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值