Netty-入门AIO编程

本文介绍了使用Java NIO2.0的异步I/O (AIO) 编程模型来实现时间服务器与客户端的通信过程。文章详细展示了AIO的原理,并提供了完整的服务器端和客户端代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在介绍Netty编程之前, 我们不得不限介绍一下Unix系统下的事件驱动IO模型;在JDK1.7之后出现的NIO2.0也引入了这个异步非阻塞通道,他不需要通过多路复用器对注册通道进行轮询操作即可实现异步读写,从而简化了NIO的编程模型;NIO2.0提供的异步的套接字通道是真正的异步I/O,在异步I/O操作的时候可以传递信号变量,当操作完成之后回调相关的方法。

 

异步I/O也被称作AIO。

 

 

下面介绍一下AIO程序,类图如下:

 

 

 

源码:

 

package com.techstar.aio;

public class AIOTimeServer {

	
	public static void main(String[] args) {
		
		
		int port = 8081;
		
		new Thread(new AsyncTimeServerHandler(port), "AsyncTimeServerHandler---001").start();
	}
}

 

package com.techstar.aio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.util.concurrent.CountDownLatch;

public class AsyncTimeServerHandler implements Runnable {

	
	private int port;
	
	CountDownLatch latch;
	AsynchronousServerSocketChannel asyncServerSocketChannel = null;
	
	
	
	public AsyncTimeServerHandler(int port) {
		this.port = port;
		try {
			this.asyncServerSocketChannel = AsynchronousServerSocketChannel.open();
			this.asyncServerSocketChannel.bind(new InetSocketAddress(this.port));
			System.out.println("The time server  is started! the port is " + this.port);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}



	@Override
	public void run() {
		
		latch = new CountDownLatch(1);
		this.doAccept();
		
		try {
			latch.await();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	private void doAccept() {
		this.asyncServerSocketChannel.accept(this, new AcceptCompletionHandler());
	}

}

 

package com.techstar.aio;

import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;

public class AcceptCompletionHandler implements CompletionHandler<AsynchronousSocketChannel, AsyncTimeServerHandler> {

	@Override
	public void completed(AsynchronousSocketChannel result, AsyncTimeServerHandler attachment) {
		attachment.asyncServerSocketChannel.accept(attachment, this);
		ByteBuffer buffer = ByteBuffer.allocate(1024);
		result.read(buffer, buffer, new ReadCompletionHandler(result));
	}

	@Override
	public void failed(Throwable exc, AsyncTimeServerHandler attachment) {
		exc.printStackTrace();
		attachment.latch.countDown();
	}

}

 

package com.techstar.aio;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.Date;

public class ReadCompletionHandler implements CompletionHandler<Integer, ByteBuffer> {

	private AsynchronousSocketChannel channel;
	
	
	public ReadCompletionHandler(AsynchronousSocketChannel channel) {
		super();
		if (this.channel == null)
			this.channel = channel;
	}

	@Override
	public void completed(Integer result, ByteBuffer attachment) {

		try {
			attachment.flip();
			byte[] body = new byte[attachment.remaining()];
			attachment.get(body);
			String order = new String(body, "UTF-8");
			System.out.println("the client request Order = " + order );
			
			String currentTime = "QUERY TIME ORDER".equals(order)?new Date(System.currentTimeMillis()).toString() : "BAD ORDER";
			
			this.doWrite(currentTime);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	@Override
	public void failed(Throwable exc, ByteBuffer attachment) {
		try {
			channel.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	

	private void doWrite(String response) {
		if (response != null && response.trim().length() > 0) {
			byte[] msg = response.getBytes();
			
			ByteBuffer writeBuffer = ByteBuffer.allocate(msg.length);
			writeBuffer.put(msg);
			writeBuffer.flip();
			channel.write(writeBuffer, writeBuffer, new CompletionHandler<Integer, ByteBuffer>() {

				@Override
				public void completed(Integer result, ByteBuffer attachment) {
					if (attachment.hasRemaining()) {
						channel.write(attachment, attachment, this);
					}
				}

				@Override
				public void failed(Throwable exc, ByteBuffer attachment) {
					try {
						channel.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
					
				}
			});
		}
	}

}

 

 

 

 

 

 

客户端代码

package com.techstar.aio;

public class AIOTimeClient {

	
	public static void main(String[] args) {
		int port = 8081;
		
		new Thread(new AsyncTimeClientHandler(port, "127.0.0.1"), "AsyncTimeClientHandler--001").start();;
	}
}

 

package com.techstar.aio;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.CountDownLatch;

public class AsyncTimeClientHandler implements CompletionHandler<Void, AsyncTimeClientHandler>, Runnable {

	private int port;

	private String host;

	private AsynchronousSocketChannel channel;

	private CountDownLatch latch;

	public AsyncTimeClientHandler(int port, String host) {
		this.port = port;
		this.host = host;

		try {
			channel = AsynchronousSocketChannel.open();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void run() {
		this.latch = new CountDownLatch(1);

		this.channel.connect(new InetSocketAddress(this.host, port), this, this);
		System.out.println("connect to the server。。。");
		try {
			this.latch.await();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		try {
			this.channel.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void completed(Void result, AsyncTimeClientHandler attachment) {
		byte[] order = "QUERY TIME ORDER".getBytes();
		this.doCompleted(order);
	}

	@Override
	public void failed(Throwable exc, AsyncTimeClientHandler attachment) {
		try {
			this.channel.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	private void doCompleted(byte[] msg) {

		ByteBuffer writeBuffer = ByteBuffer.allocate(msg.length);
		writeBuffer.put(msg);
		writeBuffer.flip();
		channel.write(writeBuffer, writeBuffer, new CompletionHandler<Integer, ByteBuffer>() {

			@Override
			public void completed(Integer result, ByteBuffer attachment) {
				if (attachment.hasRemaining()) {
					try {
						System.out.println("发送消息指令:" + new String(msg, "UTF-8"));
					} catch (UnsupportedEncodingException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					channel.write(attachment, attachment, this);
				} else {
					ByteBuffer readBuffer = ByteBuffer.allocate(1024);
					channel.read(readBuffer, readBuffer, new CompletionHandler<Integer, ByteBuffer>() {

						@Override
						public void completed(Integer result, ByteBuffer attachment) {
							attachment.flip();
							byte[] body = new byte[attachment.remaining()];
							
							attachment.get(body);
							String time;
							try {
								time = new String(body, "UTF-8");
								System.out.println("Now is:" + time);
								latch.countDown();
							} catch (UnsupportedEncodingException e) {
								e.printStackTrace();
							}
						}

						@Override
						public void failed(Throwable exc, ByteBuffer attachment) {
							try {
								channel.close();
							} catch (IOException e) {
								e.printStackTrace();
							}
						}
						
					});
				}
			}

			@Override
			public void failed(Throwable exc, ByteBuffer attachment) {
				try {
					channel.close();
				} catch (IOException e) {
					e.printStackTrace();
				}

			}
		});
	}

}

 

### Netty-all 和 Netty-buffer 的差异及其应用场景 #### 1. Netty-all 组件概述 `netty-all` 是一个聚合模块,包含了整个 Netty 框架所需的所有功能组件。该模块旨在提供一种简便的方式引入完整的 Netty 功能集到项目中,使得开发者无需单独管理多个依赖项。<groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>x.x.x.Final</version> </dependency> ``` #### 2. Netty-buffer 特定作用域分析 相比之下,`netty-buffer` 则专注于处理字节缓冲区的操作。它提供了高效的内存管理和数据传输机制,支持堆外内存(Direct Memory),这有助于减少垃圾回收压力并提高性能表现,在高并发场景下尤为重要。此外还实现了多种优化策略来增强读写效率,比如复合缓冲区 CompositeByteBuf 能够有效降低复制成本[^1]。 ```java // 创建一个新的 ByteBuf 实例 ByteBuf buffer = Unpooled.buffer(1024); try { // 向 Buffer 中写入一些数据 String message = "Hello, world!"; byte[] bytes = message.getBytes(CharsetUtil.UTF_8); buffer.writeBytes(bytes); // 将 Buffer 数据转换成字符串形式输出 System.out.println(buffer.toString(CharsetUtil.UTF_8)); } finally { // 使用完毕后释放资源 buffer.release(); } ``` #### 3. 应用场景对比 当应用程序只需要特定部分的功能时,可以选择只导入 `netty-buffer` 或其他单个子模块以减小程序体积;而如果需要全面运用 Netty 提供的各种网络通信能力,则推荐采用 `netty-all` 来简化构建配置过程。另外值得注意的是,虽然两者都可以用于开发基于异步I/O模式的服务端程序,但在实际部署过程中应当依据具体的业务需求和技术栈选型做出合理决策[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值