免费h5源码资源源码站,什么是网站内链,免费代理游戏,南宁百度seo排名优化IO模型
用什么样的通道进行数据传输和接收#xff0c;java支持3种io网络编程模式 BIO NIO AIO
BIO
同步阻塞 一个客户端连接对应一个处理线程 BIO示例代码#xff08;客户端和服务端#xff09;
package com.tuling.bio;import java.io.IOException;
import java.net.So…IO模型
用什么样的通道进行数据传输和接收java支持3种io网络编程模式 BIO NIO AIO
BIO
同步阻塞 一个客户端连接对应一个处理线程 BIO示例代码客户端和服务端
package com.tuling.bio;import java.io.IOException;
import java.net.Socket;public class SocketClient {public static void main(String[] args) throws IOException, InterruptedException {Socket socket new Socket(127.0.0.1, 9000);//向服务端发送数据socket.getOutputStream().write(HelloServer.getBytes());socket.getOutputStream().flush();System.out.println(向服务端发送数据结束);byte[] bytes new byte[1024];//接收服务端回传的数据socket.getInputStream().read(bytes);System.out.println(接收到服务端的数据 new String(bytes));socket.close();}
}package com.tuling.bio;import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;public class SocketServer {public static void main(String[] args) throws IOException {ServerSocket serverSocket new ServerSocket(9000);while (true) {System.out.println(等待连接。。);//阻塞方法Socket clientSocket serverSocket.accept();System.out.println(有客户端连接了。。);new Thread(new Runnable() {Overridepublic void run() {try {handler(clientSocket);} catch (IOException e) {e.printStackTrace();}}}).start();}}private static void handler(Socket clientSocket) throws IOException {byte[] bytes new byte[1024];System.out.println(准备read。。);//接收客户端的数据阻塞方法没有数据可读时就阻塞int read clientSocket.getInputStream().read(bytes);System.out.println(read完毕。。);if (read ! -1) {System.out.println(接收到客户端的数据 new String(bytes, 0, read));}clientSocket.getOutputStream().write(HelloClient.getBytes());clientSocket.getOutputStream().flush();}
}先启动服务端再启动客户端客户端和服务端直接可以互发消息 缺点io代码里read操作是阻塞操作如果连接不做数据读写操作会导致线程阻塞浪费资源 如果线程很多会导致服务器线程太多压力太大 应用场景连接数目小且固定的架构对服务器资源要求比较高
NIO
同步非阻塞 一个线程可以处理多个请求。 客户端发送的请求可以注册到多路复用selector上多路复用查询到IO请求就进行处理
应用场景 连接多且连接比较短的架构如聊天服务器编程比较复杂
nio示例代码
package com.tuling.nio;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;public class NioServer {// 保存客户端连接static ListSocketChannel channelList new ArrayList();public static void main(String[] args) throws IOException {// 创建NIO ServerSocketChannel,与BIO的serverSocket类似ServerSocketChannel serverSocket ServerSocketChannel.open();serverSocket.socket().bind(new InetSocketAddress(9000));// 设置ServerSocketChannel为非阻塞serverSocket.configureBlocking(false);System.out.println(服务启动成功);while (true) {// 非阻塞模式accept方法不会阻塞否则会阻塞// NIO的非阻塞是由操作系统内部实现的底层调用了linux内核的accept函数SocketChannel socketChannel serverSocket.accept();if (socketChannel ! null) { // 如果有客户端进行连接System.out.println(连接成功);// 设置SocketChannel为非阻塞socketChannel.configureBlocking(false);// 保存客户端连接在List中channelList.add(socketChannel);}// 遍历连接进行数据读取IteratorSocketChannel iterator channelList.iterator();while (iterator.hasNext()) {SocketChannel sc iterator.next();ByteBuffer byteBuffer ByteBuffer.allocate(128);// 非阻塞模式read方法不会阻塞否则会阻塞int len sc.read(byteBuffer);// 如果有数据把数据打印出来if (len 0) {System.out.println(接收到消息 new String(byteBuffer.array()));} else if (len -1) { // 如果客户端断开把socket从集合中去掉iterator.remove();System.out.println(客户端断开连接);}}}}
}nio引入多路复用器示例代码
package com.tuling.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.Iterator;
import java.util.Set;public class NioSelectorServer {public static void main(String[] args) throws IOException {// 创建NIO ServerSocketChannelServerSocketChannel serverSocket ServerSocketChannel.open();serverSocket.socket().bind(new InetSocketAddress(9000));// 设置ServerSocketChannel为非阻塞serverSocket.configureBlocking(false);// 打开Selector处理Channel即创建epollSelector selector Selector.open();// 把ServerSocketChannel注册到selector上并且selector对客户端accept连接操作感兴趣SelectionKey selectionKey serverSocket.register(selector, SelectionKey.OP_ACCEPT);System.out.println(服务启动成功);while (true) {// 阻塞等待需要处理的事件发生selector.select();// 获取selector中注册的全部事件的 SelectionKey 实例SetSelectionKey selectionKeys selector.selectedKeys();IteratorSelectionKey iterator selectionKeys.iterator();// 遍历SelectionKey对事件进行处理while (iterator.hasNext()) {SelectionKey key iterator.next();// 如果是OP_ACCEPT事件则进行连接获取和事件注册if (key.isAcceptable()) {ServerSocketChannel server (ServerSocketChannel) key.channel();SocketChannel socketChannel server.accept();socketChannel.configureBlocking(false);// 这里只注册了读事件如果需要给客户端发送数据可以注册写事件SelectionKey selKey socketChannel.register(selector, SelectionKey.OP_READ);System.out.println(客户端连接成功);} else if (key.isReadable()) { // 如果是OP_READ事件则进行读取和打印SocketChannel socketChannel (SocketChannel) key.channel();ByteBuffer byteBuffer ByteBuffer.allocateDirect(128);int len socketChannel.read(byteBuffer);// 如果有数据把数据打印出来if (len 0) {System.out.println(接收到消息 new String(byteBuffer.array()));} else if (len -1) { // 如果客户端断开连接关闭SocketSystem.out.println(客户端断开连接);socketChannel.close();}}//从事件集合里删除本次处理的key防止下次select重复处理iterator.remove();}}}
}NIO三大核心组件 channel buffer selector channel 通道 底层数组 buffer 缓冲 nio底层在jdk1.4版本基于linux内核函数select()或poll()来实现类似于nioserver代码每次都会轮询所有的channel。看哪个有读取事件即进行处理没有继续遍历。 jdk1.5后引入epoll基于事件相应来优化nio AIO 异步非阻塞 一般用于连接数多且连接时间较长的应用 jdk7支持
为什么netty 使用NIO而不是AIO 在linux系统aio底层仍然使用epoll没有很好实现AIO性能没有明显优势而且被jdk封装不易优化。 netty是异步非阻塞框架对于aio做了很多异步封装