首先为一个I/O函数设置超时,这有三种方法。然后是三个read和write函数的变体:

  • recv和send,他们可以把含有标志的第四个参数从进程传给内核;
  • readv和writev这两个函数可以指定一个缓冲区的向量以输入或输出数据;
  • recvmsg和sendmsg在其他I/O函数的所有功能基础上结合了新的接收和发送辅助数据的能力。

一、套接口超时

有三种方法给套接口上的I/O操作设置超时。

  1. 调用alarm,在到达指定事件时产生SIGALRM信号。这涉及到信号处理,这一点随不同实现而变化,而且可能与进程中其他已有的alarm调用冲突。
  2. 使用select阻塞在等待I/O上,select内部有一个时间限制,以此代替在read或write调用上阻塞。
  3. 使用新的SO_RCVTIMEO和SO_SNDTIMEO套接口选项。这种方法存在一个问题,即并不是所有的实现都能支持这两个套接口选项。

二、recv和send函数

#include <sys/socket.h>

ssize_t recv(int sockfd, void *buff, size_t nbytes, int flags);
ssize_t send(int sockfd, const void *buff, size_t nbytes, int flags);
返回:成功返回读入或写出的字节数,出错返回-
前三个参数与read和write相同,flags的值或为0,或是一个或多个常值的逻辑或构成
MSG_DONTROUTE:不查路由表
MSG_DONTWAIT:本操作不阻塞
MSG_OOB:发送或接收带外数据
MSG_PEEK:查看外来的消息
MSG_WAITTALL:等待所有数据

如果进程需要让内核来更新标志,就必须用recvmsg代替recv或recvfrom。

三、readv和writev函数

#include <sys/uio.h>

ssize_t readv(int filedes, const struct iovec *iov, int iovcnt);
ssize_t writev(int filedes, const struct iovec *iov, int iovcnt);
返回:读到或写出的字节数,出错时为-
struct iovec {
void *iov_base; /* starting address of buffer */
size_t iov_len; /* size of buffer */
};

readv和writev可用于任何描述字,不仅限于套接口描述字。

四、recvmsg和sendmsg函数

实际上,可以用recvmsg代替read、readv、readcv和recvfrom。

#include <sys/socket.h>

ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
ssize_t sendmsg(int sockfd, struct msghdr *msg, int flags);
返回:成功时为读入或写出的字符数,出错- struct msghdr {
void *msg_name; /* protocol address */用于未经连接的套接口
socklen_t msg_namelen; /* size of protocol address */未经连接的套接口
struct iovec *msg_iov; /* scatter/gather array */指明输入或输出的缓冲区数组
size_t msg_iovlen; /* # elements in msg_iov */
void *msg_control; /* ancillary data, must be aligned for a cmsghdr structure */
socklen_t msg_controllen; /* length of ancillary data */指明可选辅助数据的位置和大小
int msg_flags; /* flags returned by recvmsg() */标志变量
};

辅助数据由一个或多个辅助数据对象组成,每个对象一个cmsghdr结构开头,该结构在<sys/socket.h>中定义

struct cmsghdr{
socklen_t cmsg_len; /* length in bytes, including this structure */字节长度
int cmsg_level; /* originating protocol */初始协议
int cmsg_type; /* protocol-specific type */协议指定类型
/* followed by unsigned char cmsg_data[] */真正的控制消息数据
};

因为由recvmsg返回的辅助数据可以包括任意数目的辅助数据对象,为了对应用程序屏蔽可能出现的填充字节。

在<sys/socket.h>中定义了以下五个宏,以简化对辅助数据的处理。

#include <sys/socket.h>
#include <sys/param.h> /* for ALIGN macro on many implementations */
struct cmsghdr *CMSG_FIRSTHDR(struct msghdr *mhdrptr);
返回:指向第一个cmsghdr结构的指针,无辅助数据时为NULL
struct cmsghdr *CMSG_NXTHDR(struct msghdr *mhdrptr, struct cmsghdr *cmsgptr);
返回:指向下一个cmsghdr结构的指针,不再有辅助数据对象时为NULL
unsigned char *CMSG_DATA(struct cmsghdr *cmsgptr);
返回:指向与cmsghdr结构关联的数据的第一个字节的指针
unsigned int CMSG_LEN(unsigned in length);
返回:给定数量下存储在cmsg_len中的值
unsigned int CMSG_SPACE(unsigned int length);
返回:给定数据量下一个辅助数据对象的总大小 一些使用例子:
struct msghdr msg;
struct cmsghdr *cmptr; cmptr = CMSG_FIRSTHDR(&msg);
cmptr->cmsg_len = CMSG_LEN(sizeof(int));
cmptr->cmsg_level = SOL_SOCKET;
cmptr->cmsg_type = SCM_RIGHTS; /* send file description */
*((int *)CMSG_DATA(cmptr)) = sendfd;

使用msghdr的列子:

 #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h> int main(int argc, char *argv[])
{
int ret;
int sock[];
struct msghdr msg;
struct iovec iov[];
char send_buf[] = "Hello"; struct msghdr msgr;
struct iovec iovr[];
char recv_buf[]; ret = socketpair(AF_LOCAL, SOCK_STREAM, , sock);
if(ret == -) {
printf("socketpair err\n");
return ;
} /* sock[1] send data to local */
bzero(&msg, sizeof(msg));
msg.msg_name = NULL;
msg.msg_namelen = ;
iov[].iov_base = send_buf;
iov[].iov_len = sizeof(send_buf);
msg.msg_iov = iov;
msg.msg_iovlen = ; printf("Starting send data: \n");
printf("Send data: %s\n", send_buf);
ret = sendmsg(sock[], &msg, );
if(ret == -) {
printf("sendmsg err\n");
return -;
}
printf("Send successful\n"); /* sock[0] recv data to local */
bzero(&msgr, sizeof(msgr));
msgr.msg_name = NULL;
msgr.msg_namelen = ;
iovr[].iov_base = recv_buf;
iovr[].iov_len = sizeof(recv_buf);
msgr.msg_iov = iovr;
msgr.msg_iovlen = ;
ret = recvmsg(sock[], &msgr, );
if(ret == -) {
printf("recvmsg err\n");
return -;
}
printf("Recv successful\n");
printf("Recv data: %s\n", recv_buf); close(sock[]);
close(sock[]); return ;
}

运行结果:

$ ./a.out
Starting send data:
Send data: Hello
Send successful
Recv successful
Recv data: Hello

UNP学习 高级I/O函数的更多相关文章

  1. UNP总结 Chapter 12~14 IPv4与IPv6的互操作性、守护进程和inet超级服务器、高级I/O函数

    一.IPv4与IPv6的互操作性 1.IPv4客户与IPv6服务器 拥有双重协议栈的主机的一个基本特性就是:其上运行的IPv6服务器既能应付IPv4客户,又能应付IPv6客户.这是通过使用IPv4映射 ...

  2. UNP学习笔记4——I/O复用:select和poll函数

    1 概述 之间的学习中发现,传统的阻塞式系统调用不仅浪费进程运行时间,而且会带来狠毒问题.因此进程需要有一种预先告知内核的能力,使得内核一旦发现进程指定的一个或者多个I/O条件就绪,它就通知进程.这个 ...

  3. 第六章 高级I/O函数

    第六章 高级I/O函数 6.1 pipe函数 即管道函数,用于进程间的通信. #include<unistd.h> int pipe(int fd[2]); // fd:filedes / ...

  4. Lua学习高级篇

    Lua学习高级篇 之前已经说了很多,我目前的观点还是那样,在嵌入式脚本中,Lua是最优秀.最高效的,如果您有不同的观点,欢迎指正并讨论,切勿吐槽.这个系列完全来自于<Programming in ...

  5. shell学习总结之自定义函数

    shell学习总结之自定义函数 Myfun (){ echo -n "now i is $i " ! [ "$i" ] && exit ; ec ...

  6. makefile高级用法--使用函数

    makefile高级用法--使用函数 分类: C/C++ 使用函数 ———— 在Makefile中可以使用函数来处理变量,从而让我们的命令或是规则更为的灵活和具有智能.make所支持的函数也不算很多, ...

  7. IOS学习笔记07---C语言函数-printf函数

    IOS学习笔记07---C语言函数-printf函数 0 7.C语言5-printf函数 ------------------------- ----------------------------- ...

  8. IOS学习笔记06---C语言函数

    IOS学习笔记06---C语言函数 --------------------------------------------  qq交流群:创梦技术交流群:251572072              ...

  9. Linux高性能server编程——高级I/O函数

     高级I/O函数 pipe函数 pipe函数用于创建一个管道,实现进程间的通信. #include <unistd.h> int pipe(int pipefd[2]); 通过pipe ...

随机推荐

  1. AT2070 Card Game for Three(组合数学)

    传送门 解题思路 前面的思路还是很好想的,就是要枚举最后一个\(a\)在哪出现算贡献,之后我先想的容斥,结果彻底偏了..后来调了很久发现自己傻逼了,似乎不能容斥,终于走上正轨23333.首先可以写出一 ...

  2. python中常用内置函数用法总结

    强制类型转换:int()float()str()list()tuple()set()dict()总结,这几种类型转换函数得用法基本一致,基本就是int(要转换得数据).返回值类型为对应得数据类型   ...

  3. python中将'12345'转换为12345,不要使用int

    #将'12345'转换为12345,不要使用int s = " #定义一个数字变量 ret = 0 for x in s : ret = ret*10 +( ord(x)-ord(" ...

  4. 2018-2019-2 20175213实验四 《Android开发基础》实验报告

    一.实验报告封面 课程:Java程序设计 班级:1752班 姓名:吕正宏 学号:20175213 指导教师:娄嘉鹏 实验日期:2019年5月14日 实验时间:13:45 - 21:00 实验序号:实验 ...

  5. C# JS 前后端互传数据

    ---恢复内容开始--- 后端: public void ProcessRequest(HttpContext context) { context.Response.ContentType = &q ...

  6. QTP-创建一个word文件

    '创建word实例 Set oWordApp = CreateObject("Word.Application") oWordApp.Visible =True '添加一个word ...

  7. jenkins实现master变化时,才触发构建(过滤分支)

    现状:现在是这样的,每个开发push时,都触发jenkins进行构建 期望:只有当代码被push到master时才进行构建 (根据使用的git平台)做这些配置需要先了解一些概念: (github) p ...

  8. git 忽略提交及已push过得文件忽略提交

    在使用Git的过程中,我们喜欢有的文件比如日志,临时文件,编译的中间文件等不要提交到代码仓库,这时就要设置相应的忽略规则,来忽略这些文件的提交 Git 忽略文件提交的方法 这种方式通过在项目的某个文件 ...

  9. equals方法重写

    在java中常见的equals方法的重写: 举例:一个自定义类ball如下 public class Ball { private String name; private int weight; p ...

  10. Windows Server 2008 R2 官方简体中文免费企业版/标准版/数据中心版

    Windows Server 2008 R2是一款微软发布的Windows服务器操作系统,和之前发布的Windows Server 2008相比功能更为完善运行更为稳定,提升了系统管理弹性.虚拟化.网 ...