19.10 Boost Asio 同步文件传输
在原生套接字编程中我们介绍了利用文件长度来控制文件传输的方法,本节我们将采用另一种传输方式,我们通过判断字符串是否包含goodbye lyshark关键词来验证文件是否传输结束了,当然了这种传输方式明显没有根据长度传输严谨,但使用这种方式也存在一个有点,那就是无需确定文件长度,因为无需读入文件所以在传输速度上要快一些,尤其是面对大文件时。
服务端代码如下所示,在代码中我们分别封装实现recv_remote_file该函数用于将远程特定目录下的文件拉取到本地目录下,而send_local_file函数则用于将一个本地文件传输到对端主机上,这两个函数都接收三个参数,分别是套接字句柄,本地文件与远程文件的文件路径,在传输时采用了while循环读取发送的实现方式每次传输1024个字节,直到传输结束为止。
#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/array.hpp>using namespace boost::asio;// 将远程特定目录下的文件拉取到本地目录
bool recv_remote_file(ip::tcp::socket *socket, std::string remote_file_path, std::string local_file_path)
{boost::system::error_code error_code;// 发送需要下载的文件,告诉客户端我需要下载的文件路径std::string message = remote_file_path;bool ref = (*socket).write_some(boost::asio::buffer(message), error_code);if (ref == false)return false;char buffer[1024] = { 0 };// 打开文件,准备写入,保存远程文件到本地 FILE * fp = fopen(local_file_path.c_str(), "wb");if (NULL == fp)return false;int length = 0;// 每次传输1024字节,直到传输全部结束while ((length = (*socket).read_some(boost::asio::buffer(buffer, 1024), error_code)) > 0){// 判断最后一次是否为结束符号if (strncmp(buffer, "goodbye lyshark",15) == 0){std::cout << "传输结束,再见了 lyshark" << std::endl;fclose(fp);return true;}if (fwrite(buffer, sizeof(char), length, fp) < length){std::cout << "写入文件失败" << std::endl;break;}std::cout << "接收字节数: " << length << " Bytes" << std::endl;memset(buffer, 0, 1024);}if (error_code){fclose(fp);return false;}fclose(fp);return true;
}// 将本地特定文件发送到远程的特定目录下
bool send_local_file(ip::tcp::socket *socket, std::string local_file_path, std::string remote_file_path)
{boost::system::error_code ec;char buffer[1024] = { 0 };// 发送放入目标位置bool ref = (*socket).write_some(boost::asio::buffer(remote_file_path));if (ref == false)return false;// 打开待发送文件FILE * fp = fopen(local_file_path.c_str(), "rb");if (NULL == fp)return false;int length = 0;// 每次读入1024字节 直到全部读取结束while ((length = fread(buffer, sizeof(char), 1024, fp)) > 0){bool ref = (*socket).write_some(boost::asio::buffer(buffer, 1024));if (ref != false){std::cout << "发送字节数: " << length << " Bytes" << std::endl;memset(buffer, 0, 1024);}}// 发送结束符(*socket).write_some(boost::asio::buffer("goodbye lyshark"));if (ec){fclose(fp);return false;}fclose(fp);return true;
}int main(int argc, char* argv[])
{io_service io_service;ip::tcp::acceptor acceptor(io_service, ip::tcp::endpoint(ip::tcp::v4(), 6666));ip::tcp::socket socket(io_service);acceptor.accept(socket);std::cout << "远端IP地址: " << socket.remote_endpoint().address() << std::endl;std::cout << "本端IP地址: " << socket.local_endpoint().address() << std::endl;// 将远程目录下 c://lyshark.exe 下载到本地的 d://lyshark.exebool recv_ref = recv_remote_file(&socket, "c://lyshark.exe", "d://lyshark.exe");std::cout << "下载状态: " << recv_ref << std::endl;std::system("pause");// 将本地目录中的 d://lyshark.exe 发送到远程 c://test.exebool send_ref = send_local_file(&socket, "d://lyshark.exe", "c://test.exe");std::cout << "上传状态: " << send_ref << std::endl;std::system("pause");return 0;
}
客户端代码代码如下所示,分别实现了两个函数,函数upload_file用于将本地文件上传到服务器端,函数download_file则用于接收服务器端发送过来的文件,过程中同样采用while循环,每次传输1024个字节。
#include <iostream>
#include <boost/asio.hpp>
#include <boost/array.hpp>using namespace boost::asio;// 将本地特定文件发送到远程的特定目录下
bool upload_file(ip::tcp::socket *socket)
{boost::system::error_code error_code;boost::array<char, 4096> buf = { 0 };char buffer[1024] = { 0 };// 接收要下载文件路径size_t len = (*socket).read_some(boost::asio::buffer(buf));if (len == 0)return false;// 打开需要发送的文件FILE * fp = fopen(buf.data(), "rb");if (NULL == fp)return false;int length = 0;// 每次读入1024字节,直到全部读取结束while ((length = fread(buffer, sizeof(char), 1024, fp)) > 0){bool ref = (*socket).write_some(boost::asio::buffer(buffer, 1024));if (ref != false){std::cout << "发送字节数: " << length << " Bytes" << std::endl;memset(buffer, 0, 1024);}}// 发送结束符(*socket).write_some(boost::asio::buffer("goodbye lyshark"));// 如果出现错误直接退出if (error_code){fclose(fp);return false;}fclose(fp);return true;
}// 获取远程发送过来的文件
bool download_file(ip::tcp::socket *socket)
{boost::system::error_code error_code;// 读入需要保存文件路径char file_path[4096] = { 0 };(*socket).read_some(boost::asio::buffer(file_path));char buffer[1024] = { 0 };//打开文件,准备写入 FILE * fp = fopen(file_path, "wb");if (NULL == fp)return false;int length = 0;// 每次传输1024字节while ((length = (*socket).read_some(boost::asio::buffer(buffer, 1024), error_code)) > 0){// 判断最后一次是否为结束符号if (strncmp(buffer, "goodbye lyshark",15) == 0){std::cout << "传输结束,再见了 lyshark" << std::endl;fclose(fp);return true;}if (fwrite(buffer, sizeof(char), length, fp) < length){printf("写入文件失败 ! \n");break;}printf("接收字节: %d byte \n", length);memset(buffer, 0, 1024);}if (error_code){fclose(fp);return true;}fclose(fp);return true;
}int main(int argc, char* argv[])
{io_service io_service;ip::tcp::socket socket(io_service);ip::tcp::endpoint ep(ip::address_v4::from_string("127.0.0.1"), 6666);socket.connect(ep);// 该函数对应服务端的 recv_remote_filebool upload_ref = upload_file(&socket);std::cout << "上传状态: " << upload_ref << std::endl;std::system("pause");// 该函数对应服务端的 send_local_filebool recv_ref = download_file(&socket);std::cout << "下载状态: " << recv_ref << std::endl;std::system("pause");return 0;
}
读者可自行编译并运行上述程序,代码中依次实现了上传与下载功能,如下图所示;

相关文章:
19.10 Boost Asio 同步文件传输
在原生套接字编程中我们介绍了利用文件长度来控制文件传输的方法,本节我们将采用另一种传输方式,我们通过判断字符串是否包含goodbye lyshark关键词来验证文件是否传输结束了,当然了这种传输方式明显没有根据长度传输严谨,但使用这…...
微信小程序:两层循环的练习,两层循环显示循环图片大图(大图显示、多层循环)
效果 代码分析 外层循环 外层循环的框架 <view wx:for"{{info}}" wx:key"index"></view> wx:for"{{info}}":这里wx:for指令用于指定要遍历的数据源,即info数组。当遍历开始时,会依次将数组中的每…...
输入几个数,分别输出其中的奇数和偶数
这个问题我们只需要设计几个循环嵌套在一起就可以解决,话不多说,我们直接上代码 目录 1.运行代码 2.运行结果 1.运行代码 #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<string.h>int main() {int arr[10] {1,2,3,4,5,6,…...
香港Web3.0:从政策到实践,探索未来发展路径
随着互联网技术的快速发展,互联网正在经历从Web1.0到Web3.0的重大升级。在这场互联网新技术革命的浪潮中,谁能抓住机遇,谁就能成为未来的引领者。 2022年11月,香港政府发布了《有关香港虚拟资产发展的政策宣言》,彰显…...
Java程序员面试核心知识--Java基础知识(一)
目录 一、Java程序初始化顺序 二、Java的Clone方法作用 三、 OverLoad(重载)与Override(重写)区别 四、abstract class(抽象类)与interface(接口)的异同 五、String、StringBuf…...
Linux的test测试功能
测试文件名的类型,文件是否存在, 文件的权限检测 文件之间的比较 两个整数之间的比较 判断字符串数据 多重条件判定 一个一个来,这个有点多,不过比较有意思,来代码 案例1,判断文件是否存在ÿ…...
为什么看了那么多测试技术帖,感觉自己还是菜?
作为测试新手,最爱莫过于看各大牛发的技术贴,这篇很牛叉,那篇也很有道理,似乎自己看着看着也会成为高手。然而几年后,发现自己对专业知识的理解乱的很,里面更有很多自相矛盾的地方,这到底是哪里…...
HTML和CSS的基础-前端扫盲
想要写出一个网页,就需要学习前端开发(写网页代码)和后端开发(服务器代码)。 对于前端的要求,我们不需要了解很深,仅仅需要做到扫盲的程度就可以了。 写前端,主要用到的有…...
Flutter 02 基础组件 Container、Text、Image、Icon、ListView
一、Container容器组件: demo1: import package:flutter/material.dart;void main() {runApp(MaterialApp(home: Scaffold(appBar: AppBar(title: const Text("你好Flutter")),body: const MyApp(),),)); }// 容器组件 class MyApp extends St…...
[笔记] 字符串输入 #字符输入
字符串的多组输入格式 scanf("%c", &ch)读取单个字符,用EOF作为结束的判断标志。 刷题记录:[题] 查找最大元素 #字符输入 逐个字符手动读取,因为题目的要求,要对每个字符逐个操作,所以就输入的时候顺便…...
服务器数据恢复—EMC存储pool上数据卷被误删的数据恢复案例
服务器数据恢复环境: EMC Unity某型号存储,连接了2台硬盘柜。2台硬盘柜上创建2组互相独立的POOL,2组POOL共有21块520字节硬盘。21块硬盘组建了2组RAID6,1号RAID6有11块硬盘. 2号RAID6有10块硬盘。 服务器故障&检测࿱…...
记录一次@Slf4j log.info 日志信息未输出到日志文件的问题
Spring Boot的起步依赖(如spring-boot-starter-web)中已经包含了Slf4j的依赖,无需额外添加。: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artif…...
Git 使用规范流程
开发中使用Git流程 参考文章:阮一峰- Git 使用规范流程 开发新功能:应该新建一个单独的分支(这方面可以参考《Git分支管理策略》)。提交分支commit:分支修改后,就可以提交commit了。提交时,应遵…...
69 内网安全-域横向CobaltStrikeSPNRDP
目录 演示案例:域横向移动RDP传递-Mimikatz域横向移动SPN服务-探针,请求,导出,破解,重写域横向移动测试流程一把梭哈-CobaltStrike初体验 涉及资源 SPN主要是扫描技术,在渗透过程中结合kerberos协议,可以做一些事情 演示案例: 域横向移动RDP传递-Mimik…...
GB28181学习(十四)——语音广播与语音对讲
语音对讲 定义 用户端向设备通过视音频点播请求音频数据;用户端接收音频数据并通过特定的播放设备(如音响)播放;用户端向设备发送广播请求;设备解析广播成功后通过INVITE方法向用户请求音频数据;用户通过音…...
Java实验一编程环境使用
1.String类的常用方法(StringExample.java) package step1;public class StringExample {public static void main(String args[]) {String s1 new String("you are a student");String s2 new String("how are you")…...
【数据结构】——线性表简答题模板
目录 一、顺序表二、链表三、顺序表与链表的对比四、循环链表五、静态链表 一、顺序表 【顺序表是什么/数组与顺序表的区别】 1、数组和顺序表的区别在哪里? 答:顺序表体现了数据元素之间的线性关系,即一对一的关系,以及对数据元…...
lambda和stream
理解 lambda 表达式和 Stream 是 Java 高级工程师的关键技能之一,它们为 Java 开发提供了更强大、更精简和更高效的编程工具。本篇 CSDN 文章将帮助你以高级工程师的角度深入掌握这两个概念,以便在实际项目中发挥你的 Java 技能。 ## 什么是 Lambda 表达…...
go微信开发sdk-简单使用_已设置图床
go微信开发sdk-简单使用 GitHub - silenceper/wechat: WeChat SDK for Go (微信SDK:简单、易用) 使用的sdk为上述的,这边给出快速的项目实例 git clone https://github.com/gowechat/example.git简单的项目结构 这边简单用dock…...
Java判断文本是否有敏感词
文章目录 Java判断文本是否有敏感词实现方法一、总体流程二、实现步骤1、构建敏感词库2、加载敏感词库3、文本分词4、敏感词匹配 Java判断文本是否有敏感词实现方法 一、总体流程 在Java中判断文本是否包含敏感词可以通过构建敏感词库并进行匹配来实现。下面是整个流程的表格…...
VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
