首页 > 其他分享 >19.10 Boost Asio 同步文件传输

19.10 Boost Asio 同步文件传输

时间:2023-11-02 20:02:28浏览次数:44  
标签:Asio 1024 socket 文件 buffer boost 文件传输 file Boost

在原生套接字编程中我们介绍了利用文件长度来控制文件传输的方法,本节我们将采用另一种传输方式,我们通过判断字符串是否包含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;
}

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

标签:Asio,1024,socket,文件,buffer,boost,文件传输,file,Boost
From: https://blog.51cto.com/lyshark/8154348

相关文章

  • 19.10 Boost Asio 同步文件传输
    在原生套接字编程中我们介绍了利用文件长度来控制文件传输的方法,本节我们将采用另一种传输方式,我们通过判断字符串是否包含goodbyelyshark关键词来验证文件是否传输结束了,当然了这种传输方式明显没有根据长度传输严谨,但使用这种方式也存在一个有点,那就是无需确定文件长度,因为无需......
  • 解决xgboost\core.py", ValueError: feature_names may not contain [, ] or <
    解决"xgboost\core.py",ValueError:feature_namesmaynotcontain[,]or<在使用xgboost进行特征工程时,有时会遇到类似下面的错误提示:pythonCopycodeFile"xgboost\core.py",lineXXX,inset_inforaiseValueError('feature_namesmaynotcontain[,]o......
  • GJO-LSTM-Adaboost基于金豺算法优化长短期记忆神经网络LSTM的Adaboost分类预测
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,代码获取、论文复现及科研仿真合作可私信。......
  • GJO-BILSTM-Adaboost基于金豺算法优化双向长短期记忆神经网络BILSTM的Adaboost分类预
     ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,代码获取、论文复现及科研仿真合作可私信。......
  • 【BiLSTM-Adaboost预测】基于双向长短期记忆网络的Adaboost时间序列预测研究(matlab代
     ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • centos 6.10 安装 boost 1.78.0
    centos6.10安装boost1.78.0下载地址找到对应的版本,下载源码,而不是二进制文件。解压文件cdboost_1_78_0./bootstrap.sh./b2install-perfix/usr/local/boost1.78.0/......
  • 大文件传输方案
    1.项目背景项目后端框架是springboot,后端与后端之间需要进行文件传输,这个文件大小从几兆到10G不等,当文件太大时,传输可能存在失败超时等各种问题。所以涉及这种大文件传输时,直接传输是不可行的,需要有其他方式进行传输,传输的方式主要有两种:1.http协议传输的文件大小有限制,当文件......
  • 14.9 Socket 高效文件传输
    网络上的文件传输功能也是很有必要实现一下的,网络传输文件的过程通常分为客户端和服务器端两部分。客户端可以选择上传或下载文件,将文件分块并逐块发送到服务器,或者从服务器分块地接收文件。服务器端接收来自客户端的请求,根据请求类型执行对应的操作,并根据发送的文件名或其他标识......
  • java实现大文件传输
    简介在现代互联网中,我们经常需要传输大文件,例如视频、音频或者大型数据文件。传输大文件需要考虑诸多因素,例如网络延迟、带宽限制和传输安全性。在本文中,我们将介绍如何使用Java实现大文件传输,并提供相应的代码示例。文件传输协议在进行大文件传输之前,我们需要选择合适的传输协议......
  • 开关电源三大基础拓扑解析:BUCK/BOOST/BUCK-BOOST
    1、BUCK拓扑电路Buck电路是一个降压电路,Vi=Vls+Vo。因Vi>Vo,故具有降压作用。(1)开关管S导通阶段 当开关闭合时,续流二极管D是截止的,由于输入电压Vi与储能电感Ls接通,因此输入-输出压差(Vi-Vo)就加在Ls上,使通过Ls上的电流线性地增加。在此阶段,除向负载供电外,还有一部分电能储存......