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 ...
随机推荐
- bzoj3998-弦论
给定一个长度为\(n(n\le 5\times 10^5)\)的字符串,求它的第\(k\)小字串.有两种模式: \(Type=0\),不同位置的相同字串只算一个 \(Type=1\),不同位置相同字串 ...
- CSS3 边框 圆角 背景
CSS3用于控制网页的样式布局. CSS3是最新的CSS标准. 关于transform: transform:rotate(10deg);//顺时针方向旋转10° 浏览器支持情况:低版本的IE浏览 ...
- NetScaler VLAN’s Demystified
NetScaler VLAN’s Demystified https://www.citrix.com/blogs/2014/12/29/netscaler-vlans-demystified/ Th ...
- ARC072E Alice in linear land
---题面--- 题解: 首先我们要观察到一个性质,因为在固定的起始距离下,经过固定的操作,最后所在的位置是固定的,我们设经过操作1 ~ i之后所在的地方距离终点为d[i]. 那么如果女巫可以修改第i ...
- bzoj1901: Zju2112 Dynamic Rankings(BIT套主席树)
带修改的题主席树不记录前缀,只记录单点,用BIT统计前缀. 对于BIT上每一个点建一棵主席树,修改和询问的时候用BIT跑,在主席树上做就行了. 3k4人AC的题#256...应该不算慢 #incl ...
- NOIP2016Day1T2天天爱跑步(LCA+桶)
据说是今年NOIP最难一题了...我还记得当时满怀期待心情点开Day1的题发现T2就不会了于是怀疑人生良久... 啊好像很多大爷都是用线段树合并写的,我怎么什么数据结构都不会啊呜呜呜... 题目大意就 ...
- Spark Streaming 的一些问题
Spark Streaming 的一些问题,做选型前关注这些问题可以有效的降低使用风险. checkpoint checkpoint 是个很好的恢复机制.但是方案比较粗暴,直接通过序列化的机制写入到文 ...
- python读书笔记-《简明python教程》上
1月15日 <简明python教程>上 基本结构: 基础概念+控制流+函数+模块+数据结构+面向对象+I/O+异常+标准库+其他 1.概念 1-0 退出python linux: ...
- 第01篇 说一下Setting,我一直没有讲过
settings 调整 settings 中的设置是非常关键的,它们会改变 MyBatis 的运行时行为.下表描述了设置中各项的意图.默认值等. 设置参数 描述 有效值 默认值 cacheEn ...
- MySQL新建用户,授权
登录MySQL mysql -u root -p 添加新用户 允许本地 IP 访问 localhost, 127.0.0.1 create user 'test'@'localhost' identi ...