一、引言
readv和writev函数的功能可以概括为:对数据进行整合传输以及发送。通过writev函数可以将分散保存在多个buff的数据一并进行发送,通过readv可以由多个buff分别接受数据,适当的使用这两个函数可以减少I/O函数的调用次数:
二、writev函数
函数原型:
#include<sys/uio.h>
ssize_t writev(int fileds,const struct iovec* iov,int iovcnt);
fields表示数据传输对象的套接字描述符、IO描述符,文件描述符等等。
iov是iovec结构体数组,iovec结构体中包含了待发送buff的指针和大小信息。
iovcnt向第二个参数传递的数组长度。
返回实际写入的字节数
iovec结构体定义如下:
struct iovec
{
void* iov_base; //缓冲地址
size_t iov_len; //缓冲大小
}
调用writev函数的示例:
#include<stdio.h>
#include<string.h>
#include<sys/uio.h>
int main()
{
struct iovec iv1,iv2;
struct iovec iovs[2];
iv1.iov_base="123456789\n";
iv1.iov_len=strlen("123456789\n");
iv2.iov_base="qwertyuiop\n";
iv2.iov_len=strlen("qwertyuiop\n");
iovs[0]=iv1;
iovs[1]=iv2;
writev(1,iovs,2);//1是标准输出缓冲区的文件描述符。
return 0;
}
第6行,声明了两个iovec的结构体变量iv1和iv2;
第7行,声明了一个iovec类型的数组,数组用来存放iv1和iv2;
第9~13行,对iv1和iv2进行赋值,iov_base用来存放buffer,iov_len是buffer的大小。
第18行,调用writev函数向标准输出中写入所有buffer中的值。
该代码的运行结果如下:
[Hyman@Hyman-PC csdn]$ ./a.out
123456789
qwertyuiop
三、readv函数
#include<sys/uio.h>
ssize_t readv(int fileds,const struct iovec* iov,int iovcnt);
fields表示数据传输对象的套接字描述符、IO描述符,文件描述符等等。
iov是iovec结构体数组,用来存放接收到的buffer和buffer大小。
iovcnt向第二个参数传递的数组的长度。
返回实际读出的字节数调用readv函数的示例:
#include<stdio.h>
#include<sys/uio.h>
#define BUF_SIZE 100
int main()
{
int str_len;
struct iovec vec[2];
char buf1[BUF_SIZE]={0};
char buf2[BUF_SIZE]={0};
vec[0].iov_base=buf1;
vec[0].iov_len=5;
vec[1].iov_base=buf2;
vec[1].iov_len=BUF_SIZE;
str_len=readv(0,vec,2);//0是标准输入的文件描述符
puts(buf1);
puts(buf2);
return 0;
}
第9行,声明了一个iovec类型的数组vec。
第10,11行,声明了两个char型的数组buf1,buf2用来给vec的两个iovec结构体元素。
第13~16行,分别给vec的两个结构体元素进行赋值,请注意第14行,我们给了vec[0]这个元素的iov_len的值是5,也就是说vec[0]的iov_base只会存我们输入数据的前5个字节长度。
第18行,读取标准输入的数据。
我们运行上述程序,然后输入“hi,i am Hyman”,再打印输出时,你就会发现,字符串在am前面分开了,分别存到buf1和buf2,并进行了输出。结果如下:
[Hyman@Hyman-PC csdn]$ ./a.out
hi,i am Hyman
hi,i
am Hyman
Github位置:
https://github.com/HymanLiuTS/NetDevelopment
克隆本项目:
git clone git@github.com:HymanLiuTS/NetDevelopment.git
获取本文源代码:
git checkout NL18