网络编程都需要知道FD??? FD是个什么鬼???
Linux:万物都是文件,FD就是文件的引用 。像不像JAVA中万物都是对象?程序中操作的是对象的引用 。JAVA中创建对象的个数有内存的限制,同样FD的个数也是有限制的 。
Linux在处理文件和网络连接时,都需要打开和关闭FD 。
每个进程都会有默认的FD:
- 0 标准输入 stdin
- 1 标准输出 stdout
- 2 错误输出 stderr
- 连接建立后 。
- 等待数据准备好(CPU 闲置) 。
- 将数据从内核拷贝到进程中(CPU闲置) 。
对于一次I/O访问(以read举例),数据会先被拷贝到操作系统内核的缓冲区,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间 。
所以说,当一个read操作发生时,它会经历两个阶段:
- 等待数据准备 (Waiting for the data to be ready) 。
- 将数据从内核拷贝到进程中 (Copying the data from the kernel to the process) 。
二、IO模型介绍2.1 阻塞 I/O – Blocking I/O
简介:最原始的网络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简介:进程反复系统调用,并马上返回结果 。
缺点:当进程有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简介:单个线程就可以同时处理多个网络连接 。内核负责轮询所有socket,当某个socket有数据到达了,就通知用户进程 。多路复用在Linux内核代码迭代过程中依次支持了三种调用,即select、POLL、EPOLL三种多路复用的网络I/O模型 。下文将画图结合Java代码解释 。
推荐阅读
- 华为p50pro+配置参数详细 华为p50pro+配置参数详情
- mate10参数配置 华为mate10充电器参数
- 如何修改hosts文件内容 电脑hosts文件配置异常
- 如何共享电脑网络给手机 第二台电脑连接打印机的方法
- linux查看jdk版本命令 Linux配置jdk环境变量
- opporeno5pro配置参数如何 opporeno5pro配置介绍
- 配置及参数详情 华为P50Pro详细配置
- reno5手机参数 opporeno5系列参数配置 oppo
- opt文件用什么打开 opt无效文件规格ug
- 荣耀10上市时间 华为荣耀10的配置参数