netty(一)

xiaoxiao2021-02-28  29

package com.fuchanghai.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; public class MyNIOClient { private Selector selector=null; public void initClient (String ip , int port) throws IOException{ //相当于bio中的serversocket ServerSocketChannel serverChannel= ServerSocketChannel.open(); //设置非阻塞 serverChannel.configureBlocking(false); //绑定到对应的端口 serverChannel.socket().bind(new InetSocketAddress(ip, port)); this.selector=Selector.open(); //将通道选择器和通道绑定,一有时间连接就注册成accept serverChannel.register(selector,SelectionKey.OP_ACCEPT); } public void listen(){ //轮询事件管理器(多路复用器) while(true){ try { //阻塞处,可设置时间使其不阻塞 this.selector.select();                         //此处设置时间 //获取所有的注册的事件 Iterator<?> iteratorKey =this.selector.selectedKeys().iterator(); //取出注册的事件,并交给handle方法处理 while (iteratorKey.hasNext()){ SelectionKey selectionKey=(SelectionKey) iteratorKey.next(); iteratorKey.remove(); handle(selectionKey); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public void handle(SelectionKey selectionKey) throws IOException{ if(selectionKey.isAcceptable()){ //如果是新接入进来的 那么将ServerSockteChannel 得到,并且将其注册到selector中 ServerSocketChannel serverSocketChannel =(ServerSocketChannel) selectionKey.channel(); SocketChannel socketChannel =serverSocketChannel.accept(); socketChannel.configureBlocking(false); //给通道设置读的权限。这样服务器才能经过通道读到客户端发来的信息 socketChannel.register(selector,SelectionKey.OP_READ); }else if (selectionKey.isReadable()) { SocketChannel socketChannel =(SocketChannel) selectionKey.channel(); ByteBuffer bf = ByteBuffer.allocate(1024); int data=socketChannel.read(bf); if(data!=-1){ String msg =new String(bf.array(),"GBK"); } } } }

下面是我在听课期间模拟老师讲的实例化的流程图

首先client1到4 就是客户端发起的链接, 虚线部分实际上在代码中没有实现。实线为实现了的。 传统bio 一个client对应的服务端就需要创建一个线程。如诺无线创建线程,那么机器碰到大量的请求总会爆掉。如诺设置个线程池限制线程数量防止线程过多。实际上高并发的时候是不够用的。

使用了nio我们会将各种读写时间,和链接事件都交给selector管理。绑定类型(例如SelectionKey.OP_ACCEPT,注accpet是请求接收类型,connect是已接收类型)使得listen()知道client 要进行哪种操作。这4个顾客发起任何类型请求都会注册到selector中listen()中 ,死循环取得多路复用器中的事件(selector.select())就相当于一个服务员给多个顾客服务,即取得顾客放入selector中的请求。 我们在上面的代码中设置时间(有个注解叫设置时间的),使得程序非阻塞。实际上如果顾客1的点餐请求花费时间太长的话,还是会阻塞其他顾客的请求的。这只是初步了解。之后还要更新

转载请注明原文地址: https://www.6miu.com/read-2626666.html

最新回复(0)