《数据的IO和复用》PPT课件.ppt

上传人:桔**** 文档编号:568572969 上传时间:2024-07-25 格式:PPT 页数:37 大小:514.01KB
返回 下载 相关 举报
《数据的IO和复用》PPT课件.ppt_第1页
第1页 / 共37页
《数据的IO和复用》PPT课件.ppt_第2页
第2页 / 共37页
《数据的IO和复用》PPT课件.ppt_第3页
第3页 / 共37页
《数据的IO和复用》PPT课件.ppt_第4页
第4页 / 共37页
《数据的IO和复用》PPT课件.ppt_第5页
第5页 / 共37页
点击查看更多>>
资源描述

《《数据的IO和复用》PPT课件.ppt》由会员分享,可在线阅读,更多相关《《数据的IO和复用》PPT课件.ppt(37页珍藏版)》请在金锄头文库上搜索。

1、第第9 9章章 数据的数据的IOIO和复用和复用主要包含如下内容:主要包含如下内容:介绍常用的介绍常用的IO函数函数recv()/send()、readv()/writev()、recvmsg()/sendmsg(),并讲解函数的主要应用的场合,例如,并讲解函数的主要应用的场合,例如recvmsg()可以用于可以用于接收在多个缓冲区中,可以设置选项。接收在多个缓冲区中,可以设置选项。用几个简单的例子,说明如何使用上述函数进行程序的用几个简单的例子,说明如何使用上述函数进行程序的设计。设计。介绍常用的几种介绍常用的几种IO模型,以图形式的方法形象的进行了模型,以图形式的方法形象的进行了说明。说明

2、。介绍介绍select()和和pselect()函数、如何使用这两个函数进函数、如何使用这两个函数进行文件描述符读写条件的监视。行文件描述符读写条件的监视。简单介绍函数简单介绍函数poll()和和ppoll()的含义、使用和区别。的含义、使用和区别。以简单的例子介绍非阻塞编程的方法。以简单的例子介绍非阻塞编程的方法。9.1 IO9.1 IO函数函数Linux操作系统中的操作系统中的IO函数主要有函数主要有read()、write()、recv()、send()、recvmsg()、sendmsg()、readv()、writev()。本节对上述的主要函数进行介绍,其中的。本节对上述的主要函数进

3、行介绍,其中的read()和和write()函数在前面已经介绍过。函数在前面已经介绍过。9.1.1 9.1.1 使用使用recvrecv()()接收数据接收数据函数函数recv()用于接收数据,函数原型如下。函数用于接收数据,函数原型如下。函数recv()从套接字从套接字s中接收数据放到缓冲区中接收数据放到缓冲区buf中,中,buf的长度为的长度为len,操作的方式由操作的方式由flags指定。第一个参数指定。第一个参数s是套接口文件描述符,是套接口文件描述符,它是由系统调用它是由系统调用socket()返回的。第二个参数返回的。第二个参数buf是一个指是一个指针,指向接收网络数据的缓冲区。第

4、三个参数针,指向接收网络数据的缓冲区。第三个参数len表示接收表示接收缓冲区的大小,以字节为单位。缓冲区的大小,以字节为单位。#include #include ssize_t recv(int s, void *buf, size_t len, int flags);9.1.2 9.1.2 使用使用send()send()发送数据发送数据函数函数send()用于发送数据,函数原型如下。函数用于发送数据,函数原型如下。函数send()将缓冲区将缓冲区buf中大小为中大小为len的数据通过套接字文件描述符按照的数据通过套接字文件描述符按照flags指定的方式发送出去。当指定的方式发送出去。当se

5、nd函数的返回值小于函数的返回值小于len的的时候,表明缓冲区中仍然有部分数据没有成功发送,这时需时候,表明缓冲区中仍然有部分数据没有成功发送,这时需要重新发送剩余部分的数据。通常的剩余数据发送方法是对要重新发送剩余部分的数据。通常的剩余数据发送方法是对原来的原来的buf中的数据位置进行偏移,偏移的大小为以发送成中的数据位置进行偏移,偏移的大小为以发送成功的字节数。功的字节数。#include #include ssize_t send(int s, const void *buf, size_t len, int flags);9.1.2 9.1.2 使用使用send()send()发送数据

6、发送数据值含义EAGAIN/EWOULDBLOCK套接字定义为非阻塞,而操作采用了阻塞方式,或者定义的超时时间已经达到却没有接收到数据EBADF参数s不是合法描述符ECONNREFUSED远程主机不允许此操作EFAULT接收缓冲区指针在此进程之外EINTR在发送数据之前接收到中断信号EINVAL传递了不合法参数ENOTCONN套接字s表示流式套接字,此套接字没有连接ENOTSOCK参数不是套接字描述符ECONNRESET连接断开EDESTADDRREQ套接字没有处于连接状态ENOBUFS发送缓冲区已满ENOMEM没有足够内存EOPNOTSUPP设定的发送方式flag没有实现EPIPE套接字已经

7、关闭EACCES套接字不可写9.1.3 9.1.3 使用使用readvreadv()()接收数据接收数据函数函数readv()可用于接收多个缓冲区数据,函数原型如下。函数可用于接收多个缓冲区数据,函数原型如下。函数readv()从套接字描述符从套接字描述符s中读取中读取count块数据放到缓冲区向量块数据放到缓冲区向量vector中中#include ssize_t readv(int s, const struct iovec *vector, int count);值含义EAGAIN套接字定义为非阻塞,而操作采用了阻塞方式,或者定义的超时时间已经达到却没有接收到数据EBADF参数s不是合法

8、描述符ECONNREFUSED远程主机不允许此操作EFAULT接收缓冲区指针在此进程之外EINTR接收到中断信号EINVAL参数iov_len超出了ssize_t类型的范围,或者count参数小于0或者大于可允许最大值ENOTCONN套接字s表示流式套接字,此套接字没有连接ENOTSOCK参数不是套接字描述符9.1.3 9.1.3 使用使用readvreadv()()接收数据接收数据9.1.4 9.1.4 使用使用writevwritev()()发送数据发送数据函数函数writev()可用于接收多个缓冲区数据,函数原型如下。可用于接收多个缓冲区数据,函数原型如下。函数函数writev()向套接

9、字描述符向套接字描述符s中写入在向量中写入在向量vector中保存的中保存的count块数据。块数据。#include ssize_t writev(int fd, const struct iovec *vector, int count);9.1.5 9.1.5 使用使用recvmsgrecvmsg()()接收数据接收数据函数函数recvmsg()用于接收数据,与用于接收数据,与recv()函数、函数、readv()函数相比较,这个函数的使用要复杂一些。函数相比较,这个函数的使用要复杂一些。1函数函数recvmsg()原型含义原型含义2地址结构地址结构msghdr3函数函数recvmsg(

10、)用户空间与内核空间的交互用户空间与内核空间的交互9.1.5 9.1.5 使用使用recvmsgrecvmsg()()接收数据接收数据9.1.6 9.1.6 使用使用sendmsgsendmsg()()发送数据发送数据函数函数sendmsg()可用于接收多个缓冲区数据,函数原型如可用于接收多个缓冲区数据,函数原型如下。函数下。函数sendmsg()向套接字描述符向套接字描述符s中按照结构中按照结构msg的设定的设定写入数据,其中操作方式有写入数据,其中操作方式有flags指定。指定。#include ssize_t sendmsg(int s, const struct msghdr *msg

11、, int flags);9.1.7 IO9.1.7 IO函数的比较函数的比较表表9.8为上述函数使用时的特点,为上述函数使用时的特点,标记的为具有此种属标记的为具有此种属性。有如下规律性。有如下规律函数函数read()/write()和和readv()/writev()可以对所有的文件可以对所有的文件描述符使用;描述符使用;recv()/send()、recvfrom()/writeto()和和recvmsg/sendmsg只能操作套接字描述符。只能操作套接字描述符。函数函数readv()/writev()和和recvmsg()/sendmsg()可以操作可以操作多个缓冲区,多个缓冲区,re

12、ad()/write()、recv()/send()和和recvfrom()/sendto()只能操作单个缓冲区。只能操作单个缓冲区。函数函数recv()/send()、recvfrom()/sendto()和和recvmsg()/sendmsg()具有可选标志。具有可选标志。函数函数recvfrom()/sendto()和和recvmsg()/sendmsg()可以可以选择对方的选择对方的IP地址。地址。函数函数recvmsg()/sendmsg()有可选择的控制信心,能进有可选择的控制信心,能进行高级操作。行高级操作。9.1.7 IO9.1.7 IO函数的比较函数的比较名称任何描述符只对套

13、接字描述符单个缓冲区多个缓冲区可选标志可选对方地址可选控制信息read()/write()readv()/writev()recv()/send()recvfrom()/writeto()recvmsg()/sendmsg()9.2 9.2 使用使用IOIO函数的例子函数的例子小节小节9.1中对典型的中对典型的IO函数进行了介绍,本小节中针对函数进行了介绍,本小节中针对上述的函数给出程序设计的例子。包括典型的上述的函数给出程序设计的例子。包括典型的send()/recv()、writev()/readv()、sendmsg()/recvmsg()三种类型。三种类型。9.2.1 9.2.1 客户

14、端处理框架例子客户端处理框架例子客户端处理程序是一个程序框架,为后面的使用三种类客户端处理程序是一个程序框架,为后面的使用三种类型的收发函数建立基本的架构。型的收发函数建立基本的架构。1客户端程序框架客户端程序框架2客户端程序框架代码客户端程序框架代码9.2.1 9.2.1 客户端处理框架例子客户端处理框架例子9.2.2 9.2.2 服务器端程序框架服务器端程序框架服务器端处理程序是一个程序框架,为后面的使用三种服务器端处理程序是一个程序框架,为后面的使用三种类型的收发函数建立基本的架构。函数类型的收发函数建立基本的架构。函数process_conn_server()是进行服务器端处理的函数,

15、不同的收发函数的实现不同。是进行服务器端处理的函数,不同的收发函数的实现不同。9.2.3 9.2.3 使用使用recvrecv()()和和send()send()函数函数下面的代码是使用下面的代码是使用recv()和和send()函数进行网络数据收函数进行网络数据收发时服务器和客户端的实现代码。发时服务器和客户端的实现代码。1服务器端的实现代码服务器端的实现代码2客户端处理代码客户端处理代码3信号信号SIGINT处理函数处理函数4信号信号SIGPIPE的处理函数的处理函数9.2.4 9.2.4 使用使用readvreadv()()和和write()write()函数函数使用如下的代码代替使用如

16、下的代码代替9.2.1中的函数中的函数process_conn_server()和和process_conn_client(),使用,使用readv()和和writev()进行读进行读写。写。1服务器端的实现代码服务器端的实现代码2客户端处理代码客户端处理代码3信号信号SIGINT处理函数处理函数4信号信号SIGPIPE的处理函数的处理函数9.2.5 9.2.5 使用使用recvmsgrecvmsg()()和和sendmsgsendmsg()()函数函数使用如下的代码代替使用如下的代码代替9.2.1中的函数中的函数process_conn_server()和和process_conn_clie

17、nt(),使用,使用recvmsg()和和sendmsg()进行读写。进行读写。1服务器端的实现代码服务器端的实现代码2客户端处理代码客户端处理代码3信号信号SIGINT处理函数处理函数4信号信号SIGPIPE的处理函数的处理函数9.3. IO9.3. IO模型模型IO的方式有阻塞的方式有阻塞IO、非阻塞、非阻塞IO模型、模型、IO复用、信号驱复用、信号驱动、异步动、异步IO等,本节中以等,本节中以UDP为例介绍为例介绍IO的几种模型。的几种模型。9.3.1 9.3.1 阻塞阻塞IOIO模型模型阻塞阻塞IO是最通用的是最通用的IO类型,使用这种模型进行数据接类型,使用这种模型进行数据接收的时候

18、,在数据没有到之前程序会一直等待。收的时候,在数据没有到之前程序会一直等待。9.3.2 9.3.2 非阻塞非阻塞IOIO模型模型当把套接字设置成非阻塞的当把套接字设置成非阻塞的IO,则对每次请求,内核,则对每次请求,内核都不会阻塞,会立即返回;当没有数据的时候,会返回一个都不会阻塞,会立即返回;当没有数据的时候,会返回一个错误。错误。9.3.3 IO9.3.3 IO复用复用使用使用IO复用模型可以在等待的时候加入超时的时间,当复用模型可以在等待的时候加入超时的时间,当超时时间没有到达的时候与阻塞的情况一致,而当超时时间超时时间没有到达的时候与阻塞的情况一致,而当超时时间到达仍然没有数据接收到,

19、系统会返回,不再等待。到达仍然没有数据接收到,系统会返回,不再等待。select()函数按照一定的超时时间轮询,直到需要等待函数按照一定的超时时间轮询,直到需要等待的套接字有数据到来,利用的套接字有数据到来,利用recvfrom()函数,将数据复制到函数,将数据复制到应用层。应用层。9.3.4 9.3.4 信号驱动信号驱动IOIO模型模型信号驱动的信号驱动的IO在进程开始的时候注册一个信号处理的在进程开始的时候注册一个信号处理的回调函数,进程继续执行,当信号发生时,即有了回调函数,进程继续执行,当信号发生时,即有了IO的时间,的时间,这里即有数据到来,利用注册的回调函数将到来的函数用这里即有数

20、据到来,利用注册的回调函数将到来的函数用recvfrom()接收到。接收到。9.3.5 9.3.5 异步异步IOIO模型模型异步异步IO与前面的信号驱动与前面的信号驱动IO相似,其区别在于信号驱相似,其区别在于信号驱动动IO当数据到来的时候,使用信号通知注册的信号处理函数,当数据到来的时候,使用信号通知注册的信号处理函数,而异步而异步IO则在数据复制完成的时候才发送信号通知注册的信则在数据复制完成的时候才发送信号通知注册的信号处理函数。号处理函数。9.4 select()9.4 select()和和pselectpselect()()函数函数函数函数select()和和pselect()用于用

21、于IO复用,它们监视多个文复用,它们监视多个文件描述符的集合,判断是否有符合条件的时间发生。件描述符的集合,判断是否有符合条件的时间发生。9.4.1 select()9.4.1 select()函数函数函数函数select()与之前的与之前的recv()和和send()直接操作文件描述符不同。直接操作文件描述符不同。使用使用select()函数可以先对需要操作的文件描述符进行查询,查看是函数可以先对需要操作的文件描述符进行查询,查看是否目标文件描述符可以进行读、写或者错误操作,然后当文件描述符否目标文件描述符可以进行读、写或者错误操作,然后当文件描述符满足操作的条件的时候才进行真正的满足操作的

22、条件的时候才进行真正的IO操作。操作。1函数函数select()简介简介2函数函数select()的例子的例子值含义EBADF参数s不是合法描述符EINTR接收到中断信号EINVAL传递了不合法参数ENOMEM没有足够内存9.4.2 9.4.2 pselectpselect()()函数函数函数函数select()是用一种超时轮循的方式来查看文件的读是用一种超时轮循的方式来查看文件的读写错误可操作性。在写错误可操作性。在Linux下,还有一个相似的函数下,还有一个相似的函数pselect()。1函数函数pselect()简介简介2函数函数pselect()的例子的例子9.5 poll()9.5

23、poll()函数函数除了使用除了使用select()进行文件描述符的监视,还有一组函进行文件描述符的监视,还有一组函数也可以完成相似的功能,即函数数也可以完成相似的功能,即函数poll()和函数和函数ppoll()。9.5.1 poll()9.5.1 poll()函数函数函数函数poll()等待某个文件描述符上的某个事件的发生。等待某个文件描述符上的某个事件的发生。其原型如下:其原型如下: #include int poll(struct pollfd *fds, nfds_t nfds, int timeout);函数函数poll()监视在监视在fds数组指明的一组文件描述符上发生数组指明的

24、一组文件描述符上发生的动作,当满足条件或者超时的时候会退出。的动作,当满足条件或者超时的时候会退出。参数参数fds是一个指向结构是一个指向结构pollfd数组的指针,监视的文数组的指针,监视的文件描述符和条件放在里面。件描述符和条件放在里面。参数参数nfds,是比监视的最大描述符的值大,是比监视的最大描述符的值大1的值。的值。参数参数timeout,是超时时间,单位为毫秒,当为负值时,是超时时间,单位为毫秒,当为负值时,表示永远等待。表示永远等待。9.5.1 poll()9.5.1 poll()函数函数值含义EBADF参数s不是合法描述符EINTR接收到中断信号EINVAL传递了不合法参数EN

25、OMEM没有足够内存值含义POLLIN有数据到来,文件描述符可读POLLPRI有紧急数据可读,例如带外数据POLLOUT文件可写POLLRDHUP流式套接字半关闭POLLERR错误发生POLLHUP关闭POLLNVAL非法请求POLLRDNORM与POLLIN相同POLLRDBAND优先数据可读POLLWRNORM与POLLOUT相同POLLWRBAND优先数据可写9.5.2 9.5.2 ppollppoll()()函数函数与与select()和和pselect()的情况相似,与的情况相似,与poll()对应的也对应的也存在一个存在一个ppoll()函数,其定义如下:函数,其定义如下: #in

26、clude int ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout, const sigset_t *sigmask);9.6 9.6 非阻塞编程非阻塞编程前面介绍的前面介绍的IO程序设计,基本上都是基于阻塞方式的。程序设计,基本上都是基于阻塞方式的。阻塞方式的读写,在文件没有数据的时候,函数不会返回,阻塞方式的读写,在文件没有数据的时候,函数不会返回,而一直等待直到有数据到来。本节介绍文件的非阻塞方式程而一直等待直到有数据到来。本节介绍文件的非阻塞方式程序设计。序设计。9.6.1 9.6.1 非阻塞方

27、式程序设计介绍非阻塞方式程序设计介绍非阻塞方式的操作与阻塞方式的操作最大的不同点是函非阻塞方式的操作与阻塞方式的操作最大的不同点是函数的调用立刻返回,不管数据是否成功读取或者成功写入。数的调用立刻返回,不管数据是否成功读取或者成功写入。使用使用fcntl()将套接字文件描述符按照如下的代码进行设置后,将套接字文件描述符按照如下的代码进行设置后,可以进行非阻塞的编程:可以进行非阻塞的编程:fcntl(s, F_SETFL, O_NONBLOCK);其中的其中的s是套接字文件描述符,使用是套接字文件描述符,使用F_SETFL命令将套命令将套接字接字s设置为非阻塞方式后,再进行读写操作就可以马上返设

28、置为非阻塞方式后,再进行读写操作就可以马上返回了。回了。9.6.2 9.6.2 非阻塞程序设计的例子非阻塞程序设计的例子函数函数accept()可以使用非阻塞的方式轮询等待客户端的可以使用非阻塞的方式轮询等待客户端的到来,在之前要设置到来,在之前要设置NON_BLOCK方式。下面的代码使用方式。下面的代码使用了轮询的方式使用了轮询的方式使用accept()和和recv()函数,当客户端发送函数,当客户端发送“HELLO”字符串时,发送字符串时,发送“OK”响应给客户端并关闭客户响应给客户端并关闭客户端;当客户端发送端;当客户端发送“SHUTDOWN”字符串给服务器时,服务器字符串给服务器时,服

29、务器发送发送“BYE”的客户端,并关闭客户端,然后退出程序。的客户端,并关闭客户端,然后退出程序。9.7 9.7 小结小结本章对数据本章对数据IO进行了介绍。介绍了进行了介绍。介绍了recv()、send()、readv()、writev()、recvmsg()和和sendmsg()等函数的使用,并给等函数的使用,并给出了多个例子。介绍了出了多个例子。介绍了IO模型:阻塞模型:阻塞IO模型、非阻塞模型、非阻塞IO模型、模型、IO服用、信号驱动服用、信号驱动IO模型和异步模型和异步IO模型。模型。select()函数、函数、pselect()函数和函数和poll()函数在查询方式程序设计中经常使用,而函数在查询方式程序设计中经常使用,而fcntl()函数的函数的O_NONBLOCK选项则是进行非阻塞编程中经常使选项则是进行非阻塞编程中经常使用的设置方法。用的设置方法。

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 高等教育 > 研究生课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号