linux网络编程之IO函数
Linux操作系统中的IO函数主要有read(),write(),recv(),send(),recvmsg(),sendmsg(),readv(),writev().
接收数据的recv()函数
#include<sys/types.h>
#include<sys/socket.h>
ssize_t recv(int s,void *buf,size_t len,int flags);
该函数从套接字s中接收数据放到缓冲区buf中,buf的长度是len,操作的方式由flags指定。因此,第一个参数s是套接口文件描述符,它是由系统调用socket()返回的,第二个参数buf是一个指针,指向接收网络数据的缓冲区,第三个参数len以字节为单位来表示缓冲区的大小,第四个参数flags用于设置接收数据的方式,其值和含义如下:
MSG_DONOTWAIT 非阻塞操作,立刻返回,不等待
MSG_ERRQUEUE 错误消息从套接字错误队列接收
MSG_OOB 接收带外数据,而不是接收一般数据
MSG_PEEK 查看数据,不进行数据缓冲区的清空
MSG_TRUNC 返回所有的数据,此时如果用户的缓冲区太小,那么数据将被截断。仅仅复制缓冲区大小的数据,其他数据会被丢失
MSG_WAITALL 等待所有消息,它告诉内核在没有读到请求的字节数之前不使读操作返回
recv()函数从内核的接收缓冲区中复制数据到用户指定的缓冲区,当内核中的数据比指定的缓冲区小时,一般情况下,会复制缓冲区中的所有数据到用户缓冲区,并返回数据的度当内核缓冲区中的数据比用户指定的多时,会将用户指定长度len的接收缓冲区中的数据复制到用户指定地址,其余的数据需要下次调用接收函数的时候再复制,内核在复制用户指定的数据之后,会销毁已经复制完毕的数据并进行调整。recv()函数通常用于TCP类型的套接字,UDP使用recvfrom()函数接收数据,不过,如果你的UDP也绑定了地址和端口,那么也可以使用recv()函数接收数据。
recv()函数的返回值是成功接收到的字节数,当返回值为-1时错误发生。可以通过查看errno获取错误码,查看错误信息。
发送数据的send()函数
#include<sys/types.h>
#include<sys/socket.h>
ssize_t send(int s,const void *buf,size_t len,int flags);
与recv()函数相反过来,send()函数将缓冲区buf中大小为len的数据,通过套接字文件描述符按照flags指定的方式发送出去,其中的参数含义与recv()函数中一致,它的返回值是成功发送的字节数。当send()函数返回值小于len时,表明缓冲区中还有部分数据没有成功发送,这时需要重新发送剩余部分的数据,通常的剩余数据发送方法是对原来buf中的数据位置进行偏移,偏移的大小为已发送成功的字节数。函数send()发生错误的时候返回值为-1,这时可以通过查看errno获取错误码,而当另一方使用正常方式关闭连接的时候其返回值为0,例如通过调用close()函数关闭连接。
函数send()只能用于套接字处于连接状态的描述符,之前必须用connect()函数或者其他函数进行连接。对于send()函数和write()函数之间的差别是表示发送方式的flag,当flag为0时。send()函数和write()函数完全一致,而且send(s,buf,len,flags)与sendto(s,buf,len,flags,NULL,0)是等价的。
接收多个缓冲区数据的readv()函数
#include<sys/uio.h>
ssize_t readv(int s,const struct iovec *vector,int count);
readv()函数可以用于接收多个缓冲区数据,它从套接字描述符s中读取count块数据放到缓冲区向量vector中。每个 iovec 描述了一块要传送的数据; 它开始于 iov_base (在用户空间)并且有 iov_len 字节长. count 参数告诉有多少 个iovec 结构. 这些结构由应用程序创建, 但是内核在调用驱动之前拷贝它们到内核空间.参数vector是一个指向向量的指针,结构struct iovec在文件<sys/uio.h>中定义:
struct iovec{
void *iov_base;//向量缓冲区的地址
size_t iov_len;//向量缓冲区的大小,以字节为单位
};
在调用readv()函数的时候必须指定iovec的iov_base的长度,将值放到成员iov_len中。
发送多个缓冲区的writev()函数
#include<sys/uio.h>
ssize_t writev(int fd,const struct iovec *vector,int count);
一个 readv 调用被期望来轮流读取指示的数量到每个缓存. 相反, writev 要收集每个缓存的内容到一起并且作为单个写操作送出它们.它的使用与readv()类似。
下面的程序代码展示了如何使用writev函数将三个独立的C字符串作为一次写操作写入标准输出:
#include
int main(int argc,char **argv)
{
static char part2[] = "apple apple";
static char part3[] = "computer";
static char part1[] = "book book";
struct iovec iov[3];
iov[0].iov_base = part1;
iov[0].iov_len = strlen(part1);
iov[1].iov_base = part2;
iov[1].iov_len = strlen(part2);
iov[2].iov_base = part3;
iov[2].iov_len = strlen(part3);
writev(1,iov,3);
return 0;
}
接收数据的recvmsg()函数
#include<sys/types.h>
#include<sys/socket.h>
ssize_t recvmsg(int s,struct msghdr *msg,int flags);
与recv()函数和readv()函数相比u,这个函数的使用要复杂一点,主要区别在于第二个参数,它使用了内核的一个结构体msghdr:
struct msghdr {
void *msg_name; msg_name成员指向我们要发送或是接收信息的套接口地址
socklen_t msg_namelen; msg_namelen指明了这个套接口地址的长度
struct iovec *msg_iov; msg_iov成员指向一个struct iovec数组
size_t msg_iovlen;
void *msg_control; msg_control指向附属数据缓冲区
size_t msg_controllen; msg_controllen指明了缓冲区大小
int msg_flags;
};
#include<sys/uio.h>
sszie_t sendmsg(int s,const struct msghdr *msg,int flags);
sendmsg()函数用于发送数据,它的使用与recvmsg()函数类似,recvmsg与sendmsg功能更为强大,当然用起来也更为复杂。
上述函数的比较:
1.函数read()/write()和readv()/writev()可以对所有的文件描述符使用;recv()/send(),recvfrom()/writeto()和recvmsg()/sendmsg()只能操作套接字描述符。
2.函数readv()/writev()和recvmsg()/sendmsg()可以操作多个缓冲区,read()/write(),recv()/send()和recvfrom()/sendto()只能操作单个缓冲区。
3.函数recv()/send(),recvfrom()/sendto()和recvmsg()/sendmsg()具有可选标志。
4.函数recvfrom()/sendto()和recvmsg()/sendmsg()可以选择对方的IP地址。
5.函数recvmsg()/sendmsg()有可以选择的控制信息,能进行高级操作。
linux网络编程之IO函数的更多相关文章
- linux网络编程之IO模型
本文转自作者:huangguisu 1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式:同步: 所谓 ...
- (十)Linux 网络编程之ioctl函数
1.介绍 Linux网络程序与内核交互的方法是通过ioctl来实现的,ioctl与网络协议栈进行交互,可得到网络接口的信息,网卡设备的映射属性和配置网络接口.并且还能够查看,修改,删除ARP高速缓存的 ...
- linux网络编程之shutdown() 与 close()函数详解
linux网络编程之shutdown() 与 close()函数详解 参考TCPIP网络编程和UNP: shutdown函数不能关闭套接字,只能关闭输入和输出流,然后发送EOF,假设套接字为A,那么这 ...
- linux网络编程之socket编程(四)
经过两周的等待,终于可以回归我正常的学习之旅了,表哥来北京了在我这暂住,晚上回家了基本在和他聊天,周末带他在北京城到处乱转,几乎剥夺了我自由学习的时间了,不过,亲人之情还是很难得的,工作学习并不是生活 ...
- linux网络编程之socket编程(六)
经过一个国庆长假,又有一段时间没有写博文了,今天继续对linux网络编程进行学习,如今的北京又全面进入雾霾天气了,让我突然想到了一句名句:“真爱生活,珍惜生命”,好了,言归正传. 回顾一下我们之间实现 ...
- linux网络编程之posix条件变量
今天来学习posix的最后一个相关知识----条件变量,言归正传. 下面用一个图来进一步描述条件变量的作用: 为什么呢? 这实际上可以解决生产者与消费者问题,而且对于缓冲区是无界的是一种比较理解的解决 ...
- 服务器端网络编程之 IO 模型
引言 从 T 跳槽到 A 之后,我的编程语言也从 C++ 转为 了 Java.在 T 做的偏服务器端开发,而在 A 更偏向于业务开发.上周在 A 公司组内做了一个<服务器端高性能网络编程> ...
- 网络编程之IO模型
IO模型的分类 blocking IO:阻塞IO nonblocking IO:非阻塞IO IO multiplexing:IO多路复用 signal driven IO:异步IO 通常情况下IO默认 ...
- Linux-C网络编程之epoll函数
上文中说到假设从100的不同的地方取外卖,那么epoll相当于一部手机,当外卖到达后,送货员能够通知你.从而达到每去必得,少走非常多路. 它是怎样实现这些作用的呢? epoll的功能 epoll是se ...
随机推荐
- 当提交的表单类型为multipart/form-data时 后台的dopost则不能使用 setCharset来进行解码了 需要单独对字段使用 原始的new String(req.name("ISO-8859-1"),"utf-8")形式解码了
当提交的表单类型为multipart/form-data时 后台的dopost则不能使用 setCharset来进行解码了 需要单独对字段使用 原始的new String(req.name(" ...
- BZOJ 2120 数颜色(树状数组套主席树)
1A啊,激动. 首先,不修改的情况下可以直接用主席树搞,修改的话,直接用主席树搞一次修改的情况下复杂度是O(nlogn)的. 就像你要求区间和一样,用前缀和查询是O(1),修改是O(n),只不过主席树 ...
- openstack之keystone部署
前言 openstack更新频率是挺快的,每六个月更新一次(命名是是以A-Z的方式,Austin,Bexar...Newton).博主建议大家先可一种版本研究,等某一版本研究透彻了,在去研究新的版本. ...
- django_filters实现搜索
定义model # models.py class Product(models.Model): name = models.CharField(max_length=255) author = mo ...
- POJ3907:Build Your Home——题解
http://poj.org/problem?id=3907 题目大意:求多边形面积,结果四舍五入. ———————————————————— 多边形面积公式板子题. #include<cstd ...
- sass的颜色函数
sass中有些非常实用的颜色处理函数,总结如下 1.颜色加深或变浅 lighten($color,$amount) //颜色变浅 darken($color,$amount) //颜色加深 例如: l ...
- ucenter通信实现同步登录、同步退出(详细)
首先,需要去官网下载一个ucenter的包.然后解压下来. 先把ucenter/ucenter这个文件夹复制到你的项目根目录下改名为uc_server;(这里只是我建议修改,以便于我下面写的配置); ...
- mysql的cast()函数
先来补个知识: decimal的用法: decimal(18,4)总长18位,包括1位小数点和4为小数,也就是说18-1-4=13整数位只有13位decimal(19,1)总长19位,17位整数,1位 ...
- UVA 11922 Splay tree
UVA 11922 题意: 有n个数1~n 操作a,b表示取出第a~b个数,翻转后添加到数列的尾部 输入n,m 输入m条指令a,b 输出最终的序列 代码: #include<iostream&g ...
- 问题03.如果有多个集合的迭代处理情况【使用MAP】
在SQL开发过程中,动态构建In集合条件查询是比较常见的用法,在Mybatis中提供了foreach功能,该功能比较强大,它允许你指定一个集合,声明集合项和索引变量,它们可以用在元素体内.它也允许你指 ...