第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 / ...
随机推荐
- vs code 编译python 输出到调试控制台
如图所示,在debug菜单中点击齿轮按钮,进入launch.json,更改console选项的值(有三种) "console": "internalConsole&quo ...
- MeteoInfoLab脚本示例:数据投影-FLEXPART
FLEXPART是一个类似HYSPLIT的扩散模式,它输出的netcdf文件参照了WRF,可惜全局属性没有写全,比如只有一个投影名称(例如Lambert),没有相关的投影参数:中央经度,标准纬度等等. ...
- jmeter 相关
Don't use GUI mode for load testing !, only for Test creation and Test debugging. For load testing, ...
- DockerFile系统的学习
1.背景 DockerFile定义:用来构建Docker镜像的文件,有脚本命令组成. 自定义镜像并运行步骤:编写dockerFile文件-->docker build为镜像-->docke ...
- IDEA 半天卡住buid(编译)不动
[号外号外!] 最终解决办法并不复杂,关键在于"遇见问题,怎么样层层分析,多条路径试错,最终解决问题的思路或者能力"--资深码农的核心竞争力之一 背景 今天结束完最近2个月的一个项 ...
- 面试官:说说CountDownLatch,CyclicBarrier,Semaphore的原理?
CountDownLatch CountDownLatch适用于在多线程的场景需要等待所有子线程全部执行完毕之后再做操作的场景. 举个例子,早上部门开会,有人在上厕所,这时候需要等待所有人从厕所回来之 ...
- linux-mint18 (ubuntu 16) 安装python3
直接执行命令: sudo apt-get install python3 将python3设置为默python版本: sudo update-alternatives --install /usr/b ...
- return i++ 是先用再加么
return i++ 比较特殊,先是return i:然后i++. return i=i+ 1 则不同,它是先让i=i+1,再return
- 老板,来五道misc
开个杂项坑 穿越时空的思念 音频隐写,audacity分离音道,摩斯密码一把锁 金三胖 是个gif,明显能感觉到里面藏有flag stegsolve逐帧分离太low了,直接用脚本一把梭 import ...
- 【总结】swagger
1.swagger概念及配置 1.1基本概念 1.是一款让你更好的书写API文档的规范且完整框架. 2.提供描述.生产.消费和可视化RESTful Web Service. 3.是由庞大工具集合支撑的 ...