标签:remove ack 相互 oid 内核 nal 并且 读取 导致
《netty权威指南》读书笔记
一、BIO
1、服务端程序:
1 package bio; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.io.PrintWriter; 7 import java.net.ServerSocket; 8 import java.net.Socket; 9 import java.util.Date; 10 11 public class BioServer { 12 13 public static void main(String[] args) throws IOException { 14 ServerSocket serverSocket = new ServerSocket(8081); 15 Socket clientSocket = null; 16 while(true){ 17 clientSocket = serverSocket.accept();//如果没有客户端接入,主线程阻塞在这里 18 new Thread(new ServerHandler(clientSocket)).start(); 19 } 20 //finall关闭serverSocket 21 } 22 23 } 24 25 class ServerHandler implements Runnable{ 26 private Socket clientSocket; 27 28 public ServerHandler(Socket clientSocket) { 29 this.clientSocket = clientSocket; 30 } 31 32 @Override 33 public void run() { 34 try { 35 BufferedReader reader = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream())); 36 PrintWriter writer = new PrintWriter(this.clientSocket.getOutputStream(), true); 37 while(true){ 38 String body = reader.readLine(); 39 if (body==null){ 40 break; 41 } 42 System.out.println(body); 43 writer.println(new Date().toString() + "->" + body); 44 } 45 } catch (IOException e) { 46 e.printStackTrace(); 47 } 48 //finally关闭资源:流和socket 49 } 50 }
2、客户端程序:
1 package bio; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.io.PrintWriter; 7 import java.net.Socket; 8 9 public class BioClient { 10 public static void main(String[] args) throws IOException { 11 Socket clientSocket = new Socket("127.0.0.1", 8081); 12 BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); 13 PrintWriter writer = new PrintWriter(clientSocket.getOutputStream(), true); 14 writer.println("haha"); 15 String resp = reader.readLine(); 16 System.out.println(resp); 17 //finall关闭serverSocket 18 } 19 }
服务端阻塞的几个点:
二、NIO
1、服务端程序
1 package nio; 2 3 import java.io.IOException; 4 import java.net.InetSocketAddress; 5 import java.nio.ByteBuffer; 6 import java.nio.channels.SelectionKey; 7 import java.nio.channels.Selector; 8 import java.nio.channels.ServerSocketChannel; 9 import java.nio.channels.SocketChannel; 10 import java.util.Iterator; 11 12 public class NioServer { 13 public static void main(String[] args) throws IOException { 14 Selector selector = Selector.open(); 15 16 ServerSocketChannel serverChannel = ServerSocketChannel.open(); 17 serverChannel.configureBlocking(false); 18 serverChannel.socket().bind(new InetSocketAddress(8083));//监听链接8082端口的客户端socket 19 serverChannel.register(selector, SelectionKey.OP_ACCEPT);//将serverChannel注册到selector,并监听接受连接事件 20 21 while (selector.select() > 0) {//该方法会发生阻塞,直到至少有一个事件"准备就绪"为止 22 Iterator<SelectionKey> it = selector.selectedKeys().iterator(); 23 while (it.hasNext()) { 24 SelectionKey sk = it.next(); 25 if (sk.isAcceptable()) { 26 SocketChannel clientChannel = serverChannel.accept();//相当于客户端三次握手 27 clientChannel.configureBlocking(false); 28 clientChannel.register(selector, SelectionKey.OP_READ); 29 } else if (sk.isReadable()) { 30 SocketChannel clientChannel = (SocketChannel) sk.channel(); 31 ByteBuffer buf = ByteBuffer.allocate(1024); 32 while (clientChannel.read(buf) > 0) {//将通道中的数据读到缓冲区,因为clientChannel已经是非阻塞的,所以这里的read是非阻塞的 33 buf.flip();//将缓冲区由写模式切换到读模式 34 byte[] bytes = new byte[buf.remaining()]; 35 buf.get(bytes);//将缓冲区中的数据读取到bytes中 36 String body = new String(bytes, "UTF-8"); 37 System.out.println("接收到来自客户端的信息:" + body); 38 buf.clear(); 39 } 40 } 41 it.remove(); 42 } 43 } 44 } 45 }
2、客户端程序
1 package nio; 2 3 import java.io.IOException; 4 import java.net.InetSocketAddress; 5 import java.nio.ByteBuffer; 6 import java.nio.channels.SocketChannel; 7 8 public class NioClient { 9 public static void main(String[] args) throws IOException { 10 SocketChannel clientChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 8083));//向服务端发出连接请求,服务端会通过accept()方法实现三次握手后,建立连接 11 clientChannel.configureBlocking(false); 12 ByteBuffer buf = ByteBuffer.allocate(1024);//分配在JVM堆中:capacity=1024;position=0;limit=1024 13 // ByteBuffer buf = ByteBuffer.allocateDirect(1024);//分配在堆外内存(物理内存)中 14 buf.put("abcde".getBytes());//将数据写入缓冲区buf中:capacity=1024;position=5;limit=1024 15 buf.flip();//将缓冲区从写模式切换到读模式:capacity=1024;position=0;limit=5 16 clientChannel.write(buf);//将缓冲区的数据写入通道:capacity=1024;position=5;limit=5 17 buf.clear();//清空缓冲区:capacity=1024;position=0;limit=1024 18 clientChannel.close(); 19 } 20 }
附:ByteBuffer使用JVM堆内存和使用堆外内存的区别:(图片来自尚硅谷的NIO教程)
三、BIO与NIO的比较
1、线程数
2、阻塞情况
3、面向对象
4、适合点
四、Reactor模型
主从模型:
标签:remove ack 相互 oid 内核 nal 并且 读取 导致
原文地址:http://www.cnblogs.com/java-zhao/p/7044809.html