外贸网站建设维护,自己做网站 需要哪些,鹤山网站建设易搜互联,苏州企业如何建网站网络IO 阻塞模型 在之前网络通信都是阻塞模型 客户端向服务端发出请求后#xff0c;客户端会一直处于等待状态#xff0c;直到服务器端返回结果或网络出现问题 服务器端也是如此#xff0c;在处理某个客户端A发来的请求时#xff0c;另一个客户端B发来的请求会等待#xf… 网络IO 阻塞模型 在之前网络通信都是阻塞模型 客户端向服务端发出请求后客户端会一直处于等待状态直到服务器端返回结果或网络出现问题 服务器端也是如此在处理某个客户端A发来的请求时另一个客户端B发来的请求会等待直到服务器端的处理线程线程上一个请求的处理 在服务端使用ServerSocket来建立套接字accept方法会进行阻塞等待客户端的连接 try( // 创建一个ServerSocket对象 ServerSocket serverSocket new ServerSocket(9090); // accept方法返回Socket对象这里会进行阻塞应用程序向操作系统请求接收已准备好的客户端连接的数据信息 Socket s serverSocket.accept(); // 获取输入流这里读取数据也会阻塞 InputStream is s.getInputStream(); // 输出流给客户端返回消息 OutputStream os s.getOutputStream(); InputStreamReader isr new InputStreamReader(is); BufferedReader reader new BufferedReader(isr);){ String str; while ((str reader.readLine()) ! null){ System.out.print(str); } os.write(我已收到消息.getBytes()); } catch (IOException e){ e.printStackTrace();} serverSocket.accept()阻塞 服务器端发起一个accept动作询问操作系统是否有新的Socket套接字信息从端口发送过来如果没有则serverSocket.accept()会一直等待 阻塞模型的问题 同一时间服务器只能接收一个客户端的请求信息第二个客户端需要等待服务器接收完第一个请求数据后才会被接收 服务器一次只能处理一个客户端请求处理完成并返回后才能进行第二次请求的处理 多线程阻塞模型 由于阻塞模型的弊端高并发时会导致请求太慢所以提出了使用多线程来解决上述阻塞问题 服务器收到客户端A的请求后开启线程去进行数据处理。主线程可以继续接收客户端B的请求 但是这样在进行serverSocket.accept();操作时还是单线程运行只有业务处理才会使用多线程对于接收数据的并发能力并没有提升 同步非阻塞模型 这里先说一下同步和非同步的概念 同步和非同步是操作系统级别的主要描述操作系统在收到程序请求网络IO操作后如果网络IO资源没有准备好该如何响应程序 同步IO不响应程序直到网络IO资源准备好 非同步IO返回一个标记当网络IO资源准备好后用事件机制通知给程序 再说一下阻塞和非阻塞的概念 阻塞和非阻塞是程序级别的主要描述程序请求操作系统IO操作后如果网络IO资源没有准备好程序如何处理 阻塞IO会进行等待 非阻塞IO会继续执行且使用线程一直轮询直到IO资源准备好 { boolean flag true; try { ServerSocket serverSocket new ServerSocket(6666); // 使用超时时间来设置为非阻塞状态,超过该时间会抛出SocketTimeoutException serverSocket.setSoTimeout(100); while (true){ Socket socket null; try{ // 设置了超时时间后accept就不会阻塞了 socket serverSocket.accept(); } catch (SocketTimeoutException e){ synchronized (obj){ // 100ms内没有接收到任何数据可以在这里做一些别的操作 System.out.println(没接收到数据先歇一歇吧); try { obj.wait(10); } catch (InterruptedException interruptedException) { interruptedException.printStackTrace(); } } continue; } // 开线程处理数据 new Thread(socket).start(); } } catch (IOException e) { e.printStackTrace(); } } serverSocket.setSoTimeout可以使accept方法不一直阻塞而是到了超时时间后抛出SocketTimeoutException异常此时就可以用主线程做别的事情了虽然实际还是使用的accept阻塞模型但是有所改善 多路复用模型 多路复用模型(也就是NIO)不在使用操作系统级别的同步IO目前主要实现有select、poll、epoll、kqueue { ByteBuffer byteBuffer ByteBuffer.allocate(1024); Selector selector Selector.open(); ServerSocketChannel serverSocketChannel ServerSocketChannel.open(); // 设置为非阻塞 serverSocketChannel.configureBlocking(false); // 绑定8080端口 serverSocketChannel.bind(new InetSocketAddress(8080)); // 注册监听的事件 // ServerSocketChannel只能注册OP_ACCEPT // SocketChannel可注册OP_READ、OP_WRITE、OP_CONNECT serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); while(true){ // 询问selector中准备好的事件 selector.select(); // 获取到上述询问拿到的事件类型 SetSelectionKey selectionKeys selector.selectedKeys(); IteratorSelectionKey iterator selectionKeys.iterator(); while (iterator.hasNext()){ SelectionKey selectionKey iterator.next(); if(selectionKey.isAcceptable()){ ServerSocketChannel ssc (ServerSocketChannel) selectionKey.channel(); // 接收到服务端的请求 SocketChannel sc ssc.accept(); sc.configureBlocking(false); sc.register(selector,SelectionKey.OP_READ); // 处理过了就要移除掉否则再次select()还会拿到该事件 iterator.remove(); } else if(selectionKey.isReadable()){ SocketChannel sc (SocketChannel) selectionKey.channel(); byteBuffer.clear(); int n sc.read(byteBuffer); if(n 0){ byteBuffer.flip(); Charset charset StandardCharsets.UTF_8; String message String.valueOf(charset.decode(byteBuffer).array()); System.out.println(message); } sc.register(selector,SelectionKey.OP_WRITE); iterator.remove(); } else if(selectionKey.isWritable()){ SocketChannel sc (SocketChannel) selectionKey.channel(); ByteBuffer buffer ByteBuffer.allocate(1024); buffer.put(已接收到消息.getBytes()); buffer.flip(); sc.write(buffer); iterator.remove(); } } }} 多路复用显然绕过了accept方法的阻塞问题使得操作系统可以在一个端口上能够同时接收多个客户端的IO事件 https://zhhll.icu/2022/java基础/IO/4.网络IO/ 本文由 mdnice 多平台发布