第14章——高级IO函数
1.套接字超时
套接字IO函数设置超时的方法有三种:
(1)调用alarm。
(2)select
(3)使用SO_RECTIMEO和 SO_SNDTIMEO 选项
上面三种方法适用于输入输出操作(read , write, sendto , recvfrom ..)
(1)(2)适用于所有文件描述符,(3)适用于套接字
connect 内置超时时间很长(典型为75秒),select可用于connect的前提是对应套接字处于 非阻塞模式。(3)不适于connect。
2.一些设置超时示例
2.1 使用alarm
涉及信号就避免多线程,信号本身适中全局资源,所以要注意对其他信号使用的影响
int
connect_timeo(int sockfd, const SA *saptr, socklen_t salen, int nsec)
{
Sigfunc *sigfunc;
int n; sigfunc = Signal(SIGALRM, connect_alarm);
if (alarm(nsec) != 0)
err_msg("connect_timeo: alarm was already set"); if ( (n = connect(sockfd, saptr, salen)) < 0) {
close(sockfd);
if (errno == EINTR)
errno = ETIMEDOUT;
}
alarm(0); /* turn off the alarm */
Signal(SIGALRM, sigfunc); /* restore previous signal handler */ return(n);
} static void
connect_alarm(int signo)
{
return; /* just interrupt the connect() */
}
void
dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)
{
int n;
char sendline[MAXLINE], recvline[MAXLINE + 1]; Signal(SIGALRM, sig_alrm); while (Fgets(sendline, MAXLINE, fp) != NULL) { Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen); alarm(5);
if ( (n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL)) < 0) {
if (errno == EINTR)
fprintf(stderr, "socket timeout\n");
else
err_sys("recvfrom error");
} else {
alarm(0);
recvline[n] = 0; /* null terminate */
Fputs(recvline, stdout);
}
}
} static void
sig_alrm(int signo)
{
return; /* just interrupt the recvfrom() */
}
2.2 使用select
int
readable_timeo(int fd, int sec)
{
fd_set rset;
struct timeval tv; FD_ZERO(&rset);
FD_SET(fd, &rset); tv.tv_sec = sec;
tv.tv_usec = 0; return(select(fd+1, &rset, NULL, NULL, &tv));
/* 4> 0 if descriptor is readable */
}
/* end readable_timeo */
2.3 使用SO_RCVTIMEO
void
dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)
{
int n;
char sendline[MAXLINE], recvline[MAXLINE + 1];
struct timeval tv; tv.tv_sec = 5;
tv.tv_usec = 0;
Setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); while (Fgets(sendline, MAXLINE, fp) != NULL) { Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen); n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);
if (n < 0) {
if (errno == EWOULDBLOCK) {
fprintf(stderr, "socket timeout\n");
continue;
} else
err_sys("recvfrom error");
} recvline[n] = 0; /* null terminate */
Fputs(recvline, stdout);
}
}
3. recv 和 send 函数
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
特别的是flags参数:

MSG_DONTROUTE:
和SO_DONTROUTE的套接字选项类似,SO_DONTROUTE是修改套接字到达长期有效,MSG_DONTROUTE是单次有效。
根据IPv4的正常机制,IP分组需要根据目的地址和路由表找到适当本地接口,如果无法确定本地接口,就会报错。
可以使用本选项,以绕过上述机制,强制从某个接口发出。路由守护进程就是这么做的。
MSG_DONTWAIT
临时打开非阻塞标志,进行IO,关闭非阻塞标志
MSG_OOB
让本次调用,用于接受或发送带外数据。
TCP连接上有一个字节可以作为带外数据发送。带外数据是加急数据。
MSG_PEEK
允许查看可读数据,且recv或recvfrom返回后,该数据仍然在缓冲区,不被丢弃。
MSG_WAITALL
通知内核,在尚未读到全部指定数量的数据前不返回。这样就可以简化readnzz
#define readn(fd, ptr, n) recv(fd, ptr, n, MSG_WAITALL)
即使这样,也有可能读到少的数据:(a)信号中断,(b)连接终止(c)套接字错误
4. writev 和 readv
ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
ssize_t writev(int fd, const struct iovec *iov, int iovcnt); struct iovec {
void *iov_base; /* Starting address */
size_t iov_len; /* Number of bytes to transfer */
};
这两个函数的作用是:
集中写:将应用程序多个缓冲区的数据,集中提供给单个写操作。
分散读:将读操作的数据,分散到多个应用程序缓冲。
由于writev是原子操作,对于UDP而言,一次writev多个缓冲区数据,只发送一个UDP报文。
对于TCP而言,通过writev将多个缓冲区放到一个分组发出,避免触发 Nagle 算法。
5. 排队数据量
(1)使用非阻塞IO,可以避免没有数据时的阻塞。
(2)既想查看数据,又不想取出数据,可以用MSG_PEEK,又不希望数据没到达的阻塞,可以加MSG_DONTWAIT。对于TCP,MSG_PEEK读到的数据量和之后读到的数据量是可能不同,因为可能有新的数据来了,对于UDP,两次读到的数据量相同。
第14章——高级IO函数的更多相关文章
- 第14章高级IO总结
1 低速系统调用 可能使进程永远阻塞的一类系统调用,包括: 1)读某些文件类型(管道.终端.网络设备)的数据 2)写某些文件类型(管道.终端.网络设备),但数据不能被立即接受(管道中无空间.流量控制等 ...
- APUE读书笔记-第14章-高级I/O
14.1 引言 *高级I/O包括非阻塞I/O.记录锁.系统V流机制.I/O多路转换(select和poll函数).readv和writev函数以及存储映射I/O(mmap) 14.2 非阻塞I/O * ...
- MySQL基础之第14章 存储过程和函数
避免编写重复的语句 安全性可控 执行效率高 14.1.创建存储过程和函数 14.1.1.创建存储过程 CREATE PROCEDUREsp_name ([proc_parameter[,...]]) ...
- UNIX环境高级编程 第14章 高级I/O
这一章涉及很多概念和函数,包括:非阻塞I/O.记录锁.I/O复用.异步I/O.readv和writev函数以及内存映射. 非阻塞I/O 在Unix中,可以将系统调用分为两种,一种是“低速”系统调用,另 ...
- 6 高级IO函数
6.1 pipe函数 pipe函数创建一个管道,用于实现进程间通信 #include<unistd.h> ]); 参数包含两个文件描述符fd[0]和fd[1],往fd[1]写入的数据可以从 ...
- 《Unix 网络编程》14:高级 I/O 函数
高级 I/O 函数 ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ...
- JavaScript高级程序设计(第三版)学习笔记13、14章
第13章,事件 事件冒泡 IE的事件叫做事件冒泡:由具体到不具体 <!DOCTYPE html> <html> <head> <title>E ...
- UNIX高级环境编程(6)标准IO函数库 - 流的概念和操作
标准IO函数库隐藏了buffer大小和分配的细节,使得我们可以不用关心预分配的内存大小是否正确的问题. 虽然这使得这个函数库很容易用,但是如果我们对函数的原理不熟悉的话,也容易遇到很多问题. 1 ...
- 第六章 高级I/O函数
第六章 高级I/O函数 6.1 pipe函数 即管道函数,用于进程间的通信. #include<unistd.h> int pipe(int fd[2]); // fd:filedes / ...
随机推荐
- MeteoInfoLab脚本示例:FY-2C 云分类HDF数据
脚本程序: #Add data file fn = 'D:/Temp/hdf/FY2C_CLC_MLT_NOM_20070730_1800.hdf' f = addfile(fn) #Get data ...
- [论文阅读]阿里DIN深度兴趣网络之总体解读
[论文阅读]阿里DIN深度兴趣网络之总体解读 目录 [论文阅读]阿里DIN深度兴趣网络之总体解读 0x00 摘要 0x01 论文概要 1.1 概括 1.2 文章信息 1.3 核心观点 1.4 名词解释 ...
- 【学习笔记】Min-max 容斥
经常和概率期望题相结合. 对于全序集合 \(S\),有: \[\max S=\sum\limits_{T\subseteq S,T\not=\varnothing}(-1)^{\vert T\vert ...
- 【Azure云服务 Cloud Service】Cloud Service的实例(VM)中的服务描述Software Protection 与 Windows Defender, 如何设置Windows Defender Antivirus服务
1)Software Protection 与 Windows Defender是两个独立的服务.在Windows 服务中他们的描述分别为 Software Protection Enables th ...
- Helium文档8-WebUI自动化-wait_until等待元素出现
前言 wait_until等待某个条件为真才继续往下执行.默认的超时时间为10s,每0.5查询一次,这俩参数选填.可以设置超时时间和轮询间隔. 可以作为添加后校验元素是否存在的场景 入参介绍 def ...
- Vulkan Driver for VC4(Raspberry Pi 3b) base on mesa
这是一篇关于在raspberry Pi 3b上移植实现vulkan 驱动的文章. 经过一段时间的代码搬运,终于实现了零的突破,可以在树莓派3B上运行Vulkan triangle/texture.当然 ...
- 自定义Jackson2HttpMessageConverter,适应.html后缀url
Jackson2HttpMessageConverter 用处 SpringMVC中,controller中的方法返回java Bean对象,mvc将此对象转换成字符串 默认支持的mediaType: ...
- (CVPR 2019)The better version of SRMD
CVPR2019的文章,解决SRMD的诸多问题, 并进行模拟实验. 进行双三次差值(bicubic)===>对应matlab imresize() %% read images im = {}; ...
- STM32入门系列-库帮助文档使用
在前面文件夹介绍时,提到了stm32f10x_stdperiph_lib_um.chm文件,此文件是库函数使用帮助文档,可以直接打开如下图. 因为STM32库函数非常多,我们不可能把所有的外设函数都记 ...
- Redis还可以做哪些事?
在上一篇文章中,讲到了redis五大基本数据类型的使用场景,除了string,hash,list,set,zset之外,redis还提供了一些其他的数据结构(当然,严格意义上也不算数据结构),一起来看 ...