当前位置: 首页 > news >正文

繁昌县网站开发旺道seo网站优化大师

繁昌县网站开发,旺道seo网站优化大师,深圳设计培训机构,网络工程师证书有哪些BIO:同步阻塞IO,客户端一个连接请求(socket)对应一个线程。阻塞体现在: 程序在执行I/O操作时会阻塞当前线程,直到I/O操作完成。在线程空闲的时候也无法释放用于别的服务只能等当前绑定的客户端的消息。 BIO的代码实现 …

BIO:同步阻塞IO,客户端一个连接请求(socket)对应一个线程。阻塞体现在: 程序在执行I/O操作时会阻塞当前线程,直到I/O操作完成。在线程空闲的时候也无法释放用于别的服务只能等当前绑定的客户端的消息。

BIO的代码实现 :

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;public class Main {public static void main(String[] args) throws IOException {int id = 0;ServerSocket socket = new ServerSocket(9090);System.out.println("服务器成功启动...");while (true) {System.out.println("等待客户端连接...");//监听等待客户端连接 这是阻塞操作Socket client = socket.accept();System.out.println("客户" + ++id + "成功连接到:" + client.getInetAddress().getHostAddress());//需要为该客户分配线程执行任务new Thread(new Runnable() {@Overridepublic void run() {try {InputStream is = client.getInputStream();BufferedReader br = new BufferedReader(new InputStreamReader(is));while (true) {//阻塞等待客户端消息String line = br.readLine();if (line == null) {System.out.println("客户端断开...");clinet.close();break;}System.out.println(line);}} catch (IOException e) {throw new RuntimeException(e);}}});}}
}

bio一个客户端对应一个线程所以每有一个客户接入服务器都会创建一个新的线程(创建新线程是通过调用内核的clone()指令来实现的)。

想必大家一定发现bio的明显的弊端了吧,随着接入的客户端越来越多服务器创建的线程数也就越多,在提供服务时在不同线程间的切换(需要保护当前现场,恢复下个线程运行的环境)也会越频繁,这会造成cpu利用的极大浪费,且这种模式的接入量存在明显的上限。

我们可以思考一下造成这一问题的原因是什么:因为是阻塞IO-->在系统调用时缺少参数(需要等待连接或等待消息传递)会被中断等待-->所以当前线程会被阻塞在原地无法提供别的服务-->此时若有新客户端接入我们不得不创建新线程为新客户端服务-->导致线程数越来越多。所以根本问题就在阻塞上,阻塞导致原线程无法提供服务。

**以上的系统调用过程**/*
在类Unix操作系统中,文件描述符(File Descriptor)是一个非负整数,它是一个指向内核中打开文件的指针。每个打开的文件(无论是常规文件、目录、套接字、管道等)都会被分配一个文件描述符。文件描述符通常用于后续的系统调用
标准输入(stdin):通常分配文件描述符 0。
标准输出(stdout):通常分配文件描述符 1。
标准错误(stderr):通常分配文件描述符 2。
打开一个文件可能会返回文件描述符 3。
创建一个套接字可能会返回文件描述符 4。
创建一个管道可能会返回文件描述符 5 和 6(一个用于读,一个用于写)。
*///以下两步对应的就是java代码中的"ServerSocket socket = new ServerSocket(9090);"
socket()=3;//这个函数请求内核创建一个新的套接字,系统调用执行成功并返回了一个文件描述符3 
bind(3,9090);//socke绑定9090端口//监听这个socket
listen(3);
while(true) { accept(3, )=5;//没有客户端连接时会阻塞,当有客户端连接时括号内空的参数就是客户端的一些信息,系统调用执行成功并返回了一个文件描述符5(代表客户端)//接下来需要为客户端分配线程 clone(一些共享参数)=线程号;//通过系统调用clone()指令实现,执行成功会返回线程号
}
对于那个新创建的线程有如下步骤
//创建InputStream
while(true){recv(5, //阻塞等待客户端的消息
}

所以为了解决bio在高连接数的情况下性能急速下降的问题nio就应运而生。

NIO:同步非阻塞IO,是Java 1.4版本开始引入的一个新IO API,支持面向缓冲区、基于通道的IO操作,以更加高效的方式进行文件读写。

Buffer和通道可以相互读写,程序和Buffer交互,所以NIO是面向缓冲区的编程

 

//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.LinkedList;public class Main {public static void main(String[] args) throws IOException {//客户链LinkedList<SocketChannel> clients = new LinkedList<>();//开启服务器ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();//监听9090serverSocketChannel.bind(new InetSocketAddress(9090));//监听线程设置非阻塞serverSocketChannel.configureBlocking(false);while (true) {//等待客户端连接但是不会阻塞等待,由连接时返回连接对象,无连接时返回null(系统调用层面返回-1)while (true) {SocketChannel client= serverSocketChannel.accept();if(client!=null){break;} else {//连接线程设置非阻塞client.configureBlocking(false);int port = client.socket().getPort();System.out.println("当前客户端port:" + port);clients.add(client);}}//执行为客户端提供的服务,以接收消息为例//创建bufferByteBuffer buffer = ByteBuffer.allocate(1024);for (SocketChannel client : clients) {//非阻塞的读int read = client.read(buffer);//有消息时read>0, 无消息read=0, 异常事件read=-1if(read==-1) {//断开连接释放资源client.close();clients.remove(client);break;}if(read > 0) {buffer.flip();byte[] bytes = new byte[buffer.limit()];buffer.get(bytes);String s = new String(bytes);System.out.println(client.socket().getPort() + ":" + s);}}}}
}

 

**系统层面流程**//对应的就是java代码中的"ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();"
socket()=4;//这个函数请求内核创建一个新的套接字,系统调用执行成功并返回了一个文件描述符4 
//对应的就是java代码中的"serverSocketChannel.bind(new InetSocketAddress(9090));"
bind(4,9090);//socke绑定9090端口
//监听这个socket
listen(4);
//多了一步设置非阻塞
fcntl(4,0_NONBLOCK)=0;
while(true){accept(4,)=?;//返回具体客户端或-1,-1代表没有连接fcntl(?, 0_NONBLOCK);//clients.add(?);for(client : clients) {recv(?);//接收消息}
}

但是需要thread去不断轮询clients,当clients非常大的时候循环的事件开销就会很大,并且对于客户链来说需要执行读写操作的时间和数量只占很小的一部分,所以对于轮询操作不仅耗时而且大部分操作是无效的。

为了解决这个问题又引出了多路复用器的概念,由多路复用器来监测并通知thread,再由thread执行相应操作。  

//对应的就是java代码中的"ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();"
socket()=4;//这个函数请求内核创建一个新的套接字,系统调用执行成功并返回了一个文件描述符4 
//对应的就是java代码中的"serverSocketChannel.bind(new InetSocketAddress(9090));"
bind(4,9090);//socke绑定9090端口
//监听这个socket
listen(4);
//多了一步设置非阻塞
fcntl(4,0_NONBLOCK)=0;
while(true){accept(4,)=?;//返回具体客户端或-1,-1代表没有连接clients.add(?);int cnt = select(4,{客户列表});//由多路复用器来监听客户列表中是否需要执行读写操作并告知threadif(cnt>0) {//有事件发生才处理recv(cnt);}
}

当selector连接多个channel时,它会监听每一个channel看是否有读写事件发生,然后再由selector通知thread哪个channel上需要执行什么事件由thread执行。

图片来自这位大佬的博客:BIO、NIO_bio nio-CSDN博客

http://www.hkea.cn/news/657483/

相关文章:

  • wordpress收费资源下载关键词优化的策略
  • 广州做网站建设的公司网站公司
  • 做网络平台的网站有哪些广州网站维护
  • 网页 代码怎么做网站东莞市民最新疫情
  • 电子商务网站设计中影响客户体验的元素有搜索引擎有哪些种类
  • 网站建设难点优化关键词技巧
  • 免费行情网站链接百度知道合伙人官网
  • 餐饮公司网站建设的特点大数据智能营销
  • 济南快速排名刷关键词排名seo软件
  • 系统做网站的地方百度推广登录后台登录入口
  • 集约化网站建设情况广告公司网站制作
  • 网站制作发票字节跳动广告代理商加盟
  • 义乌做网站武汉seo推广优化公司
  • 济宁哪家网站建设公司正规谷歌浏览器 免费下载
  • 有没有女的做任务的网站广东省新闻
  • seo长尾关键词优化如何做网站推广优化
  • 网站搭建服务合同seo排名赚
  • 东莞有什么比较好的网站公司苏州关键词排名系统
  • 做中国供应商免费网站有作用吗浙江网站推广运营
  • mysql8 wordpress百度推广优化是什么意思
  • 做装修广告网站好seo推广公司招商
  • 城市模拟建设游戏网站今天最新的新闻头条新闻
  • 手机网站自适应代码品牌网络营销策划方案
  • 个人网站建设在哪里百度资源搜索平台
  • 云空间免费空间北京网站优化校学费
  • 个人网站做导航网站项目推广平台有哪些
  • 威海住房建设局网站培训学校资质办理条件
  • 做趣味图形的网站免费线上培训平台
  • 女生做网站前端设计师成都网站seo
  • 濮阳建设银行官方网站搜索引擎优化的对比