NIO(十)—— NIO的几个例子

1. FileChannel写入文件

package com.mycom.test.nio;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * FileChannel写入文件
 * 
 * @author guweiqiang
 */
public class TestFileChannelWrite {

	public static void main(String[] args) {
		try {
			// 新建一个File对象
			File file = new File("e:/writeData.txt");
			// 将文件读取到文件输出流中
			FileOutputStream outputStream = new FileOutputStream(file);
			// 获取FileChannel通道对象
			FileChannel fileChannel = outputStream.getChannel();
			// 新建缓冲区
			ByteBuffer buffer = ByteBuffer.allocate(1024);
			String testStr = "hello world!";
			// 将内容写入到缓冲区
			buffer.put(testStr.getBytes());
			buffer.flip(); //此处必须要调用buffer的flip方法
			// 将缓冲区内容写入到fileChannel通道
			fileChannel.write(buffer);
			// 关闭fileChannel通道
			fileChannel.close();
			// 关闭文件输出流
			outputStream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}		
	}

}

 

 

2. FileChannel读取文件

package com.mycom.test.nio;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * FileChannel读取文件
 * 
 * @author guweiqiang
 */
public class TestFileChannelRead {

	@SuppressWarnings("resource")
	public static void main(String[] args) {
		try {
			// 新建一个RandomAccessFile对象
			RandomAccessFile file = new RandomAccessFile("e:/readData.txt", "rw"); // rw表示以读写方式打开文件,r表示只读方式打开
			// 获取FileChannel通道对象
			FileChannel fileChannel = file.getChannel();
			// 新建缓冲区
			ByteBuffer buffer = ByteBuffer.allocate(1024);
			// 将fileChannel中的数据读取到buffer中
			fileChannel.read(buffer);
			// 再将buffer中的数据读取到String对象中
			byte[] data = buffer.array();
			String ss = new String(data).trim();
			System.out.println(ss);
			// 关闭fileChannel通道
			fileChannel.close();
		} catch (IOException e) {
			e.printStackTrace();
		}		
	}

}

 (前提是存在以下文件:e:/readData.txt

 

 

 3. Server与Cilent通信

NIO 服务端:

package com.mycom.test.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

/**
 * NIO 服务端
 * 
 * @author guweiqiang
 */
public class NIOServer {
	// 通道管理器
	private Selector selector;
	
	/**
	 * 获取一个服务端通道ServerSocket,并进行初始化
	 */
	public void initServer(int port) throws IOException{
		// 获取一个ServerSocket服务端通道
		ServerSocketChannel serverChannel = ServerSocketChannel.open();
		// 设置通道为非阻塞模式
		serverChannel.configureBlocking(false);
		// 绑定端口
		serverChannel.socket().bind(new InetSocketAddress(port));
		// 获取一个通道管理器
		this.selector = Selector.open();
		// 将通道管理器和通道进行绑定,并为该通道注册SelectionKey.OP_ACCEPT事件
		// 当事件到达时,selector.select()就会返回;如果事件没有到达,则selector.select()就会一直阻塞
		serverChannel.register(selector, SelectionKey.OP_ACCEPT);
	}
	
	/**
	 * 采用轮询的方式监听selector上是否有需要处理的事件,如果有则进行处理
	 */
	@SuppressWarnings("rawtypes")
	public void listen() throws IOException{
		System.out.println("服务端启动成功!");
		
		// 轮询访问selector
		while(true){
			// 当有已注册的事件到达时,方法返回,否则就一直阻塞到有注册的事件到达为止
			selector.select();
			
			// 获取selector中选中项的迭代器,选中项为注册的事件
			Iterator it = this.selector.selectedKeys().iterator();
			while(it.hasNext()){
				SelectionKey key = (SelectionKey)it.next();
				// 删除已选的key,防止重复处理
				it.remove();
				
				if(key.isAcceptable()){ // 有客户端请求连接的事件
					// 获取服务端通道
					ServerSocketChannel serverChannel = (ServerSocketChannel)key.channel();
					// 获取与客户端连接的通道
					SocketChannel clientChannel = serverChannel.accept();
					// 设置为非阻塞
					clientChannel.configureBlocking(false);
					// 给客户端发送消息
					clientChannel.write(ByteBuffer.wrap(new String("hello client, i'm server!").getBytes("utf-8")));
					// 在和客户端连接成功之后,为了可以接收到客户端的消息,需要给通道设置读权限
					clientChannel.register(this.selector, SelectionKey.OP_READ);
					
				} else if(key.isReadable()){ // 有读取事件发生
					readKey(key);
				}
			}
		}
	}

	/**
	 * 处理读取客户端发来的消息
	 */
	private void readKey(SelectionKey key) throws IOException {
		// 服务器可读取消息:得到事件发生的Socket通道 
		SocketChannel channel = (SocketChannel)key.channel();
		
		// 读取通道里的消息
		ByteBuffer buffer = ByteBuffer.allocate(1024);
		channel.read(buffer);
		byte[] data = buffer.array();
		String receivedMsg = new String(data).trim();
		System.out.println("服务端收到客户端发来的的消息:" + receivedMsg);
		
		// 向通道写入消息
		String sendMsg = "hello client!";
		ByteBuffer outBuffer = ByteBuffer.wrap(sendMsg.getBytes("utf-8")); 
		channel.write(outBuffer);// 将消息回送给客户端  
	}
	
	/**
	 * 启动服务端测试
	 */
	public static void main(String[] args) {
		try {
			NIOServer server = new NIOServer();
			server.initServer(8000);
			server.listen();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

 NIO 客户端:

package com.mycom.test.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

/**
 * NIO 客户端
 * 
 * @author guweiqiang
 */
public class NIOClient {
	// 通道管理器
	private Selector selector;
	
	/**
	 * 获取一个客户端通道,并进行初始化
	 * @throws IOException 
	 */
	public void initClient(String ip, int port) throws IOException{
		// 获取一个Socket客户端通道
		SocketChannel clientChannel = SocketChannel.open();
		// 设置通道为非阻塞模式
		clientChannel.configureBlocking(false);
		// 获取一个通道管理器
		this.selector = Selector.open();
		// 客户端连接服务器
		clientChannel.connect(new InetSocketAddress(ip, port));
		// 将通道管理器和通道进行绑定,并为该通道注册SelectionKey.OP_CONNECT事件
		clientChannel.register(selector, SelectionKey.OP_CONNECT);
	}

	/**
	 * 采用轮询的方式监听selector上是否有需要处理的事件,如果有则进行处理
	 */
	@SuppressWarnings("rawtypes")
	public void listen() throws IOException{
		// 轮询访问selector
		while(true){
			// 当有已注册的事件到达时,方法返回,否则就一直阻塞到有注册的事件到达为止
			selector.select();
			
			// 获取selector中选中项的迭代器,选中项为注册的事件
			Iterator it = this.selector.selectedKeys().iterator();
			while(it.hasNext()){
				SelectionKey key = (SelectionKey)it.next();
				// 删除已选的key,防止重复处理
				it.remove();
				
				if(key.isConnectable()){ // 有连接事件发生
					// 获取客户端通道
					SocketChannel clientChannel = (SocketChannel)key.channel();
					// 如果正在连接,则设置连接完成
					if(clientChannel.isConnectionPending()){
						clientChannel.finishConnect();
					}
					// 设置通道为非阻塞模式
					clientChannel.configureBlocking(false);
					// 给服务端发送消息
					clientChannel.write(ByteBuffer.wrap(new String("hello server, i'm client!").getBytes("utf-8")));
					// 在和服务端连接之后,为了可以接收到服务端的消息,需要给客户端设置读权限
					clientChannel.register(selector, SelectionKey.OP_READ);
					
				} else if(key.isReadable()){ // 有读取事件发生
					this.readKey(key);
				}
			}
		}
	}
	
	/**
	 * 处理读取服务端发来的消息
	 */
	private void readKey(SelectionKey key) throws IOException {
		// 服务器可读取消息:得到事件发生的Socket通道 
		SocketChannel channel = (SocketChannel)key.channel();
		
		// 读取通道里的消息
		ByteBuffer buffer = ByteBuffer.allocate(1024);
		channel.read(buffer);
		byte[] data = buffer.array();
		String receivedMsg = new String(data).trim();
		System.out.println("客户端收到服务端发来的消息:" + receivedMsg);
		
		// 向通道写入消息
		String sendMsg = "hello server!";
		ByteBuffer outBuffer = ByteBuffer.wrap(sendMsg.getBytes("utf-8")); 
		channel.write(outBuffer);// 将消息回送给服务端  
	}
	
	/**
	 * 启动客户端测试
	 */
	public static void main(String[] args) {
		try {
			NIOClient client = new NIOClient();
			client.initClient("127.0.0.1", 8000);
			client.listen();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

猜你喜欢

转载自guwq2014.iteye.com/blog/2221528
NIO