网络编程中常见的5种I/O模型

I/O模型

Unix下共有五种I/O模型:

1>:阻塞I/O

2>:非阻塞I/O

3>:I/O多路复用

4>:信号驱动I/O

5>:异步I/O

其中前四种是同步I/O模型,只有第五种是异步的。

同步与异步:

这里的同步和两个实体之间通信中的同步的概念是不一样的,这里的同步是指关于这个I/O中的一系列动作都需要自己来完成,无论你是原地等待事件的发生(阻塞)还是当某个事件已经准备好的时候你去完成后面的的动作(非阻塞)都属于同步。

异步,它是指是调用另一个执行者去完成,当执行者发现要处理的时间后调用你,你再完成这件事情,执行的过程和你的动作是不牵扯的。

阻塞与非阻塞:

阻塞是指,等待某个事件的发生,如果它没有发生则一直等待下去直到事件发生为止。

非阻塞,不需要死死的等待,当它有返回的时候再去处理。

1>阻塞I/O

使用的I/O函数,导致程序阻塞,等待数据,如果数据没有准备好则一直等待。

例如我们使用的阻塞式的socket创建套接字的时候,调用accept/recvfrom/connect...等都会是阻塞式的等待连接,请求或者数据的到来

阻塞式的函数实现起来很简单,但它有很多的问题,首先作为一个网络的服务器,阻塞式的等待会浪费大量的资源和时间,当服务器调用函数sendto给远端的一个客户端发送数据时,这时候不做其他的事情那么往后的动作都堵塞在后面,这样显然是不合适的,解决这种问题的方法往往是创建一个进程或者线程去解决这件事,因为进程的开销远远地大于线程的开销,所以使用多线程的方法解决是很行得通的。

阻塞式的I/O的好处就是它非常的稳定,他能保证连接保证接受和发送数据的确定性,这是大多大的互联网公司使用多线程的原因,并且使用线程池也会大大增加线程开启的效率。

2>非阻塞式I/O

调用socket函数并将其设置为非阻塞模式,设置方式,linux下调用fcntl()函数。

非阻塞方式下,当前执行流不再以睡眠的方式来等待请求或者数据的到来,而采用轮询的方式,这种方式的运作流程是这样的,每隔一个时间段便返回一次,如果有数据到来则返回,如果没有,则返回一个错误码WSAEWOULDBLOCK,我们需要不断的用循环来等待数据的成功返回,这个过程往往会占用大量的CPU。

非阻塞的缺点,虽然他不用再使等待太僵硬,但它不可避免的一次只能等待一个事件的到来。

3>信号驱动I/O

在TCPsocket中发生以下事件均会产生SIGIO信号,因为在同一个时候产生这种信号的原因太多我们不能区分到底是哪一种情况产生的SIGIO信号,所以在TCP中信号驱动是不太适合使用的,相反在UDP中却比较适合使用。

信号驱动的工作方式如下图所示

4>I/O多路复用。

这种方式下的工作方式就比较特别了,按TCPsocket来举例,他会当listen到一个新的链接的时候将它放到一个集合中,当这个集合中的套接字有读的情况,我们便读取,有写的情况,我们便写,它是非阻塞I/O和信号驱动I/O再加上可以等待多个,这三个的合体,常见的函数有select,poll,epoll等,这些函数会在后面的博客中细细讲述。

它的缺点就是,无论是上面所述的哪种函数,每次发送或者接受一个数据都会进入两次内核与用户的转换。

I/O多路复用的模型如下图

5>异步I/O

当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者的输入输出操作

5种I/O模型的对比如下图

可以看出最好的方式是异步I/O了当然它实现起来比较负责,阻塞I/O的可靠性最好。

时间: 2024-11-19 00:15:05

网络编程中常见的5种I/O模型的相关文章

网络编程中常见错误码总结

在网络编程中,总有各种需要注意的环节,几乎每个API都要进行异常处理,判断返回值以及错误码来定位是否需要退出. 本文根据自身使用经验,总结以下错误码及其出现场景和一般处理流程. 网络编程的一般性流程如下 : 客户端 : socket -> connect -> write / read 服务端 : socket -> bind -> listen -> accept 还有因为设置属性带来的其它改变,比如非阻塞和套接字选项. EADDRINUSE : 如果你在同一个端口运行了无

Unix网络编程中的五种I/O模型_转

转自:Unix网络编程中的的五种I/O模型 下面主要是把unp第六章介绍的五种I/O模型. 1. 阻塞I/O模型 例如UDP函数recvfrom的内核到应用层.应用层到内核的调用过程是这样的:首先把描述符.接受数据缓冲地址.大小传递给内核,但是如果此时 该与该套接口相应的缓冲区没有数据,这个时候就recvfrom就会卡(阻塞)在这里,知道数据到来的时候,再把数据拷贝到应用层,也就是传进来的地址空 间,如果没有数据到来,就会使该函数阻塞在那里,这就叫做阻塞I/O模型,如下图: 2. 非阻塞I/O模

网络编程中的超时检测

我们在网络编程中常见的一种做法是:创建好套接字后以阻塞的方式读写,如果没有数据可读的话,程序会一直等待.事实上,网络状况一直不断变化,很有可能在通讯过程中出现网络连接断开.我们在程序中有必要对这种情况进行检测,从而及时做出响应.下面介绍几种常用的超时检测方法(假设我们要求通过套接字等待数据的最大时间为8秒): 一. 设置套接字接收超时 setsockopt可以设置套接字的属性,其中包括接收超时时间.参考代码如下        struct timeval tv; // 描述时间的结构体变量   

Java中常见的5种WEB服务器介绍

这篇文章主要介绍了Java中常见的5种WEB服务器介绍,它们分别是Tomcat.Resin.JBoss.WebSphere.WebLogic,需要的朋友可以参考下 Web服务器是运行及发布Web应用的容器,只有将开发的Web项目放置到该容器中,才能使网络中的所有用户通过浏览器进行访问.开发Java Web应用所采用的服务器主要是与JSP/Servlet兼容的Web服务器,比较常用的有Tomcat.Resin.JBoss.WebSphere 和 WebLogic 等,下面将分别进行介绍. Tomc

网络编程中的关键问题总结

总结下网络编程中关键的细节问题,包含连接建立.连接断开.消息到达.发送消息等等: 连接建立 包括服务端接受 (accept) 新连接和客户端成功发起 (connect) 连接. accept接受连接的问题在本文最后会聊到,这里谈谈connect的关键点:     使用非阻塞连接建立需要注意:     connect/select返回后,可能没有连接上:需要再次确认是否成功连接: 步骤为: 使用异步connect直接连接一次,因为使用了非阻塞,函数立刻返回: 检查返回值,为0成功连接,否则加入到s

网络编程中的同步与异步

网络编程中有三对关键的词,单线程与多线程.阻塞与非阻塞.同步与异步,同步与异步一直是比较疑惑的地方.以前认为,同步就是阻塞socket,异步就是非阻塞socket,现在发现这样理解很片面的,其实好多地方有同步异步的概念. 数字电路中的同步与异步是针对时钟来说的 同步时序逻辑电路:各触发器有相同的时钟脉冲,时钟脉冲到来时所有触发器状态同时改变异步时序逻辑电路:没有统一的时钟脉冲,所有触发器的状态转换不一定发生在同一时刻,某些触发器的状态转换有可能会延迟. 在通信原理中也有同步与异步的概念 同步传输

浅谈TCP/IP网络编程中socket的行为

我认为,想要熟练掌握Linux下的TCP/IP网络编程,至少有三个层面的知识需要熟悉: . TCP/IP协议(如连接的建立和终止.重传和确认.滑动窗口和拥塞控制等等) . Socket I/O系统调用(重点如read/write),这是TCP/IP协议在应用层表现出来的行为. . 编写Performant, Scalable的服务器程序.包括多线程.IO Multiplexing.非阻塞.异步等各种技术. 关于TCP/IP协议,建议参考Richard Stevens的<TCP/IP Illust

网络编程中shut_down和close()函数的区别

在Linux C网络编程中,一共有两种方法来关闭一个已经连接好的网络通信,它们就是close函数和shutdown函数,它们的函数原型分别为: 1 #include<unistd.h> 2 int close(int sockfd) 3 //返回:0--成功, 1--失败 4   5 #include<sys/socket.h> 6 int shutdown(int sockfd, int howto) 7 //返回:0--成功, 1--失败 对一个tcp socket调用clos

关于网络编程中MTU、TCP、UDP、IP

名词解释: MTU(Maxium Transmission Unit)最大传输单元 TCP (Transmission Control Protocal)传输控制协议 UDP (Usage Datagram Protocal)用户数据报协议 IP (Internet Protocal) 因特网协议 TCP/IP协议,涉及到四层:链路层,网络层,传输层,应用层(TCP/IP是一个协议簇,并不是代表TCP协议和IP协议) 以太网(Ethemet)的数据帧在链路层 IP包在网络层 TCP或UDP包在传