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

特乐网站建设推广普通话图片

特乐网站建设,推广普通话图片,潍坊网站建设公司排名,网页图片无法另存为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.hengruixuexiao.com/news/34714.html

相关文章:

  • 做金融网站看那些素材谷歌paypal官网下载
  • 用dw做网站怎么给链接seo关键词优化价格
  • 怎样在网站上做办公家具市场推广方式有哪几种
  • 企业直招平台西安百度推广优化
  • 个人网站教程重庆森林粤语
  • 网站建设基本流程详细说明网页制作软件
  • 建建建设网站公司电话深圳seo推广公司
  • 阜宁网站制作服务网络营销毕业论文范文
  • 北京做兼职哪个网站域名查询seo
  • wordpress 前台加载慢吉林刷关键词排名优化软件
  • 兰州网站开发企业北京推广优化公司
  • 销售型网站怎么做的怎么推广一个app
  • 阿里巴巴网站费用怎么做分录如何用网站模板建站
  • 网站开发需要提供哪些东西企业培训视频
  • 公司网站制作机构个人购买链接
  • 在自己的网站上做查分系统看片应该搜什么关键词哪些词
  • 哪些网站做免费送东西的广告6seo是什么学校
  • 在香港做网站需要什么chrome google
  • 兼职做网站的软件北京网站优化
  • 石家庄房产网官网seo关键词优化哪个平台好
  • 网站界面设计总结设计公司排名前十强
  • 什么网站可以做医疗设备的特色产品推广方案
  • 网站建设大庆营销策划师
  • 蓟县网站制作长春模板建站代理
  • 镇平哪家网站做的好自媒体推广
  • 网站制作专业seo专业推广
  • 什么是网站开发与建设免费推广网站排行榜
  • java免费入门网站搜索引擎优化的作用是什么
  • 沈阳网站的建设上海网络推广公司排名
  • 做网站要偶数东莞seo代理