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 ...
随机推荐
- (一)Redis简介及安装
Redis简介 Redis 是一个开源(BSD许可)的,内存中的key-value数据结构存储系统,它可以用作数据库.缓存和消息中间件. Redis具有丰富的数据结构类型.包括字符串(string), ...
- [LOJ#2340] [WC2018] 州区划分
题目链接 洛谷题面. LOJ题面.还是LOJ机子比较快 Solution 设\(f(s)\)表示选\(s\)这些城市的总代价,那么我们可以得到一个比较显然的\(dp\): \[ f(s)=\frac{ ...
- 自学Python快速入门
1 helloworld#基本语法print("hello") #换行print('1221312\12312312\2312312321312\21312312') ##表示注释 ...
- POJ2891:Strange Way to Express Integers——题解
http://poj.org/problem?id=2891 题目大意: k个不同的正整数a1,a2,...,ak.对于一些非负m,满足除以每个ai(1≤i≤k)得到余数ri.求出最小的m. 输入和输 ...
- BZOJ5157 & 洛谷3970:[TJOI2014]上升子序列——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=5157 https://www.luogu.org/problemnew/show/P3970 给定 ...
- BZOJ4754 & 洛谷4323 & LOJ2072:[JSOI2016]独特的树叶——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4754 https://www.luogu.org/problemnew/show/P4323 ht ...
- BZOJ3998:[TJOI2015]弦论——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=3998 https://www.luogu.org/problemnew/show/P3975 对于 ...
- HDU5726:GCD——题解
题目:hdu的5726 (我原博客的东西,正好整理过来,属于st表裸题) (可以看出我当时有多么的菜--) 这道题写了一遍,然而蒟蒻的我的时间爆炸了-- 于是看了一下学长的代码(顺便在此处%一下学长) ...
- BZOJ3437 小P的牧场 【斜率优化dp】
3437: 小P的牧场 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 1502 Solved: 836 [Submit][Status][Disc ...
- YBT 1.1 贪心算法
本人因为过于懒所以以后就将题解放进原文件中,存入百度网盘,自行下载,里面包含题目网站,源文件,与相应题解(这次没有写) 链接: https://pan.baidu.com/s/1eSoQ_LFWMxF ...