NIO的Selector

使用Selector实现简单的Sever:

package 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;

public class NIOServer {
	
	private Selector selector;
	
	private ByteBuffer buffer = ByteBuffer.allocate(1024);
	
	private ByteBuffer lBuffer = ByteBuffer.allocate(32);
	
	private ByteBuffer[] bbs = new ByteBuffer[]{buffer,lBuffer};
	
	public NIOServer(int port) throws Exception{
		init(port);
	}

	public  void init(int port) throws Exception{
		selector = Selector.open();//首先生成一个Selector
		ServerSocketChannel schanel = ServerSocketChannel.open();//创建一个ServerSocketChannel
		schanel.configureBlocking(false);//设置为非阻塞
		schanel.bind(new InetSocketAddress(port));//绑定端口号
		schanel.register(selector, SelectionKey.OP_ACCEPT);//在Selector上注册一个接受事件
	}
	
	public void start() throws Exception{
		while(true){
			int num = selector.select();
			System.out.println("数量:"+num);
			Iterator<SelectionKey> ite=selector.selectedKeys().iterator();
			while(ite.hasNext()){
				SelectionKey key = ite.next();
				handle(key);
				ite.remove();//需要自己手动remove事件
			}
		}
	}
	
	public void handle(SelectionKey key) throws Exception{
		if(key.isAcceptable()){//接受到一个客户端请求
			System.out.println("接受到一个请求");
			ServerSocketChannel s = (ServerSocketChannel)key.channel();
			SocketChannel socket = s.accept();//获取一个客户端连接SocketChannel
			socket.configureBlocking(false);
			socket.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE);//在客户端连接上注册READ和WRITE事件
		}else
		if(key.isReadable()){
			System.out.println("接受到一个read请求");
			buffer.clear();
			SocketChannel socket = (SocketChannel)key.channel();
			
			int r = socket.read(buffer);
			System.out.println("读取长度:"+r);
			if(-1==r){
				socket.close();
				key.cancel();
			}
			System.out.println(new String(buffer.array(),"utf-8"));
			
		}
	}
	public static void main(String[] args) throws Exception {
		NIOServer server = new NIOServer(9999);
		server.start();
	}
}

 客户端代码:

package socket;

import java.io.DataOutputStream;

import mySocket.SocketWrapper;

public class Client {

	public static void main(String[] args) {
		SocketWrapper client;
		try {
			client = new SocketWrapper("127.0.0.1", 9999);
			DataOutputStream out = client.getOutputStream();
			out.writeInt(1);
			String s = new String("师妃暄的脸上méng着一层淡淡的薄纱,说不出来的朦胧和神秘,目注从营帐中行出的祝yù研");
			byte[] ss = s.getBytes("utf-8");
			System.out.println(ss.length);
//			out.writeInt(ss.length);
			out.write(ss);
			out.flush();
//			OutputStreamWriter writer = new OutputStreamWriter(client.getOutputStream());
//			writer.write("你是谁啊啊啊啊");
//			writer.flush();
			
			
			
			out.close();
			client.close();
			System.out.println("GAME OVER!!!");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

}
 

代码存在一些问题,服务端会调用多次read事件,且会把整个buffer(1024)全部打印出来

以下是修改之后的代码:

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

public class NIOServer {
	
	private Selector selector;
	
	private ByteBuffer buffer = ByteBuffer.allocate(1024);
	
	private ByteBuffer lBuffer = ByteBuffer.allocate(32);
	
	private ByteBuffer[] bbs = new ByteBuffer[]{buffer,lBuffer};
	
	public NIOServer(int port) throws Exception{
		init(port);
	}

	public  void init(int port) throws Exception{
		selector = Selector.open();//首先生成一个Selector
		ServerSocketChannel schanel = ServerSocketChannel.open();//创建一个ServerSocketChannel
		schanel.configureBlocking(false);//设置为非阻塞
		schanel.bind(new InetSocketAddress(port));//绑定端口号
		schanel.register(selector, SelectionKey.OP_ACCEPT);//在Selector上注册一个接受事件
	}
	
	public void start() throws Exception{
		while(true){
			int num = selector.select();
//			System.out.println("数量:"+num);
			Iterator<SelectionKey> ite=selector.selectedKeys().iterator();
			while(ite.hasNext()){
//			Set<SelectionKey> selectionKeySet = selector.selectedKeys();
//			for (SelectionKey selectionKey : selectionKeySet) {
				SelectionKey key = ite.next();
//				ite.remove();
				selector.selectedKeys().remove(key);
				handle(key);
			}
//			selectionKeySet.clear();
		}
	}
	
	public void handle(SelectionKey key) throws Exception{
		if(key.isAcceptable()){//接受到一个客户端请求
			System.out.println("接受到一个请求");
			ServerSocketChannel s = (ServerSocketChannel)key.channel();
			SocketChannel socket = s.accept();//获取一个客户端连接SocketChannel
			socket.configureBlocking(false);
			socket.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE);//在客户端连接上注册READ和WRITE事件
		}else
		if(key.isReadable()){
//			System.out.println("接受到一个read请求");
			buffer.clear();
			SocketChannel socket = (SocketChannel)key.channel();
			
			int r = socket.read(buffer);
//			System.out.println("读取长度:"+r);
			if(r<1){
				socket.close();
				key.cancel();
			}else
			System.out.println(new String(buffer.array(),0,r,"utf-8"));
			
		}
	}
	public static void main(String[] args) throws Exception {
		NIOServer server = new NIOServer(8888);
		server.start();
	}
}

猜你喜欢

转载自h140465.iteye.com/blog/2214795