Socket编程实践(10) --5种I/O模型

阻塞I/O

说明1:当上层应用Application1调用recv系统调用时,如果对等方没有发送数据(Linux内核缓冲区中没有数据),上层应用Application1将阻塞[默认:被Linux内核阻塞)

说明2:当对等方发送了数据,Linux内核recv端缓冲区数据到达,内核会把数据copy给用户空间。然后上层应用Application1解除阻塞,执行下一步操作。

非阻塞I/O

说明1: 上层应用程序Application2将套接字设置成非阻塞模式。

说明2: 上层应用程序Application2轮询调用recv函数,接受数据。若缓冲区没有数据,上层程序Application2不会阻塞,recv返回值为-1,错误码是EWOULDBLOCK。

说明3:上层应用程序不断轮询有没有数据到来。造成上层应用忙等待。大量消耗CPU。很少直接用。应用范围小,一般和select IO复用配合使用。

I/O多路复用[重点]

说明1: 上层应用程序Application3调用select(该机制由Linux内核支持,避免了Application3忙等待),进行轮询文件描述符的状态变化。

说明2:当select管理的文件描述符没有数据(或者状态没有变化时),上层应用程序Application3也会阻塞。

说明3:好处是:select机制可以管理多个文件描述符

说明4:select可以看成一个管理者,用select来管理多个IO。

一旦检测到的一个I/O或者多个IO,有我们感兴事件发生时,select函数将返回,返回值为检测到的事件个数。进而可以利用select相关API函数,操作具体事件。

说明5:select函数可以设置等待时间,避免了上层应用程序Application3长期僵死。

说明6: 和阻塞IO模型相比,selectI/O复用模型相当于提前阻塞了。等到有数据到来时,再调用recv就不会发生阻塞。

信号驱动I/O

说明1: 上层应用程序Application4建立SIGIO信号处理程序。当缓冲区有数据到来,内核会发送信号告诉上层应用程序Application4。

说明2:上层应用程序Application4接收到信号后,调用recv函数,因缓冲区有数据,recv函数一般不会阻塞。

说明3:这种用于模型用的比较少,属于典型的“拉模式(上层应用被动的去Linux内核空间中拉数据)”。即:上层应用Application4,需要调用recv函数把数据拉进来,会有时间延迟,我们无法避免在延迟时,会又有新的信号的产生。

异步I/O[重点]

说明1:上层应用程序Application5调用aio_read函数,同时提交一个应用层的缓冲区buf;调用完毕后,不会阻塞。上层应用程序Application5可以继续其他任务。

说明2:当TCP/IP协议缓冲区有数据时,Linux主动的把内核数据copy到用户空间。然后再给上层应用Application5发送信号;告诉Application5数据到来,需要处理!

说明3:典型的“推模式”

说明4: 效率最高的一种模式,上层应用程序Application5有异步处理的能力(在Linux内核的支持下,处理其他任务的同时,也可支持IO通讯)。

异步I/O是指什么?

上层应用程序Application5,在进行其他任务的同时时,也可以接收数据(接受异步通信事件)。而且上层应用程序并不需要调用recv函数

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

Socket编程实践(10) --5种I/O模型的相关文章

Socket编程实践(10) --select的限制与poll的使用

select的限制 用select实现的并发服务器,能达到的并发数一般受两方面限制: 1)一个进程能打开的最大文件描述符限制.这可以通过调整内核参数.可以通过ulimit -n(number)来调整或者使用setrlimit函数设置,但一个系统所能打开的最大数也是有限的,跟内存大小有关,可以通过cat /proc/sys/fs/file-max 查看 /**示例: getrlimit/setrlimit获取/设置进程打开文件数目**/ int main() { struct rlimit rl;

Socket编程实践(6) --TCPNotes服务器

僵尸进程过程 1)通过忽略SIGCHLD信号,避免僵尸进程 在server端代码中加入 signal(SIGCHLD, SIG_IGN); 2)通过wait/waitpid方法.解决僵尸进程 signal(SIGCHLD,onSignalCatch); void onSignalCatch(int signalNumber) { wait(NULL); } 3) 假设多个客户端同一时候关闭, 问题描写叙述如以下两幅图所看到的: watermark/2/text/aHR0cDovL2Jsb2cuY

Socket编程实践(6) --TCP服务端注意事项

僵尸进程处理 1)通过忽略SIGCHLD信号,避免僵尸进程 在server端代码中添加 signal(SIGCHLD, SIG_IGN); 2)通过wait/waitpid方法,解决僵尸进程 signal(SIGCHLD,onSignalCatch); void onSignalCatch(int signalNumber) { wait(NULL); } 3) 如果多个客户端同时关闭, 问题描述如下面两幅图所示: /** client端实现的测试代码**/ int main() { int s

Socket编程实践(19) --Socket API封装(2)

注:这一片博客与下一篇博客<Socket编程实践(20)>合为一篇,由于代码较多,所以分为两篇,本篇为上篇,主要讲解前一篇讲解的Socket类的增强,下一篇主要讲解怎样使用这个增强版的Socket类(ServerSocket/ClientSocket类的实现与使用)! 思想来源: 1)http://www.cnblogs.com/-Lei/archive/2012/09/04/2670964.html 2)http://blog.csdn.net/column/details/linux66.

Socket编程实践(20) --Socket API封装(3)

注:这一片博客与上一篇博客<Socket编程实践(19)>合为一篇,由于代码较多,所以分为两篇,本篇为下篇,这一篇主要讲解怎样使用上一篇开发的增强版的Socket类(ServerSocket/ClientSocket类的实现与使用)! 思想来源: 1)http://www.cnblogs.com/-Lei/archive/2012/09/04/2670964.html 2)http://blog.csdn.net/column/details/linux66.html 3)http://blo

Socket编程实践(6) --TCP粘包原因与解决

流协议与粘包 粘包的表现 Host A 发送数据给 Host B; 而Host B 接收数据的方式不确定 粘包产生的原因 说明 TCP 字节流,无边界 对等方,一次读操作,不能保证完全把消息读完 UDP 数据报,有边界 对方接受数据包的个数是不确定的 产生粘包问题的原因分析 1.SQ_SNDBUF 套接字本身有缓冲区 (发送缓冲区.接受缓冲区) 2.tcp传送的端 mss大小限制 3.链路层也有MTU大小限制,如果数据包大于>MTU要在IP层进行分片,导致消息分割. 4.tcp的流量控制和拥塞控

Socket编程实践(7)   --TCP粘包解决方法2

包尾加\n编程实践 SYNOPSIS #include <sys/types.h> #include <sys/socket.h> ssize_t recv(int sockfd, void *buf, size_t len, int flags); 与read相比,只能用于套接字文件描述符,而且多了一个flags Flags常用取值: MSG_OOB(紧急指针,带外数据) This flag requests receipt of out-of-band data that wo

Socket编程实践(8) --Select-I/O复用

五种I/O模型介绍 (1)堵塞I/O[默认] 当上层应用App调用recv系统调用时,假设对等方没有发送数据(Linux内核缓冲区中没有数据),上层应用Application1将堵塞;当对等方发送了数据,Linux内核recv端缓冲区数据到达,内核会把数据copy给用户空间. 然后上层应用App解除堵塞,运行下一步操作. (2)非堵塞I/O[少用] 上层应用App将套接字设置成非堵塞模式, 然后循环调用recv函数.接受数据. 若缓冲区没有数据.上层应用不会堵塞.recv返回值为-1,错误码是E

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

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