UDP+IO模型

 
<sys/types.h> 基本系统数据类型
是Unix/Linux系统的基本系统数据类型的头文件,含有size_t,time_t,pid_t等类型。linux编程中经常用到的头文件。
一、UDP通信模型
recvfrom
sendto
注意:UDP中使用connect( tcp里的发起连接请求 )并没有连接的概念,connect函数将对端的IP + port保存在内核当中
 
二、总结
 
三、UDP服务器模型
(1)UDP循环服务器模型
与TCP循环服务器模型类型,一次只能处理一个客户端
不同之处在于不会出现一个客户端独占服务器的情况
(2)UDP并发服务器模型
人们把并发的概念用于UDP就得到了UDP并发服务器模型。
UDP并发服务器模型TCP服务器模型一样,创建一个子进程来处理客户端的请求
 
除非UDP服务器在处理某个客户端的请求时所用的时间比较长,人们实际上较少用这种模型。
close(sockfd);的作用可以用 close-on-exec实现
父进程里int sockfd = socket(PF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
四、I/O模型
Linux上的文本操作不同模型的效率
在UNIX/Linux下主要有5种I/O 模型
针对单个设备:
阻塞IO模型
非阻塞IO模型
信号驱动IO模型
异步IO模型
针对多个设备:
IO多路复用模型
 
数据从内核准备好再转移到用户态的过程,一般分为两个阶段,
  1. 第一个是等待io就绪,
  2. 第二个是数据在内核空间和用户空间之间的移动。
对这两个阶段的不同处理策略导致了不同的IO模型定义,并最终导致不同的IO读写处理效率。
-------------------------------------------------------------------------------------------------------------------------------------
(1)阻塞IO模型
第一阶段:阻塞方式等待IO就绪
第二阶段:用户自己调用系统调用搬运数据
阻塞模型
read属于哪个阶段?还是指两个阶段的组合??看非阻塞模型
 
-------------------------------------------------------------------------------------------------------------------------------------
(2)非阻塞IO模型
第一个阶段:非阻塞轮询的方式等待IO就绪
第二个阶段:用户自己调用系统调用搬运数据
 
优点:相较于阻塞IO模型,进程有机会做其他的事情
缺点:循环调用系统调用,消耗CPU资源,效率低
消耗CPU资源( 中断现场?
fcntl(2)常看看 ioctl
F_SETFD:设置close-on-exec 标志值( 我不确定
F_GETFL 文件 状态 标志的值
F_GETSIG: 当读取或写入时发送的信号的值变为可能,或对于传统的SIGIO行为来说是零。
F_SETOWN:设置接受SIGIO信号的进程标志.
fcntl(sockfd, F_SETOWN, getpid());
close-on-exec以下( 因为socket灭有没有文件状态标志设置接口
每个文件描述符都有一个close-on-exec标志。默认情况下,这个标志最后一位被设置为 0。这个标志符的具体作用在于当开辟其他进程调用exec()族函数时,在调用exec函数之前为exec族函数释放对应的文件描述符
父子进程中的端口占用情况。父进程监听一个端口后,fork出一个子进程,然后kill掉父进程,再重启父进程,这个时候提示端口占用,用netstat查看,子进程占用了父进程监听的端口。
原理其实很简单,子进程在fork出来的时候,使用了写时复制(COW,Copy-On-Write)方式获得父进程的数据空间、 堆和栈副本,这其中也包括文件描述符。刚刚fork成功时,父子进程中相同的文件描述符指向系统文件表中的同一项(这也意味着他们共享同一文件偏移量)。这其中当然也包含父进程创建的socket。
接着,一般我们会调用exec执行另一个程序,此时会用全新的程序替换子进程的正文,数据,堆和栈等。此时保存文件描述符的变量当然也不存在了,我们就无法关闭无用的文件描述符了。所以通常我们会fork子进程后在子进程中直接执行close关掉无用的文件描述符,然后再执行exec。
但是在复杂系统中,有时我们fork子进程时已经不知道打开了多少个文件描述符(包括socket句柄等),这此时进行逐一清理确实有很大难度。我们期望的是能在fork子进程前打开某个文件句柄时就指定好:“这个句柄我在fork子进程后执行exec时就关闭”。其实时有这样的方法的:即所谓 的 close-on-exec。
回到我们的应用场景中来,只要我们在创建socket的时候加上 SOCK_CLOEXEC 标志,就能够达到我们要求的效果,在fork子进程中执行exec的时候,会清理掉父进程创建的socket。
int sockfd = socket(PF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
也可以用fcntl来修改文件状态标志
fcntl(fd, F_SETFD, 1) 此句将fd的close-on-exec 标志设置为1,开启 SOCK_CLOEXEC
fcntl(fd, F_SETFD, 0) 此句将fd的close-on-exec 标志设置为0,关闭 SOCK_CLOEXEC
需要在父进程就开启,只子进程开启的话,只能在孙进程生效了
socket非阻塞模式的实现:
fd = open("filename", O_RDWR | O_CREAT | O_TRUNC | O_NONBLOCK, 0666);
sockfd = socket (没有文件状态标志设置接口)
fcntl 操作(文件设置),管理文件描述符
setsockopt (套接字设置)
 
#include <unistd.h>
#include <fcntl.h>
 
int fcntl(int fd, int cmd, ... /* arg */ );
  1. fd : 需要操作的文件描述符
  2. cmd : 操作文件描述的指令
  3. arg : 可变参
 
step 1: 先获取原先的文件状态标志(F_GETFL,获取文件状态标志)
int flag;
flag = fcntl(sockfd, F_GETFL); (返回值就是获取的文件状态标志)
step 2:将O_NONBLOCK标志( 非阻塞标识)加入到文件状态标志
flag = flag | O_NONBLOCK;
step 3:重新设置文件状态标志(F_SETFL, 设置文件状态标志)
fcntl(sockfd, F_SETFL, flag); (通过第三个参数flag来制定需要设置的文件状态标志)
-------------------------------------------------------------------------------------------------------------------------------------
(3)信号驱动IO模型(SIGIO)
第一个阶段:非阻塞异步方式等待IO就绪
第二个阶段:用户自己调用系统调用搬运数据
 
优点:改进了第一个阶段,是第一个阶段变成异步的
缺点:没有改进第二个阶段
因为进程-----内核,都参与工作,才实现了异步
信号驱动IO实现:
step 1:设置SIGIO信号的信号处理函数
signal(SIGIO, signalhanler);
step 2:设置接受SIGIO信号的进程 fcntl ( F_SETOWN ,设置接受SIGIO信号的进程标志
fcntl(sockfd, F_SETOWN, getpid()); ( 根据第三个参数制定进程号
step 3:产生SIGIO信号 O_ASYNC( 开启信号驱动IO模型
int flag;
flag = fcntl(sockfd, F_GETFL); ( 返回值就是获取的文件状态标志)(F_GETFL,获取文件状态标志)
flag = flag | O_ASYNC; ( 将O_ASYNC标志加入到文件状态标志)
fcntl(sockfd, F_SETFL, flag); ( 通过第三个参数flag来制定需要设置的文件状态标志(F_SETFL, 设置文件状态标志))
-------------------------------------------------------------------------------------------------------------------------------------
(4)异步io模型
 
-------------------------------------------------------------------------------------------------------------------------------------
(5)多路复用IO模型
 
调用的函数是:
实现:
 
加1指最多文件描述个数
 
timeout
<select.h>
 
 
 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值