使用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(); } }