netty的简介
Netty是基于Java NIO的网络应用框架.
Netty是一个NIOclient-server(客户端服务器)框架,使用Netty可以快速开发网络应用,
例如服务器和客户端协议。Netty提供了一种新的方式来使开发网络应用程序,这种新的
方式使得它很容易使用和有很强的扩展性。Netty的内部实现时很复杂的,但是Netty提
供了简单易用的api从网络处理代码中解耦业务逻辑。Netty是完全基于NIO实现的,所以
整个Netty都是异步的。
网络应用程序通常需要有较高的可扩展性,无论是Netty还是其他的基于Java NIO的框
架,都会提供可扩展性的解决方案。Netty中一个关键组成部分是它的异步特性.
客户端
1,客户端启动类
public class NettyClientImpl {
private final String ip;
private final int port;
public NettyClientImpl(String ip, int port) {
this.ip = ip;
this.port = port;
}
public static void main(String[] args) throws InterruptedException {
new NettyClientImpl("127.0.0.1", 20207).netClientStart();
}
public void netClientStart() throws InterruptedException {
//可以理解为一个线程池,用来处理连接,接收数据和发送数据
EventLoopGroup elg = null;
try {
elg = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();//客户端引导类
bootstrap.group(elg)
.channel(NioSocketChannel.class)//指定通道类型为NioSocketChannel,一种异步模式
.remoteAddress(ip,port)//设置客户端发送请求的ip和端口号
.handler(new ChannelInitializer<SocketChannel>() {//业务处理类
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
/**设置执行流程,可以有多个inboundhandler和outboundhandler;
* 执行时inboundhandler按添加顺序执行,outboundhandler按添加的反顺序执行
* 添加时,最后一个添加的不能是outboundhandler
*/
socketChannel.pipeline().addLast(new ClientHandler());//注册handler
}
});
//连接服务器,sync():一直连接,直到连接成功
ChannelFuture future = bootstrap.connect().sync();
// future.channel().writeAndFlush(new Object()).sync();//可以用来发送数据
//直到获取到返回结果后才关闭
future.channel().closeFuture().sync();
} finally {
//直到所有工作完成后,关闭连接
elg.shutdownGracefully().sync();
}
}
}
2,客户端执行流程类
public class ClientHandler extends SimpleChannelInboundHandler {
//客户端连接服务器后被调用
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("向服务端发送数据..........");
Person person = new Person("可达鸭","man",2);
//数据传输必须是字节数组,需要进行编码、解码才可以获取到实际的数据
byte[] bytes = ObjectToByteUtils.objectToBytes(person);//通过ObjectOutputStream将数据编码
ByteBuf byteBuf = Unpooled.copiedBuffer(bytes);
//发送数据
ctx.write(byteBuf);
ctx.flush();
}
//接收到服务端返回的数据后被调用
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
//读取服务端返回数据
ByteBuf byteBuf = (ByteBuf) o;
byte[] bytes = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(bytes);
Person person = (Person) ObjectToByteUtils.bytesToObject(bytes);//通过ObjectInputStream将数据解码
System.out.println(person);
}
//出现异常被调用
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
}
}
服务端
1,服务端启动类
public class NettyServerImpl {
private final int port;
public NettyServerImpl(int port) {
this.port = port;
}
public static void main(String[] args) throws InterruptedException {
new NettyServerImpl(20207).netServerStart();
}
public void netServerStart() throws InterruptedException {
//相当于一个线程池,用来处理连接,发送数据和处理数据
EventLoopGroup elg = null;
try{
elg = new NioEventLoopGroup();
//服务端引导类
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(elg)//多线程处理
.channel(NioServerSocketChannel.class)//指定服务端通道类型
.localAddress("localhost",port)//设置监听的ip和端口
.childHandler(new ChannelInitializer<Channel>() {//业务处理
@Override
protected void initChannel(Channel channel) throws Exception {
channel.pipeline().addLast(new ServerHandlerImpl());//设置执行流程
}
});
//绑定服务器,直到完成绑定,调用sync()会阻塞,
ChannelFuture future = serverBootstrap.bind().sync();
System.out.println("开始监听,监听端口为...."+future.channel().localAddress());
future.channel().closeFuture().sync();//直到拿到结果后才关闭
}finally {
elg.shutdownGracefully().sync();
}
}
}
2,服务端执行流程类
public class ServerHandlerImpl extends SimpleChannelInboundHandler {
//接收到客户端发送的数据时调用
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
//读取客户端传过来的数据
ByteBuf byteBuf = (ByteBuf) o;
byte[] bytes = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(bytes);
Person person = (Person) ObjectToByteUtils.bytesToObject(bytes);//通过ObjectInputStream将数据解码
System.out.println(person);
}
//服务端处理完成数据时调用
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
//服务端向客户端发送数据
Person person = new Person("槑の少年","man",23);
byte[] bytes = ObjectToByteUtils.objectToBytes(person);
ByteBuf byteBuf = Unpooled.copiedBuffer(bytes);
//发送数据
ctx.write(byteBuf);
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
}
}