linux 高级i o函数,高级I/O函数

对于socket,最基本的输入输出函数就是,read和write。它们最基本,同样功能也是最少的。Unix中有几个函数是read/write的变种,在基本的输入输出功能上,还增加了一些非常使用的功能和特性,它们是:recv/send、readv/writev和recvmsg/sendmsg。

1、socket超时的实现

一般来说,要在对socket的I/O操作实现超时,有3种方式:

·注册SIGALRM信号的处理函数,然后调用alrm,则若对socket的I/O操作阻塞时间大于alrm注册的时间,则在alrm时间到时会阻塞会被SIGALRM打断。这样做有个缺点,就是alrm的调用会影响到同一进程的其他alrm调用。某些系统中,系统调用被信号打断后,会自动重新调用,在这种系统中可以使用setlongjmp/siglongjmp来跳出。

·使用SO_RCVTIMEO/SO_SNDTIMEO选项。注意,并不是所有的系统都支持这两个选项。

·用select代替read/write。

前面两种方式只对socket进行输入/输出有效,而最后一种除了输入/输出以外,还对connect有效(socket必须处于nonblocking模式下)。

2、recv/send

函数原型:

#include

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);

Both return: number of bytes read or written if OK, –1 on error

可以看到,前3个参数和read/write是一样的,很好理解。最后一个flag参数的值可以是一下几个常量中的一个或多个的或:

·MSG_DONTROUTE 适用于send,表示此次发送的数据包不经过系统的路由过程,直接发送。

·MSG_DOWAIT 适用于recv/send,表示此次操作采用非阻塞方式(不一定所有的系统都支持此项)。

·MSG_OOB 适用于recv/send,表示发送或接收“out-of-band data”(只能发送1个字节的out-of-band data)。

·MSG_PEEK 适用于recv,表示此次读取的是缓存中数据的副本。

·MSG_WAITALL 适用于recv,表示调用将直接阻塞知道指定的指定的字节数被读出(若中途遇到EOF或出错,则也会少于指定字节数)。

2、readv/writev

原型:#include

ssize_t readv(int filedes, const struct iovec *iov, int iovcnt);

ssize_t writev(int filedes, const struct iovec *iov, int iovcnt);

Both return: number of bytes read or written, –1 on error

这两个函数名字和read/write只多一个字母'v',功能更强大。readv可以将数据读入到多个buffer中,而writev可以将多个buffer的数据输出。iov指向一个iovec的数组,iovcnt为数组大小(linux中最大为1024)。

iovec结构如下:struct iovec {

void *iov_base; /* starting address of buffer */

size_t iov_len; /* size of buffer */

};

iov_base指向buffer的起始地址,iov_len为buffer的大小。

3、recvmsg/sendmsg

这对函数可以说是socket输入/输出的“万金油”,它们可以替代之前提到过的输入/输出函数。原型如下:#include

ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

ssize_t sendmsg(int sockfd, struct msghdr *msg, int flags);

Both return: number of bytes read or written if OK, –1 on error

大部分重要的都放在msg指向的msghdr中:struct msghdr {

void *msg_name; /* protocol address */

socklen_t msg_namelen; /* size of protocol address */

struct iovec *msg_iov; /* scatter/gather array */

int msg_iovlen; /* # elements in msg_iov */

void *msg_control; /* ancillary data (cmsghdr struct) */

socklen_t msg_controllen; /* length of ancillary data */

int msg_flags; /* flags returned by recvmsg() */

};

msg_name指向相应的socket地址,msg_namelen为地址大小,这两个成员仅在socket未连接的情况下使用(需设置IP_RECVDSTADDR),对于已连接的socket(如TCP和已连接的UDP),msg_name应置为NULL,msg_namelen为0。在使用recvmsg时,msg_namelen是值-结果类型。

msg_iov与msg_iovlen和readv/writev表示的意义一样。

msg_flags仅对recvmsg有用,当recvmsg调用时,将flags赋值给msg_flags,然后内核按照msg_flags进行操作,返回时将更新(有可能)后的flags通过这个值返回;sendmsg仅使用flags。

附表,flag总结

090416100656.jpg

msg_control成员很重要,下一节将详细分析;msg_controllen为msg_control大小。

4、辅助数据

辅助数据是指msghdr中的msg_control和msg_controllen成员,它们又称谓“控制信息”。在某些情况下,这些信息是非常有用的。

附表,辅助数据总结(直接截图,凑活着看)

090416102549.jpg

辅助数据可以包含多条信息,每条信息存放在cmsghdr的结构中:

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[] */

};

注意,数据区cmsg_data是可变的,按需求分配。

在处理cmsghdr时,有5个实用的宏:#include

#include /* for ALIGN macro on many implementations */

struct cmsghdr *CMSG_FIRSTHDR(struct msghdr *mhdrptr) ;

#Returns: pointer to first cmsghdr structure or NULL if no ancillary data

struct cmsghdr *CMSG_NXTHDR(struct msghdr *mhdrptr, struct cmsghdr *cmsgptr) ;

#Returns: pointer to next cmsghdr structure or NULL if no more ancillary data objects

unsigned char *CMSG_DATA(struct cmsghdr *cmsgptr) ;

#Returns: pointer to first byte of data associated with cmsghdr structure

unsigned int CMSG_LEN(unsigned int length) ;

#Returns: value to store in cmsg_len given the amount of data

unsigned int CMSG_SPACE(unsigned int length) ;

#Returns: total size of an ancillary data object given the amount of data

图例:

090416103941.jpg

代码片段:

struct msghdr msg;

struct cmsghdr *cmsgptr;

/* fill in msg structure */

/* call recvmsg() */

for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;

cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {

if (cmsgptr->cmsg_level == ... &&

cmsgptr->cmsg_type == ... ) {

u_char *ptr;

ptr = CMSG_DATA(cmsgptr);

/* process data pointed to by ptr */

}

}

5、如何得知当前缓冲区中有多少数据?

使用MSG_PEEK即可,这样可以获取缓冲区数据的副本,而不是“消耗”,副本的大小即为当前缓冲区中的数据量。需注意的是,网卡每时每刻都有可能收到数据,因此缓冲区的数据量是一直在变化的。

6、socket I/O与标准I/O

之前提到的函数(read/write、recv/send等)都是系统调用,除了系统调用之外,还可以使用标准I/O库操作socket。标准I/O库自带缓冲机制,同时考虑了一些细节,这给使用者带来一定的方便。但是,方便的同时,它带来了新的问题,这些问题的根源就是缓冲机制!避免一些“奇怪”问题的建议就是,不要使用标准I/O库来处理socket。(见unpv13e 14.8)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/552623.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安装linux必不可少的一个分区,安装linux系统对硬盘分区时,必须有的两种分区类型是什么?...

安装Linux系统对硬盘分区时,必须有两种分区类型: 根分区和交换分区。根分区就是root分区,所有的东西都在这个分区内。 /swap分区是交换分区,是一定磁盘空间(分区或文件),用于将部分内存中的数据换下来,以腾…

ubuntu和linux服务器,Linux服务器系统CentOS和Ubuntu Server如何选择? | 偶乃秋辰

在秋辰看来,目前最优秀的服务器系统就是Linux,但是Linux并不能说是一套完整的操作系统,准确的说它只是系统的内核,否则也不会有那么多的发行版如:Red Hat、CentOS、Debian、Ubuntu、Fedora等。其实Linux发行版系统很多…

linux 黑屏后死机,如何修复各种各样的黑屏死机

每次我们打开这些设备,我们都希望我们生活中的科技能发挥作用。当他们不能工作时,会让我们非常沮丧,尤其是当我们不知道如何解决问题时。所谓的“死亡黑屏”在操作系统之间很常见,当您打开机器,但屏幕空白。有时监视器…

cmd文件 c语言的段,对于TMS320F2812的CMD文件的理解

1.COFF格式要谈CMD文件,首先不可避免的要谈下COFF格式,COFF格式是通用目标文件格式(Common Object FileFormat)的缩写,它是一种流行的二进制可执行文件格式,在DSP里二进制可执行文件包括库文件(.lib)、目标文件(.obj)和最终可执行…

android点击事件的优先级,Android事件体系全面总结+实践分析,系列篇

前言在这一个月里,我利用闲余的时间看了下最近Android职业发展这块该怎么选择?这个问题各位大神的回答都非常透彻,相信对大家或多或少都在一定程度上有很大的帮助,今天在这里写这篇文章更多的是想以我开发十年的工作经历&#xff…

android各组件翻译,Android App框架指南(译文)

该系列文章是对Android推出的架构组件相关文章,按作者自己理解来翻译的,同时标记有作者自己一些简单笔记。如果读者发现文中有翻译不准确的地方,或者理解错误的地方,请不吝指教。源自Android官方Guide to app architecturel princ…

鸿蒙手机是个噱头,华为鸿蒙不是谈判噱头 必要时会应用手机当中!

7月30日,华为2019年上半年财报发布会上,华为董事长梁华在接受媒体采访时回应称,“鸿蒙”系统不是用来应对与美国谈判的噱头。今年5月,美国商务部将华为列入“实体清单”后不久,华为一系列“备胎”方案开始浮出水面&…

360浏览器html5无法播放,win7系统360浏览器播放不了视频的解决方法

今天和大家分享一下win7系统360浏览器播放不了视频问题的解决方法,在使用win7系统的过程中经常不知道如何去解决win7系统360浏览器播放不了视频的问题,有什么好的办法去解决win7系统360浏览器播放不了视频呢?小编教你只需要 1、视频无法正常…

html设置数字显示位数,数字万用表的显示位数和精度

数字万用表的显示位数和精度今天,我们来聊一聊数字万用表的位数和精度,到底什么是四位半?分辨率到底是哪个数?万用表的精度要如何计算?万用表的显示位数计数显示:万用表的显示位数范围。位数显示&#xff1…

w7提示无法关闭计算机,win7关不了机怎么回事?老司机教你怎么解决电脑关不了机...

win10系统的到来,慢慢的曾经称霸多年的xp已经退出了系统的舞台了,逐渐的win7也将重演历史,不过说到这个win7系统可以说是微软革命性的系统之一,其稳定、友好的界面,受到广大用户的拥戴,不过win7也有一些让人…

杭州招聘计算机专业毕业生,毕业季必看!杭州高校毕业生就业情况:这些专业最吃香!这个岗位最缺人!...

原标题:毕业季必看!杭州高校毕业生就业情况:这些专业最吃香!这个岗位最缺人!夏天,就是毕业的季节有一群人要离开校园,走上社会也有一群人要面临填志愿、选专业在杭州,什么专业最热门…

澳国立计算机录取分数,澳洲出国:2018年澳洲国立大学对高考成绩的本科录取分数线(多图)...

大师兄留学网(微信公众号:留学申请Free)是一支免费申请澳大利亚,新西兰,泰国,新加坡,马来西亚的零中介平台。大师兄留学网(微信号:Betty8990)在申请澳洲方面,有办理留学经验超过十年的学长学姐&…

寻仙手游维护公告服务器停服更新,寻仙手游3月1日停服更新公告 更新内容分享...

原标题:寻仙手游3月1日停服更新公告 更新内容分享在寻仙手游中,为了让玩家们更好的体验游戏。寻仙手游将于3月1日对游戏进行停服更新,本次更新新增了哪些新内容,今天小编就给大家带来寻仙手游3月1日停服更新公告的详细内容。寻仙手…

王者荣耀8月15日服务器维护,王者荣耀8月15日维护ios更新不了解 王者荣耀8月15日维护ios更新不了解决办法_蚕豆网新闻...

王者荣耀8月15日进行了维护更新,这次版本更新比较大,有新英雄马超等内容。但是维护完后不少玩家发现ios更新不了。大版本更新ios就很容易出现更新失败的情况,ios更新失败原因是什么?更新不了怎么解决?王者荣耀8月15日ios更新不了怎么办?第…

崩坏3服务器故障 临时维护,崩坏3 11.5游戏故障处理及补偿说明

崩坏3 11.5游戏故障补偿什么时候发?介绍了11.5游戏故障处理及补偿说明,希望这篇文章能够帮助到崩坏3的玩家!游戏介绍:崩坏3是由同名漫画改编的游戏作品,延续了崩坏学园2中的崩坏世界观,人气角色琪亚娜、雷电…

易语言通过服务器发送文件,易语言服务器与客户端发送文件

易语言服务器与客户端发送文件 内容精选换一换PL/pgSQL是一种可载入的过程语言。用PL/pgSQL创建的函数可以被用在任何可以使用内建函数的地方。例如,可以创建复杂条件的计算函数并且后面用它们来定义操作符或把它们用于索引表达式。SQL被大多数数据库用作查询语言。…

服务器将office转pdf文件,Windows服务-Office转PDF文件

一. 应用场景开发一个课件在线学习功能,要求将WORD, EXCEL, PPT类型课件可在线打开学习;最初设想使用第三方office插件,无奈价格太高放弃使用;我们最终的方案是:利用office自身的另存为功能,在服务器将上传…

最拼爹的css属性:z-index失效情况记录

最近自己用angular封装了一个多级下拉菜单的控件,使用过程中发现一个奇怪的bug 第一反应是菜单z-index太小,被覆盖了,结果设置成9999都没有效果。 调试样式后发现,是因为引用菜单控件的时候,父元素的position为fixed,右边控件的position为relative,而菜单父元素没有设置…

ubuntu nginx添加站点配置失效处理

最近开始接触阿里云服务器,一步步开始自己配置,记录下自己的一步一坑: nginx安装很简单,apt-get install nginx 成功后就可以打开默认站点 nginx配置文件在/etc/nginx目录下的nginx.conf 查看里面的文件内容可以知道&#xff0…

中用BBP公式计算_如何计算基础代谢率

了解基础代谢率(BMR)以后,可以知道身体减重、保持重量或增重时需要多少卡路里。基础代谢是身体休息的时候用掉的能量,即便没有动,身体还是在使用能量,维持体温、输送血液、呼吸、消化食物等等。基础代谢可以…