| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 网络协议 -> 网络编程socket,BIO,NIO -> 正文阅读 |
|
[网络协议]网络编程socket,BIO,NIO |
Socket理解Socket是什么?Socket在JDK包里就是一个普普通通的类,里面定义了一组跟网络编程相关的方法(API),比如容易理解的connect(),bind()方法,分别是客户端建立连接,服务端绑定端口的API,从这个层面理解Socket就是一组处理网络io的API。它把TCP/IP协议族中网络通信代码(如TCP建立连接的过程)进行封装,相当于介于应用程序和TCP/IP协议族之间的中间软件抽象层。 以TCP协议为例,一台主机(client)上的应用程序需要与另一个主机(server)上的应用程序通信就必须通过Socket套接字建立连接,client端每建立一个连接就会创建一个socket实例,而server端每接受一个连接就会创建一个socket实例与client的socket进行通信,有多少个客户端建立连接就会server就会创建多少个socket实例。 短连接,长连接短连接:建立连接——>数据传输——>关闭连接:数据传输完毕就关闭连接 长连接:建立连接——>数据传输——>数据传输。。。。——>关闭连接:即使没有数据传输也会保持连接状态,直到某一方关闭连接 网络IO编程BIO(Blocking IO)BIO,即阻塞的IO。server创建ServerSocket实例并绑定IP地址和端口号,调用accept()启动监听器。当client端创建Socket对server端发起连接时,server端接收到连接创建socket实例与client端socket实例进行通信,读取数据并处理业务,如图:单线程的BIO ?client代码
server代码
上面代码client向server发送"hello world",server读取数据并打印出来之后就关闭socket。 既然BIO是阻塞IO,那么阻塞体现在哪里呢?主要体现在两点 一、server启动应用程序调用serverSocket.accept()方法,线程就会一直阻塞在这里即使没有接收到连接,知道有连接才会继续执行。 二、启动server应用程序后,client1端debug断点打在建立连接之后,发送数据之前,并启动这个client1,此时同样的代码再启动一个client2向server发送数据,client2很快执行完成了,但是server此时没有任何打印,这是因为server端一直阻塞在read()等待client1发送数据过来。 由此看出,单线程模式的BIO处理效率有限,如果由于某client数据发送出现问题,会导致server段阻塞,自然会想到多线程去处理任务。 多线程处理任务BIO? server每接收到一个连接,就创建一个线程处理该socket实例读取数据,执行业务。 多线程BIO server代码?
这种方式处理少数连接没有太大的问题,但是如果连接多了,很明显这种处理方式比较浪费线程资源,所以我们可以把线程资源通过线程池管理起来。 伪异步BIO 伪异步BIO把线程资源管理起来,通过一定数量的线程去处理多个连接。 代码就不演示了,比较简单。这种模式优势在于对线程资源的控制,但是限制了线程数量,在大并发量,数据读取比较慢时,其他连接就只能等待,这就是最大的弊端。 NIONIO即nonblock-IO,非阻塞IO。 它和IO最大的区别就是,NIO是面向缓冲区的,而java IO是面向流的。java IO在读取数据时,一次只能顺序读一个字节或多个字节,直到读取所有的数据;而NIO是从缓冲区读取或向缓冲区写入数据,缓冲区数据可以通过指针灵活读取数据。其次java IO在调用read()和write()方法时,会一直阻塞直到有数据可读或者可写。而java NIO的非阻塞模式体现在从通道读取数据到buffer时,只会读取目前可用的数据,如果没有可用的数据,它不会一直等待阻塞,而是什么都不做或者去处理其他事情。通过缓冲区向通道写入数据时,线程不需要等数据完全写入,同时可以去处理其他事情。java NIO通过利用线程空闲时间去做其他事情充分利用线程资源,因此一个线程可以管理多个输入和输出通道。 NIO之reactor模式reactor译为反应堆,看各种资料“反应”即“倒置”或者“控制反转”,从中文角度来讲我有点想不通。无论如何,reactor模式表达的是client向server发起连接或者发送数据后,server端并不是被动执行连接读取数据,而是把ServerSocketChannel注册selector选择器上,再通过Reactor线程轮询selector读取这些已经就绪的事件(读、写或连接事件)。 单线程Reactor模式 单线程Reactor-工作者线程池? 多线程Reactor模式? NIO三大核心组件selector选择器 selector选择器是主要有两个作用:其一提供channel注册事件的容器,其二提供轮询事件的API,如:select(),select(int timeout)等。对于客户端和服务端在启动的时候,客户端会向Selector实例中注册一个连接事件,而这些事件存放在而线程会轮询检查是否到该事件。 channel通道 通道是被建立的一个应用程序和操作系统进行交互事件、传递数据的渠道。代码中体现出来的就是ServerSocketChannel和SocketChannel,从这两个channel中可以获取ServerSocket和Socket,不难看出,应用程序可以通过它们读取数据,同时也可以向它们写入数据。注意,通道是面向缓冲区,他只能操作缓冲区(buffer) buffer缓冲区 buffer说到底就是一块内存空间(字节组数或者其他类型数组),应用程序通过channel可以向缓冲区写入数据,也可以从缓冲区读取数据。 三大组件处理数据方式 参考Netty权威指南NIO源码示例: 1、NIO server启动,创建selector选择器对象和ServerSocketChannel对象(简称ssc),将ssc通道设置为非阻塞模式,通过ssc向selector注册该通道感兴趣的接收事件。 2、NIO client启动,创建selector2选择器对象和SocketChannel对象(简称sc),将sc通道设置为非阻塞模式,通过sc.connect()向NIO server端发起tcp异步连接,如果连接成功则向selector2注册读事件,如果失败则注册连接事件。 3、server接收到连接事件,轮询调用selector.select()会收到就绪的事件并交由感兴趣的通道ssc处理,ssc接收到连接并创建socketChannel,socketChannel向selector注册感兴趣的读事件 4、client连接server成功后,调用doWrite()向server发送数据,server通过轮询selector.select()感知到有数据就绪(即读事件),通过selectionKey获取到socketChannel将数据读到buffer缓冲区,交由应用程序进行业务处理。 5、应用程序处理完成后需要响应客户端,将数据复制到buffer写缓冲,调用socketChannel.write()方法将buffer数据写出去,这是直接写出去;也可以通过调用socketChannel.register()向selector注册感兴趣的读事件,与此同时也会向就绪的事件集合中添加写事件,让selector能轮询到,最后通过write()发送给客户端,通过这种方式需要注意防止写空转的问题,在将数据发送给客户端以后可以通过调用key.interestOps(SelectionKey.OP_READ);将原来注册的写事件覆盖,否则selector中就绪事件集合中会一直存在写事件导致发生写空转,与此同时isWritable()是判断写缓冲是否有空闲或者说是否可以写入数据,那么它会一直返回true。 nio-client流程 nio-server流程 |
|
网络协议 最新文章 |
使用Easyswoole 搭建简单的Websoket服务 |
常见的数据通信方式有哪些? |
Openssl 1024bit RSA算法---公私钥获取和处 |
HTTPS协议的密钥交换流程 |
《小白WEB安全入门》03. 漏洞篇 |
HttpRunner4.x 安装与使用 |
2021-07-04 |
手写RPC学习笔记 |
K8S高可用版本部署 |
mySQL计算IP地址范围 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 | -2024/12/30 3:17:13- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |