19.10 Boost Asio 同步文件传输

08-11 汽车 投稿:乌小翠
文章目录 站点概览

王瑞

一个面向信息安全技术爱好者的知识分享平台。 自创建以来,一直致力并专注于分享信息安全领域研究经验及成果,倡导并从事前慑性信息安全技术研究、交流、整理、和推广工作,普及安全技术和安全常识,提高网络安全整体水平,让更多信息安全爱好者从中受益。 285 日志 在原生套接字编程中我们介绍了利用文件长度来控制文件传输的方法,本节我们将采用另一种传输方式,我们通过判断字符串是否包含`goodbye lyshark`关键词来验证文件是否传输结束了,当然了这种传输方式明显没有根据长度传输严谨,但使用这种方式也存在一个有点,那就是无需确定文件长度,因为无需读入文件所以在传输速度上要快一些,尤其是面对大文件时。

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

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

声明:生活头条网所有作品(图文、音视频)均由用户自行上传分享,仅供网友学习交流。若您的权利被侵害,请联系admin@gdcyjd.com