在原生套接字编程中我们介绍了利用文件长度来控制文件传输的方法,本节我们将采用另一种传输方式,我们通过判断字符串是否包含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.exe
bool 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.exe
bool 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_file
bool upload_ref = upload_file(&socket);
std::cout << "上传状态: " << upload_ref << std::endl; std::system("pause"); // 该函数对应服务端的 send_local_file
bool recv_ref = download_file(&socket);
std::cout << "下载状态: " << recv_ref << std::endl; std::system("pause");
return 0;
}

读者可自行编译并运行上述程序,代码中依次实现了上传与下载功能,如下图所示;

19.10 Boost Asio 同步文件传输的更多相关文章

  1. qt+boost::asio+tcp文件传输

    客户端: void qt_boost::pbSendFileClicked(){ QString filename = ui.leFileName->text(); QByteArray ba ...

  2. boost::asio 同步&异步例子

    同步客户端: using boost::asio; io_service service; ip::tcp::endpoint ep( ip::address::from_string(); ip:: ...

  3. Linux文件传输FTP详解

    ftp命令用来设置文件系统相关功能.ftp服务器在网上较为常见,Linux ftp命令的功能是用命令的方式来控制在本地机和远程机之间传送文件,这里详细介绍Linux ftp命令的一些经常使用的命令,相 ...

  4. FTP文件传输协议两种模式 ftp协议集,错误码集,ftp客户端命令集

    TCP/IP协议中,FTP标准命令TCP端口号为21,Port方式数据端口为20.FTP协议的任务是从一台计算机将文件传送到另一台计算机,它与这两台计算机所处的位置.联接的方式.甚至是是否使用相同的操 ...

  5. Windows、Linux -- 远程登录、文件传输、文件共享

    Linux  <--->  Linux 远程登录: ssh服务 ssh root@10.20.62.124 文件传输: scp服务 上传  scp /home/xxx.txt root@1 ...

  6. 详解:基于WEB API实现批量文件由一个服务器同步快速传输到其它多个服务器功能

    文件同步传输工具比较多,传输的方式也比较多,比如:FTP.共享.HTTP等,我这里要讲的就是基于HTTP协议的WEB API实现批量文件由一个服务器同步快速传输到其它多个服务器这样的一个工具(简称:一 ...

  7. boost::ASIO的同步方式和异步方式

    http://blog.csdn.net/zhuky/article/details/5364574 http://blog.csdn.net/zhuky/article/details/536468 ...

  8. 使用Boost asio实现同步的TCP/IP通信

    可以先了解一下Boost asio基本概念,以下是Boost asio实现的同步TCP/IP通信: 服务器程序部分,如果想保留套接字之后继续通信,可以动态申请socket_type,保存指针,因为so ...

  9. boost::asio设置同步连接超时

    boost::asio设置同步连接超时   CSDN上求助无果,只好用自创的非主流方法了.asio自带的例子里是用deadline_timer的async_wait方法来实现超时的,这种方法需要单独写 ...

  10. 【Linux探索之旅】第四部分第三课:文件传输,潇洒同步

    内容简单介绍 .第四部分第三课:文件传输.潇洒同步 2.第四部分第四课:分析网络.隔离防火 文件传输.潇洒同步 这一课的内容相对简单,所以我们慢慢享用. 经过上一课的学习.我们已经知道怎样远程连接到其 ...

随机推荐

  1. 【换模型更简单】如何用 Serverless 一键部署 Stable Diffusion?

    作者|寒斜(阿里云智能技术专家) 前文回顾 AI 作画火了,如何用 Serverless 函数计算部署 Stable Diffusion? [自己更换模型]如何用 Serverless 一键部署 St ...

  2. linux ntp时间服务器搭建

    工作中经验遇到搭建时间服务器的任务,如何搭建网上找的例子总是有些许问题,如下自己动手操作一遍总结一下,方便自己和后来人直接上手使用. 准备工作:192.168.0.1   服务端: ntp服务器192 ...

  3. 使用 Sealos 将 ChatGLM3 接入 FastGPT,打造完全私有化 AI 客服

    FastGPT 是一款专为客服问答场景而定制的开箱即用的 AI 知识库问答系统.该系统具备可视化工作流功能,允许用户灵活地设计复杂的问答流程,几乎能满足各种客服需求. 在国内市场环境下,离线部署对于企 ...

  4. freeswitch的2833和inband对接方案

    概述 freeswitch支持三种模式的DTMF传输方式,分别时inband.INFO.2833. 在传统的PSTN网络中,所有的DTMF码都是inband模式,所以VOIP网络和PSTN网络对接中, ...

  5. Servlet系列:(HttpServletRequest、HttpServletResponse、ServletContext、ServletConfig)详解

    HttpServletRequest HttpServletRequest 对象:主要作用是用来接收客户端发送过来的请求信息,例如:请求的参数,发送的头信息等都属于客户端发来的信息,service() ...

  6. Laravel组件化开发学习笔记

    组件化开发就是基于组件来进行迭代开发,而不是从零开始开发 1.语法基础 组件开发的基础语法是命名空间. 可以使用魔法常量__NAMESPACE__可以直接获取当前命名空间的名称的字符串. 例如: &l ...

  7. 问题--VSCODE终端中文乱码问题

    1.问题 问题如下,终端出现中文乱码问题 根本原因是VSCODE是UFT-8编码,而终端显示的中文则是GBK编码 网上很多都是改VSCODE为GBK编码,但改终端为UFT-8也挺方便 2.解决方法 1 ...

  8. [转帖]rsync原理

    简介: Rsync(remote synchronize)是一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件.Rsync使用所谓的"Rsync算法"来使本地和远 ...

  9. JDBC针对SQLServer的sendStringParametersAsUnicode=false的验证

    JDBC针对SQLServer的sendStringParametersAsUnicode=false的验证 背景 部分客户的SQLServer数据库出现了大量死锁的情况. 虽然部分客户并没有反馈死锁 ...

  10. [转帖]存储器分级:L1 Cache 比内存和 SSD 快多少倍?

    目录 1.为什么会有存储器分级策略? 2.存储器分级策略 2.1 存储器的级别 2.2.1 L1-Cache 2.2.2 L2-Cache 2.2.3 L3-Cache 3.内存 4.SSD 和硬盘 ...