sendfile | 传说中的零拷贝(主要用于网络中文件传输)
sendfile函数
- sendfile函数简介
- sendfile简单小例子
- 用sendfile函数简单模拟文件下载
sendfile函数简介
- sendfile函数:sendfile函数是在两个文件描述符中直接传递数据(完全在内核中操作),从而避免了用户和内核之间的数据拷贝,所以效率很高,也被称之为零拷贝。
- sendfile函数用法
- 头文件:#include <sys/sendfile.h>
- 用法:ssize_t sendfile(int out_fd,int in_fd,off_t * offset,size_t count)
- out_fd:待写入内容的文件描述符,一般为accept的返回值
- in_fd:待读出内容的文件描述符,一般为open的返回值
- offset:指定从读入文件流的哪个位置开始读,如果为空,则使用读入文件流的默认位置,一般设置为NULL
- count:两文件描述符之间的字节数,一般给struct stat结构体的一个变量,在struct stat中可以设置文件描述符属性
注意:in_fd规定指向真实的文件,不能是socket等管道文件描述符,一般使open返回值,而out_fd则是socket描述符
- sendfile的优点:是专门为网络上传输文件而设计的函数,效率高
sendfile简单小例子
//打开文件
int file_fd = open("./wyg.txt",O_RDWR | O_CREAT,664);
if(file_fd < 0)
{perror("open");return -1;
}
//设置file_fd文件描述符属性
struct stat stat_buf;
fstat(file_fd,&stat_buf);
//把目标文件传递给服务器
int ret = sendfile(newts.GetFd(),file_fd,NULL,stat_buf.st_size);
if(ret < 0)
{perror("sendfile");return -1;
}
用sendfile函数简单模拟文件下载
实现功能:客户端连接服务器,会自动下载服务器的文件
主要实现:其实就是基于tcp套接字编程 + sendfile函数来实现的,传输效率高
1、服务器
- 创建套接字
- 绑定地址信息
- 监听
- 获取连接
- 打开文件
- 设置打开的文件描述符属性
- 把目标文件通过sendfile传递给服务器
- 关闭套接字
2、客户端
- 创建套接字
- 发起连接
- 接收文件
- 关闭套接字
3、总代码实现如下
tcp_svr.hpp
#include<iostream>
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>class Tcpsvr
{public:Tcpsvr(){_sockfd = -1;}~Tcpsvr(){}bool Createsocket()//创建套接字{_sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if(_sockfd < 0){perror("socket");return false;}return true;}bool Bind(const std::string& ip,uint16_t port)//绑定地址信息{struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(port);addr.sin_addr.s_addr = inet_addr(ip.c_str());int ret = bind(_sockfd,(struct sockaddr*)&addr,sizeof(addr));if(ret < 0){perror("bind");return false;}return true;}bool Listen(int backlog = 5)//监听{int ret = listen(_sockfd,backlog);if(ret < 0){perror("listen");return false;}return true;}bool Accept(Tcpsvr *newts,struct sockaddr_in* peeraddr)//获取连接{socklen_t addrlen = sizeof(struct sockaddr_in);int newfd = accept(_sockfd,(struct sockaddr*)peeraddr,&addrlen);if(newfd < 0){perror("accept");return false;}newts->_sockfd = newfd;return true;}bool Connect(const std::string& ip,uint16_t port)//发起连接{struct sockaddr_in dest_addr;dest_addr.sin_family = AF_INET;dest_addr.sin_port = htons(port);dest_addr.sin_addr.s_addr = inet_addr(ip.c_str());int ret = connect(_sockfd,(struct sockaddr*)&dest_addr,sizeof(dest_addr));if(ret < 0){perror("connect");return false;}return true;}bool Recv(std::string* data)//接收数据{char buf[1024] = {0};int recv_size = recv(_sockfd,buf,sizeof(buf) - 1,0);if(recv_size < 0){perror("recv");return false;}else if(recv_size == 0){//对端关闭了连接printf("peer shutdown connect\n");return false; }data->assign(buf,recv_size);return true;}int GetFd()//获取套接字描述符{return _sockfd;}void Close()//关闭套接字{close(_sockfd);}private:int _sockfd;
};
服务器svr.cpp
#include "tcp_svr.hpp"
#include <unistd.h>
#include <fcntl.h>
#include <sys/sendfile.h>
#include <sys/types.h>
#include <sys/stat.h>
#define CHECK_RET(p) if(p == false){return 0;}//判断封装接口是否调用成功,失败直接返回
int main()
{Tcpsvr tp;//1、创建套接字CHECK_RET(tp.Createsocket());//2、绑定地址信息CHECK_RET(tp.Bind("192.168.163.129",18888));//3、监听CHECK_RET(tp.Listen());Tcpsvr newts;while(1){//4、获取连接struct sockaddr_in cli_addr;CHECK_RET(tp.Accept(&newts,&cli_addr));//5、打开文件int file_fd = open("./wyg.txt",O_RDWR | O_CREAT,664);if(file_fd < 0){perror("open");return -1;}//6、//设置file_fd文件描述符属性struct stat stat_buf;fstat(file_fd,&stat_buf);//7、//把目标文件传递给服务器int ret = sendfile(newts.GetFd(),file_fd,NULL,stat_buf.st_size);if(ret < 0){perror("sendfile");return -1;}}//8、关闭套接字tp.Close();newts.Close();return 0;
}
客户端cli.cpp
#include "tcp_svr.hpp"
#define CHECK_RET(p) if(p == false){return 0;}//判断封装的接口是否调用成功,失败直接返回
int main()
{Tcpsvr tp;//1、创建套接字CHECK_RET(tp.Createsocket());//2、发起连接CHECK_RET(tp.Connect("192.168.163.129",18888));//3、接收std::string buf;tp.Recv(&buf);printf("%s",buf.c_str());//4、关闭套接字tp.Close();return 0;
}
makefile
all:cli svr
cli:cli.cppg++ $^ -o $@
svr:svr.cppg++ $^ -o $@
wyg.txt
hello world
1、我在要传输的文件wyg.txt就写了hello world这一句话,其实是可以实现大文件传输的,感兴趣的可以传大文件试一下,也可以把程序改成并发的,这样传的更快
2、我在让客户端接收的时候只是让文件内容打印出来了,其实是可以写入到另外一个文件的
sendfile | 传说中的零拷贝(主要用于网络中文件传输)相关推荐
- 图解数据在网络中的传输过程
数据在网络中的传输过程 在计算机网络当中,数据是怎么样保证准确的从客户端发送到服务器端的,这是本文探究的重点. 下图是本文中使用的网络拓扑图,数据从客户端发送给服务器端. 客户端各层对数据的封装 ja ...
- 数据包在网络中的传输过程详解
我们当今使用电子设备都离不开网络,通过网络我们可以聊天.玩游戏.看电影都操作. 网络的本质就是交换数据. 本文我们就来看下数据是如何在网络中传输的. 计算机网络模型 现在有两种计算机网络模型,分别为O ...
- 浅析网络数据帧在网络中的传输
文章目录 网络帧的传输 1. 网络的分层 2.网络帧的封装 3. 网络帧的传输 4. 相关疑问 参考材料 网络帧的传输 本文主要简单回顾一下网络数据包的封装.分片.传输以及重新组装的过程,帮助我们理解 ...
- 读书笔记(随笔2)数据在网络中的传输
2 数据在网络中的传输 所有的数据对于网络来说都是业务,不同的业务数据对传输的要求不一样, 就需要有不同的 信令协议 来满足它,不同的信令协议对数据的封装和标识提出 了不同的要求,从而又产生了各种 封 ...
- 操作系统中的零拷贝与java中的使用
下面是在Linux操作系统中将磁盘中的数据传输到网络设备上的示例图. 在图中可以看到数据先从磁盘上读取到用户空间而后再从用户空间写入到网络设备中,写入和读取一共经历四次拷贝,和四次状态的切换(用户到内 ...
- 数据在网络中的传输(一)
最近面试被问到了一些<<计算机网络>>方面的问题,由于之前的工作中很少涉及到,7.8年了前学的了,都基本还给老师了,回答得不太满意.所以这几天又从头学习了一遍<<计 ...
- 如何通过网络将文件传输到嵌入式设备_嵌入式系统 Boot Loader技术内幕,带你完全了解Boot Loader...
一个嵌入式 Linux 系统从软件的角度看通常可以分为四个层次:1. 引导加载程序.包括固化在固件(firmware)中的 boot 代码(可选),和 Boot Loader 两大部分.2. Linu ...
- Linux中文件传输方式
TFTP : FTP是文件服务器,可实现将文件上传至远程服务器,也可以从服务器下载文件到本地主机. scp: scp能够将不同主机的文件进行相互传输,使用简单方便. rz : 用于linux与wind ...
- 九、WebService中文件传输
WebService处理传递普通的信息,还可以传输文件,下面介绍WebService是怎么完成文件传输的. 1. 首先编写服务器端上传文件的WebService方法 代码 上传方法和我们以前在Web中 ...
最新文章
- java for循环和数组--冒泡排序、二分查找法
- python 嵌套字典key_查找和修改python嵌套字典(key,value)
- Java与汽车_Java NIO:IO与NIO的区别
- 【JS 逆向百例】无限 debugger 绕过,某网站互动数据逆向
- html彩色背景指令,HTML_第四章 颜色背景的CSS,本 章 C S S 的 主 - phpStudy...
- sql删除主键_产品经理的第一节SQL课——ID到底是干什么的?!
- DataBseDesign工作笔记002---数据库表设计
- 制作简单的GIF动图
- 手机腾讯网mt框架简介
- [下载]最新QQ空间牧场开通器 V2.0
- 下载篇:程序员修炼之道+从小工到专家(高清、免费)
- 英语论文应该怎么查重?
- 信号完整性与电源完整性分析 第三版 pdf_电源完整性,信号完整性,你说哪个更重要一点?...
- matlab多种分配方案_基于Matlab解决m个人n项任务的最优分派
- 人工智障和神经病网络对话--30行python让图灵机器人和茉莉机器人无止尽的瞎扯蛋
- 在PHP中如何获取用户的真实IP
- [C/C++]二分查找专题/最后一个小于等于目标值target的数/第一个大于等于目标值target的数
- 全自动模拟布局设计的挑战和机遇
- 大话分布式理论之二——共识算法与一致性的区别
- ubuntu去除PDF文档密码
热门文章
- c语言unsigned占几字节,在C语言中,double、long、unsigned、int、char类型数据所占字节数(示例代码)...
- kts 样例,包含多渠道打包。改名
- C#开发身份证信息管理系统之登陆
- 微信小程序跳转到其他网页(外部链接)
- cmake gui安装教程_CMake安装使用教程
- 封面|这几张肯定适合你的朋友圈封面
- Thymeleaf语法webjars使用
- 物联卡,纯流量卡,消费级物联网专用卡,这些关键词你听过吗?
- android电脑不识别手机号码,安卓手机刷机后电脑不识别怎么办 如何让电脑重新识别手机...
- LaTeX公式自动换行