BIO同步阻塞
服务器端创建ServerSocket对象,客户端创建Socket对象来连接服务器进行通信,服务器端需要对每个请求建线程。客户端和服务器端的IO流是阻塞的。客户端的IO流,在服务器端将返回值传输回来之前,都是处于阻塞的状态,服务器和客户端一直占用连接。
NIO同步非阻塞
NIO解决了阻塞问题,不是每个连接对应一个线程,是一个有效的请求对应一个处理线程,连接公用线程。
NIO中间的三个角色
SocketChannel
类似BIO中间的Socket,用于建立连接和传输数据,可以被多个线程公用。
Buffer
就是计算内存中间一块区域,通过Buffer实现数据的读写操作
Selector
监听SocketChannel。实现非阻塞
代码实现:
NIOServer
package com.wanmait.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.Set; public class TestServer { public static void main(String[] args) { try { System.out.println("服务器"); Selector selector = Selector.open(); ServerSocketChannel serverChannel = ServerSocketChannel.open(); serverChannel.configureBlocking(false);//设置为非阻塞模式 serverChannel.socket().bind(new InetSocketAddress(50000),60000); //设置监听的端口 50000 ~ 60000 serverChannel.register(selector, SelectionKey.OP_ACCEPT); //ServerSocketChanner注册到Selector 有Selector监听 new Thread() { public void run() { while(true) { try { selector.select(); Set<SelectionKey> selectionKeys = selector.selectedKeys(); for(SelectionKey selectionKey:selectionKeys) { if(selectionKey.isValid())//判断key是否有效 { ServerSocketChannel server = (ServerSocketChannel)selectionKey.channel(); //建立连接 SocketChannel client = server.accept(); //获得客户通道 client.configureBlocking(true); //设置成为阻塞 ByteBuffer receivebuffer = ByteBuffer.allocate(1024); int count = client.read(receivebuffer); //读取数据 if(count>0) { receivebuffer.flip(); byte[] bytes = new byte[receivebuffer.remaining()]; receivebuffer.get(bytes); String body = new String(bytes,"utf-8"); System.out.println(body); } } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }.start(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
NIOClient:
package com.wanmait.nio; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; public class TestClient { public static void main(String[] args) { // TODO Auto-generated method stub try { SocketChannel socketChannel = SocketChannel.open(); boolean flag = socketChannel.connect(new InetSocketAddress("127.0.0.1",50000)); if(flag) { ByteBuffer sendbuffer = ByteBuffer.allocate(1024); sendbuffer.put("wanmait".getBytes()); sendbuffer.flip(); socketChannel.write(sendbuffer); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
AIO异步非阻塞
进行读写操作时,调用API的read和write方法。将可读的数据传入read方法,并通知程序读。
AIO服务器代码:
package com.wanmait.aio; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousServerSocketChannel; import java.nio.channels.AsynchronousSocketChannel; import java.nio.channels.CompletionHandler; import java.nio.charset.Charset; import java.util.concurrent.TimeUnit; public class Server { public static void main(String[] args) { // TODO Auto-generated method stub try { ByteBuffer buffer = ByteBuffer.allocate(8); AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(50000)); //读取数据 CompletionHandler<Integer,Object> completionData = new CompletionHandler<>() { @Override public void completed(Integer result, Object attachment) { // TODO Auto-generated method stub if(result!=-1) { buffer.flip(); System.out.println(Charset.forName("utf-8").decode(buffer)); } } @Override public void failed(Throwable exc, Object attachment) { // TODO Auto-generated method stub exc.printStackTrace(); } }; //获得客户端的连接 CompletionHandler<AsynchronousSocketChannel,Object> completionClient = new CompletionHandler<>() { @Override public void completed(AsynchronousSocketChannel acceptChannel, Object attachment) { // TODO Auto-generated method stub acceptChannel.read(buffer,10L,TimeUnit.SECONDS,null,completionData); } @Override public void failed(Throwable exc, Object attachment) { // TODO Auto-generated method stub exc.printStackTrace(); } }; server.accept(null,completionClient); Thread.sleep(5000); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
AIO客户端代码:
package com.wanmait.aio; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousSocketChannel; import java.util.concurrent.ExecutionException; public class Client { public static void main(String[] args) { // TODO Auto-generated method stub try { AsynchronousSocketChannel client = AsynchronousSocketChannel.open(); client.connect(new InetSocketAddress("127.0.0.1",50000)).get(); //连接服务器 client.write(ByteBuffer.wrap("wanmait".getBytes())); //相服务器发送数据 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
0条评论
点击登录参与评论