linux网络配置命令 linux网络配置的详细过程( 二 )



网络编程都需要知道FD??? FD是个什么鬼???
Linux:万物都是文件,FD就是文件的引用 。像不像JAVA中万物都是对象?程序中操作的是对象的引用 。JAVA中创建对象的个数有内存的限制,同样FD的个数也是有限制的 。

linux网络配置命令 linux网络配置的详细过程


Linux在处理文件和网络连接时,都需要打开和关闭FD 。
每个进程都会有默认的FD:
  • 0 标准输入 stdin
  • 1 标准输出 stdout
  • 2 错误输出 stderr
1.5 服务端处理网络请求的过程
linux网络配置命令 linux网络配置的详细过程


  • 连接建立后 。
  • 等待数据准备好(CPU 闲置) 。
  • 将数据从内核拷贝到进程中(CPU闲置) 。
怎么优化呢?
对于一次I/O访问(以read举例),数据会先被拷贝到操作系统内核的缓冲区,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间 。
所以说,当一个read操作发生时,它会经历两个阶段:
  • 等待数据准备 (Waiting for the data to be ready) 。
  • 将数据从内核拷贝到进程中 (Copying the data from the kernel to the process) 。
【linux网络配置命令 linux网络配置的详细过程】正是因为这两个阶段,Linux系统升级迭代中出现了下面三种网络模式的解决方案 。
二、IO模型介绍2.1 阻塞 I/O – Blocking I/O
linux网络配置命令 linux网络配置的详细过程


简介:最原始的网络I/O模型 。进程会一直阻塞,直到数据拷贝完成 。
缺点:高并发时,服务端与客户端对等连接,线程多带来的问题:
  • CPU资源浪费,上下文切换 。
  • 内存成本几何上升,JVM一个线程的成本约1MB 。
public static void main(String[] args) throws IOException {ServerSocket ss = new ServerSocket();ss.bind(new InetSocketAddress(Constant.HOST, Constant.PORT));int idx =0;while (true) {final Socket socket = ss.accept();//阻塞方法new Thread(() -> {handle(socket);},"线程["+idx+"]" ).start();}}static void handle(Socket socket) {byte[] bytes = new byte[1024];try {String serverMsg = "server sss[ 线程:"+ Thread.currentThread().getName() +"]";socket.getOutputStream().write(serverMsg.getBytes());//阻塞方法socket.getOutputStream().flush();} catch (Exception e) {e.printStackTrace();}}2.2 非阻塞 I/O – Non Blocking IO
linux网络配置命令 linux网络配置的详细过程


简介:进程反复系统调用,并马上返回结果 。
缺点:当进程有1000fds,代表用户进程轮询发生系统调用1000次kernel,来回的用户态和内核态的切换,成本几何上升 。
public static void main(String[] args) throws IOException {ServerSocketChannel ss = ServerSocketChannel.open();ss.bind(new InetSocketAddress(Constant.HOST, Constant.PORT));System.out.println(" NIO server started ... ");ss.configureBlocking(false);int idx =0;while (true) {final SocketChannel socket = ss.accept();//阻塞方法new Thread(() -> {handle(socket);},"线程["+idx+"]" ).start();}}static void handle(SocketChannel socket) {try {socket.configureBlocking(false);ByteBuffer byteBuffer = ByteBuffer.allocate(1024);socket.read(byteBuffer);byteBuffer.flip();System.out.println("请求:" + new String(byteBuffer.array()));String resp = "服务器响应";byteBuffer.get(resp.getBytes());socket.write(byteBuffer);} catch (IOException e) {e.printStackTrace();}}2.3 I/O 多路复用 – IO multiplexing
linux网络配置命令 linux网络配置的详细过程


简介:单个线程就可以同时处理多个网络连接 。内核负责轮询所有socket,当某个socket有数据到达了,就通知用户进程 。多路复用在Linux内核代码迭代过程中依次支持了三种调用,即select、POLL、EPOLL三种多路复用的网络I/O模型 。下文将画图结合Java代码解释 。

推荐阅读