首页 > 代码库 > Java网络编程-Nio 实例代码

Java网络编程-Nio 实例代码


  IO NIO 区别请看 : http://blog.csdn.net/jiangtao_st/article/details/38041479


一、基于Nio的 Server ,过程略复杂,但是无疑这样的效率高;代码中得注释比较详细,请看注释说明

package com.zhuoxuan.net.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
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;
import java.util.Random;
import java.util.Set;

/**
 * 
 * <p>
 * 	基于nio的Server
 * </p>
 * 
 * @author 卓轩
 * @创建时间:2014年7月7日
 * @version: V1.0
 */
public class NioServer {
	
	private final int port = 8787;
	private final int BLOCK_SIZE = 4096;
	
	private Selector selector;
	
	private ByteBuffer receiveBuffer = ByteBuffer.allocate(BLOCK_SIZE);
	private ByteBuffer sendBuffer = ByteBuffer.allocate(BLOCK_SIZE);
	
	
	

	//构造函数
	public NioServer() throws IOException {
		//打开服务器套接字通道 
		ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
		//服务器配置为非阻塞模式
		serverSocketChannel.configureBlocking(false);
		//获取与通道关联的 ServerSocket对象
		ServerSocket serverSocket = serverSocketChannel.socket();
		//绑定端口
		serverSocket.bind(new InetSocketAddress(port));
		//打开一个选择器
		selector = Selector.open();
		//注册到selector上,等待连接
		serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
		
		System.out.println("Server:init successfuly.");
	}
	
	/**
	 * 监听端口
	 */
	private void linstenr() throws Exception{
		
		while (true) {
			//选择一组键
			selector.select();
			//返回获取选择的键集
			Set<SelectionKey> selectionKeys = selector.selectedKeys();
			if(selectionKeys.isEmpty()){
				continue;
			}
			//遍历,循环处理请求的键集
			Iterator<SelectionKey> iterator =  selectionKeys.iterator();
			while (iterator.hasNext()) {
				SelectionKey selectionKey = (SelectionKey) iterator.next();
				iterator.remove();
				handlerKey(selectionKey);
			}
			
			Thread.sleep(4000);
		}
		
	}
	
	/**
	 * 处理对应的  SelectionKey
	 * @param selectionKey
	 */
	private void handlerKey(SelectionKey selectionKey) throws IOException{
		
		ServerSocketChannel server;
		SocketChannel client;
		
		// 测试此键的通道是否已准备好接受新的套接字连接
		if(selectionKey.isAcceptable()){
			//此键对应的关联通道
			server = (ServerSocketChannel)selectionKey.channel();
			//接受到此通道套接字的连接
			client = server.accept();
			//配置为非阻塞
			client.configureBlocking(false);
			//注册到selector 等待连接
			client.register(selector, SelectionKey.OP_READ);
			
		}
		
		else if (selectionKey.isReadable()) {
		
			client = (SocketChannel)selectionKey.channel();
			//将缓冲区清空,下面读取
			receiveBuffer.clear();
			//将客户端发送来的数据读取到 buffer中
			int count = client.read(receiveBuffer);
			if(count >0){
				String receiveMessage = new String(receiveBuffer.array(),0,count);
				System.out.println("Server:接受客户端的数据:" + receiveMessage);
				client.register(selector, SelectionKey.OP_WRITE);
			}
		}
		
		else if (selectionKey.isWritable()) {
			//发送消息buffer 清空
			sendBuffer.clear();
			//返回该键对应的通道
			client = (SocketChannel)selectionKey.channel();
			String sendMessage = "Send form Server...Hello... "+new Random().nextInt(100)+" .";
			//向缓冲区中写入数据
			sendBuffer.put(sendMessage.getBytes());
			//put了数据,标志位被改变
			sendBuffer.flip();
			//数据输出到通道
			client.write(sendBuffer);
			System.out.println("Server:服务器向客户端发送数据:" + sendMessage);
			client.register(selector, SelectionKey.OP_READ);
		}
		
		
	}
	
	
	public static void main(String[] args) {
		
		try {
			
			NioServer nioServer = new NioServer();
			nioServer.linstenr();
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
	}
	

}


二、Nio Client 实例

package com.zhuoxuan.net.nio;

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;
import java.util.Set;

/**
 * 
 * <p>
 *   nio client
 * </p>
 * 
 * @author 卓轩
 * @创建时间:2014年7月7日
 * @version: V1.0
 */
public class NioClient {

	private static final int BLOCK_SIZE = 4096;
	
	private static ByteBuffer sendBuffer = ByteBuffer.allocate(BLOCK_SIZE);
	
	private static ByteBuffer receiveBuffer = ByteBuffer.allocate(BLOCK_SIZE);
	
	private static final  InetSocketAddress SERVER_ADDRESS = new InetSocketAddress("127.0.0.1",8787);
	
	
	public static void main(String[] args) {
		
		try {
			//打开socket通道
			SocketChannel socketChannel = SocketChannel.open();
			//设置为非阻塞模式
			socketChannel.configureBlocking(false);
			//打开选择器
			Selector selector = Selector.open();
			//向selector 选择器注册此通道
			socketChannel.register(selector, SelectionKey.OP_CONNECT);
			//链接
			socketChannel.connect(SERVER_ADDRESS);
			
			SocketChannel client;
			while (true) {
				//选择一组键
				selector.select();
				//返回此选择器的已选择键集
				Set<SelectionKey> selectionKeys = selector.selectedKeys();
				Iterator<SelectionKey> iterator = selectionKeys.iterator();
				//遍历对应的 SelectionKey 处理
				while (iterator.hasNext()) {
					SelectionKey selectionKey = (SelectionKey) iterator.next();
					//判断此键的通道是否已完成其套接字连接操作
					if (selectionKey.isConnectable()) {
						System.out.println("Client:  already connected.");
						client = (SocketChannel)selectionKey.channel();
						//判断该通道是否进行连接过程、完成连接过程
						if(client.isConnectionPending()){
							client.finishConnect();
							
							sendBuffer.clear();
							sendBuffer.put("hello nio server".getBytes());
							sendBuffer.flip();
							
							client.write(sendBuffer); //将数据写入该通道
							client.register(selector, SelectionKey.OP_READ);
						}
					}
					else if(selectionKey.isReadable()){
						//获取该键中对应的通道
						client = (SocketChannel)selectionKey.channel();
						
						receiveBuffer.clear();
						int count = client.read(receiveBuffer);
						if(count > 0){
							String receiveMessage = new String(receiveBuffer.array(),0,count);
							System.out.println("Client:接收到来自Server的消息," + receiveMessage);
							client.register(selector, SelectionKey.OP_WRITE);
						}
					}
					else if(selectionKey.isWritable()){
						sendBuffer.clear();  
	                    client = (SocketChannel) selectionKey.channel();  
	                    String sendText = "hello server,key..";
	                    sendBuffer.put(sendText.getBytes());  
	                     //将缓冲区各标志复位,因为向里面put了数据标志被改变要想从中读取数据发向服务器,就要复位  
	                    sendBuffer.flip();  
	                    client.write(sendBuffer);  
	                    System.out.println("Client:客户端向服务器端发送数据--:"+sendText);  
	                    client.register(selector, SelectionKey.OP_READ);
						
					}
				}
				selectionKeys.clear();
				Thread.sleep(3000);
			}
			
			
			
			
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
	}
	
	
	
}