当前位置: 首页 > news >正文

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 同步文件传输

在原生套接字编程中我们介绍了利用文件长度来控制文件传输的方法&#xff0c;本节我们将采用另一种传输方式&#xff0c;我们通过判断字符串是否包含goodbye lyshark关键词来验证文件是否传输结束了&#xff0c;当然了这种传输方式明显没有根据长度传输严谨&#xff0c;但使用这…...

微信小程序:两层循环的练习,两层循环显示循环图片大图(大图显示、多层循环)

效果 代码分析 外层循环 外层循环的框架 <view wx:for"{{info}}" wx:key"index"></view> wx:for"{{info}}"&#xff1a;这里wx:for指令用于指定要遍历的数据源&#xff0c;即info数组。当遍历开始时&#xff0c;会依次将数组中的每…...

输入几个数,分别输出其中的奇数和偶数

这个问题我们只需要设计几个循环嵌套在一起就可以解决&#xff0c;话不多说&#xff0c;我们直接上代码 目录 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:从政策到实践,探索未来发展路径

随着互联网技术的快速发展&#xff0c;互联网正在经历从Web1.0到Web3.0的重大升级。在这场互联网新技术革命的浪潮中&#xff0c;谁能抓住机遇&#xff0c;谁就能成为未来的引领者。 2022年11月&#xff0c;香港政府发布了《有关香港虚拟资产发展的政策宣言》&#xff0c;彰显…...

Java程序员面试核心知识--Java基础知识(一)

目录 一、Java程序初始化顺序 二、Java的Clone方法作用 三、 OverLoad&#xff08;重载&#xff09;与Override&#xff08;重写&#xff09;区别 四、abstract class&#xff08;抽象类&#xff09;与interface&#xff08;接口&#xff09;的异同 五、String、StringBuf…...

Linux的test测试功能

测试文件名的类型&#xff0c;文件是否存在&#xff0c; 文件的权限检测 文件之间的比较 两个整数之间的比较 判断字符串数据 多重条件判定 一个一个来&#xff0c;这个有点多&#xff0c;不过比较有意思&#xff0c;来代码 案例1&#xff0c;判断文件是否存在&#xff…...

为什么看了那么多测试技术帖,感觉自己还是菜?

作为测试新手&#xff0c;最爱莫过于看各大牛发的技术贴&#xff0c;这篇很牛叉&#xff0c;那篇也很有道理&#xff0c;似乎自己看着看着也会成为高手。然而几年后&#xff0c;发现自己对专业知识的理解乱的很&#xff0c;里面更有很多自相矛盾的地方&#xff0c;这到底是哪里…...

HTML和CSS的基础-前端扫盲

想要写出一个网页&#xff0c;就需要学习前端开发&#xff08;写网页代码&#xff09;和后端开发&#xff08;服务器代码&#xff09;。 对于前端的要求&#xff0c;我们不需要了解很深&#xff0c;仅仅需要做到扫盲的程度就可以了。 写前端&#xff0c;主要用到的有&#xf…...

Flutter 02 基础组件 Container、Text、Image、Icon、ListView

一、Container容器组件&#xff1a; demo1&#xff1a; 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)读取单个字符&#xff0c;用EOF作为结束的判断标志。 刷题记录&#xff1a;[题] 查找最大元素 #字符输入 逐个字符手动读取&#xff0c;因为题目的要求&#xff0c;要对每个字符逐个操作&#xff0c;所以就输入的时候顺便…...

服务器数据恢复—EMC存储pool上数据卷被误删的数据恢复案例

服务器数据恢复环境&#xff1a; EMC Unity某型号存储&#xff0c;连接了2台硬盘柜。2台硬盘柜上创建2组互相独立的POOL&#xff0c;2组POOL共有21块520字节硬盘。21块硬盘组建了2组RAID6&#xff0c;1号RAID6有11块硬盘. 2号RAID6有10块硬盘。 服务器故障&检测&#xff1…...

记录一次@Slf4j log.info 日志信息未输出到日志文件的问题

Spring Boot的起步依赖&#xff08;如spring-boot-starter-web&#xff09;中已经包含了Slf4j的依赖&#xff0c;无需额外添加。&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artif…...

Git 使用规范流程

开发中使用Git流程 参考文章&#xff1a;阮一峰- Git 使用规范流程 开发新功能&#xff1a;应该新建一个单独的分支&#xff08;这方面可以参考《Git分支管理策略》&#xff09;。提交分支commit&#xff1a;分支修改后&#xff0c;就可以提交commit了。提交时&#xff0c;应遵…...

69 内网安全-域横向CobaltStrikeSPNRDP

目录 演示案例:域横向移动RDP传递-Mimikatz域横向移动SPN服务-探针,请求,导出,破解,重写域横向移动测试流程一把梭哈-CobaltStrike初体验 涉及资源 SPN主要是扫描技术&#xff0c;在渗透过程中结合kerberos协议&#xff0c;可以做一些事情 演示案例: 域横向移动RDP传递-Mimik…...

GB28181学习(十四)——语音广播与语音对讲

语音对讲 定义 用户端向设备通过视音频点播请求音频数据&#xff1b;用户端接收音频数据并通过特定的播放设备&#xff08;如音响&#xff09;播放&#xff1b;用户端向设备发送广播请求&#xff1b;设备解析广播成功后通过INVITE方法向用户请求音频数据&#xff1b;用户通过音…...

Java实验一编程环境使用

1&#xff0e;String类的常用方法&#xff08;StringExample.java&#xff09; 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、数组和顺序表的区别在哪里&#xff1f; 答&#xff1a;顺序表体现了数据元素之间的线性关系&#xff0c;即一对一的关系&#xff0c;以及对数据元…...

lambda和stream

理解 lambda 表达式和 Stream 是 Java 高级工程师的关键技能之一&#xff0c;它们为 Java 开发提供了更强大、更精简和更高效的编程工具。本篇 CSDN 文章将帮助你以高级工程师的角度深入掌握这两个概念&#xff0c;以便在实际项目中发挥你的 Java 技能。 ## 什么是 Lambda 表达…...

go微信开发sdk-简单使用_已设置图床

go微信开发sdk-简单使用 GitHub - silenceper/wechat: WeChat SDK for Go &#xff08;微信SDK&#xff1a;简单、易用&#xff09; 使用的sdk为上述的&#xff0c;这边给出快速的项目实例 git clone https://github.com/gowechat/example.git简单的项目结构 这边简单用dock…...

Java判断文本是否有敏感词

文章目录 Java判断文本是否有敏感词实现方法一、总体流程二、实现步骤1、构建敏感词库2、加载敏感词库3、文本分词4、敏感词匹配 Java判断文本是否有敏感词实现方法 一、总体流程 在Java中判断文本是否包含敏感词可以通过构建敏感词库并进行匹配来实现。下面是整个流程的表格…...

DeepSeek总结的 PostgreSQL 19:为 UPDATE/DELETE 添加 FOR PORTION OF 子句

原文地址&#xff1a;https://www.depesz.com/2026/04/02/waiting-for-postgresql-19-add-update-delete-for-portion-of/ 等待 PostgreSQL 19&#xff1a;为 UPDATE/DELETE 添加 FOR PORTION OF 子句 2026 年 4 月 1 日&#xff0c;Peter Eisentraut 提交了一个补丁&#xf…...

STM32F407实战:用CubeMX+FreeRTOS+SDIO+FatFs,5分钟搞定SD卡文件读写

STM32F407实战&#xff1a;5分钟极速实现SD卡文件系统全流程 拿到一块STM32F407开发板时&#xff0c;如何快速验证SD卡文件读写功能&#xff1f;这套组合方案或许能帮你省下大量调试时间——CubeMX生成基础框架、FreeRTOS管理任务调度、SDIO硬件接口驱动配合FatFs文件系统&…...

Vue2项目实战:v-md-editor从安装到二次封装全流程(附常见问题解决)

Vue2项目深度整合v-md-editor&#xff1a;从核心配置到企业级封装实践 在内容管理系统的开发中&#xff0c;Markdown编辑器已成为技术文档、博客平台和知识库系统的标配组件。v-md-editor作为Vue生态下功能完备的Markdown解决方案&#xff0c;其双栏实时预览、深度定制能力和丰…...

Zynq Linux FPGA Manager实战:5分钟搞定PL配置(含bit转bin避坑指南)

Zynq Linux FPGA Manager实战&#xff1a;5分钟搞定PL配置&#xff08;含bit转bin避坑指南&#xff09; 第一次在Zynq开发板上尝试配置PL逻辑时&#xff0c;我盯着Vivado生成的.bit文件发愁——官方文档里提到的PCAP、ICAP协议像天书一样&#xff0c;而网上各种教程要么步骤不全…...

Vue3 + xterm.js 4.x + WebSocket 打造现代化Web终端实战指南

1. 为什么选择Vue3 xterm.js 4.x WebSocket组合&#xff1f; 在构建现代化Web终端时&#xff0c;技术选型直接影响开发效率和最终用户体验。Vue3提供了响应式编程范式和组件化开发优势&#xff0c;xterm.js 4.x是最新版本的浏览器终端模拟器&#xff0c;而WebSocket则实现了…...

Modbus实战:从功能码到网络选型的工业通信指南

1. Modbus协议基础&#xff1a;从功能码到设备角色 第一次接触Modbus时&#xff0c;我被它简洁的设计震惊了——这个诞生于1979年的协议&#xff0c;至今仍是工业自动化领域的通用语言。就像乐高积木一样&#xff0c;Modbus用几个基础功能码就能搭建出复杂的控制系统。让我们先…...

3大核心突破:解密m4s-converter如何实现B站缓存视频的智能重生

3大核心突破&#xff1a;解密m4s-converter如何实现B站缓存视频的智能重生 【免费下载链接】m4s-converter 一个跨平台小工具&#xff0c;将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 你是否曾面对B站缓存目…...

Allegro 17.4表贴焊盘设计实战:用Pad Designer快速创建符合IPC标准的SMD焊盘

Allegro 17.4表贴焊盘设计实战&#xff1a;从零构建符合IPC标准的SMD封装 在高速PCB设计领域&#xff0c;表贴器件(SMD)的焊盘设计质量直接影响焊接良率和信号完整性。Cadence Allegro 17.4的Pad Designer工具提供了专业级的焊盘设计解决方案&#xff0c;但许多工程师在实际操作…...

告别while循环轮询!用STM32 HAL库定时器中断实现按键扫描(附状态机源码)

STM32高效按键处理实战&#xff1a;定时器中断与状态机的完美结合 在嵌入式开发中&#xff0c;按键处理看似简单却暗藏玄机。传统while循环轮询方式不仅占用CPU资源&#xff0c;还容易导致代码结构混乱。本文将带你用STM32 HAL库的定时器中断和状态机&#xff0c;实现一套高效、…...

开源音乐解锁工具:浏览器端全平台音频解密解决方案

开源音乐解锁工具&#xff1a;浏览器端全平台音频解密解决方案 【免费下载链接】unlock-music 在浏览器中解锁加密的音乐文件。原仓库&#xff1a; 1. https://github.com/unlock-music/unlock-music &#xff1b;2. https://git.unlock-music.dev/um/web 项目地址: https://…...