用asio传文件

网络库asio脱离boost 前言 之前公司用的boost库作为底层开发库,网络方面用的aiso,aiso是很好用的c++异步编程库,但boost功能太多,太大,编译使用起来很麻烦。 随着c++11的诞生,代码对boost的依赖已经逐步减少,因为boost的依赖库太过庞大, boost的很多优秀的模块都已经加入到c++11,如智能指针,auto,bind,智能锁,线程等等。 asio的官网已经说明可以脱离boost独立编译了。... 阅读详情

from:点击打开链接

看了几天asio文档,总算可以写点小程序了。有些细节还是没弄明白,同步IO好像还不能设超时?服务器端采用异步IO,客户端则采用同步IO。传送文件,不得不注意到 C/C++ 2G文件限制,好像没通用的解决方法。

 

先定义下头文件,统一下asio和boost_asio。


#ifndef _FILE_INFO_H_
#define _FILE_INFO_H_

  #if USE_ASIO_ALONE
    #include <asio.hpp>
  #else
    #include <boost/asio.hpp>
    namespace asio {
      using namespace boost::asio;
      using boost::system::error_code;
    }
  #endif
  
  struct File_info {
    typedef unsigned long long Size_type;
    Size_type filesize;
    size_t filename_size;
    File_info() : filesize(0), filename_size(0) {}
  };
  
#endif

client_sender

//www.cnblogs.com/flyinghearts

#include <iostream>
#include <cstdio>
#include <cstring>
#include <boost/shared_ptr.hpp>
#include "file_info.h"


void sender(asio::io_service& io, const char* ip_address, unsigned port, const char* filename)
{
  typedef asio::ip::tcp TCP;
  
  FILE *fp = fopen(filename, "rb");
  if (fp == NULL) {
    std::cerr << "cannot open file\n";
    return;
  }
  
  //使用智能指针,防止程序出现异常时,fclose未被调用。
  boost::shared_ptr<FILE> file_ptr(fp, fclose);
  
  clock_t cost_time = clock();
  
  const size_t k_buffer_size = 32 * 1024;
  char buffer[k_buffer_size];
  File_info file_info;
  
  int filename_size  = strlen(filename) + 1;
  size_t file_info_size = sizeof(file_info);
  size_t total_size = file_info_size + filename_size;
  if (total_size > k_buffer_size) {
    std::cerr << "File name is too long";
    return;
  }
  file_info.filename_size = filename_size;
  
  fseek(fp, 0, SEEK_END);
  file_info.filesize = ftell(fp);
  rewind(fp);

  memcpy(buffer, &file_info, file_info_size);
  memcpy(buffer + file_info_size, filename, filename_size);

  TCP::socket socket(io);
  socket.connect(TCP::endpoint(asio::ip::address_v4::from_string(ip_address), port));
  
  std::cout << "Sending file : " << filename << "\n";
  size_t len = total_size;
  unsigned long long total_bytes_read = 0;
  while (true) {
    socket.send(asio::buffer(buffer, len), 0);
    if (feof(fp)) break;
    len = fread(buffer, 1, k_buffer_size, fp);
    total_bytes_read += len;
  }
  
  cost_time = clock() - cost_time;
  if (cost_time == 0) cost_time = 1;
  double speed = total_bytes_read * (CLOCKS_PER_SEC / 1024.0 / 1024.0) / cost_time;
  std::cout << "cost time: " << cost_time / (double) CLOCKS_PER_SEC  << " s " 
    << "  transferred_bytes: " << total_bytes_read << " bytes\n"
    << "speed: " <<  speed << " MB/s\n\n"; 
}

int main(int args, char* argc[])
{
  if (args < 3) {
    std::cerr << "Usage: " << argc[0] << " ip_address  filename1 filename2 \n"; 
    return 1;
  }
  
  asio::io_service io;
  for (int i = 2; i < args; ++i) {
    try { sender(io, argc[1], 1345, argc[i]); }
    catch (std::exception& err) {
      std::cerr << err.what() << "\n";
    }
  }
}


server_reciver

//www.cnblogs.com/flyinghearts
#include <iostream>
#include <cstdio>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>

#include "file_info.h"

class Session : public boost::enable_shared_from_this<Session> {
public:
  typedef asio::ip::tcp TCP;
  typedef asio::error_code Error; 
  typedef boost::shared_ptr<Session> Pointer;
  typedef File_info::Size_type Size_type;
  
  static void print_asio_error(const Error& error) { std::cerr << error.message() << "\n";}
  
  static Pointer create(asio::io_service& io) { return Pointer(new Session(io));}
  
  TCP::socket& socket() { return socket_; }
  
  ~Session() 
  {
    if (fp_) fclose(fp_);
    clock_ = clock() - clock_;
    Size_type bytes_writen = total_bytes_writen_;
    if (clock_ == 0) clock_ = 1;
    double speed = bytes_writen * (CLOCKS_PER_SEC / 1024.0 / 1024.0) / clock_ ;
    std::cout << "cost time: " << clock_ / (double) CLOCKS_PER_SEC << " s  " 
       << "bytes_writen: " << bytes_writen << " bytes\n"
       << "speed: " <<  speed << " MB/s\n\n"; 
  }
  
  void start()
  {
    clock_ = clock();
    std::cout << "client: " << socket_.remote_endpoint().address() << "\n";
    socket_.async_receive(
      asio::buffer(reinterpret_cast<char*>(&file_info_), sizeof(file_info_)),
      boost::bind(&Session::handle_header, shared_from_this(), asio::placeholders::error)); 
  }
  
private:
  Session(asio::io_service& io) : socket_(io), fp_(NULL), total_bytes_writen_(0) { }
  
  void handle_header(const Error& error) 
  {
    if (error) return print_asio_error(error);
    size_t filename_size = file_info_.filename_size;
    if (filename_size > k_buffer_size) {
      std::cerr << "Path name is too long!\n";
      return;
    }
    //得用async_read, 不能用async_read_some,防止路径名超长时,一次接收不完
    asio::async_read(socket_, asio::buffer(buffer_, file_info_.filename_size),
      boost::bind(&Session::handle_file, shared_from_this(), asio::placeholders::error)); 
  }
  
  void handle_file(const Error& error)
  {
    if (error) return print_asio_error(error);
    const char *basename = buffer_ + file_info_.filename_size - 1;
    while (basename >= buffer_ && (*basename != '\\' && *basename != '/')) --basename;
    ++basename;
    
    std::cout << "Open file: " << basename << " (" << buffer_ << ")\n";
    
    fp_ = fopen(basename, "wb");
    if (fp_ == NULL) {
      std::cerr << "Failed to open file to write\n";
      return;
    }
    receive_file_content();
  }
  
  void receive_file_content()
  {
    socket_.async_receive(asio::buffer(buffer_, k_buffer_size), 
      boost::bind(&Session::handle_write, shared_from_this(), asio::placeholders::error,
        asio::placeholders::bytes_transferred)); 
  }
  
  void handle_write(const Error& error, size_t bytes_transferred)
  {
    if (error) {
      if (error != asio::error::eof) return print_asio_error(error);
      Size_type filesize = file_info_.filesize;
      if (total_bytes_writen_ != filesize) 
          std::cerr <<  "Filesize not matched! " << total_bytes_writen_ 
            << "/" << filesize << "\n";
      return;     
    }  
    total_bytes_writen_ += fwrite(buffer_, 1, bytes_transferred, fp_);
    receive_file_content();
  }
  
  clock_t clock_;
  TCP::socket socket_;
  FILE *fp_;
  File_info file_info_;
  Size_type total_bytes_writen_;
  static const unsigned k_buffer_size = 1024 * 32;
  char buffer_[k_buffer_size];
};

class Tcp_server
{
public:
  typedef asio::ip::tcp TCP;
  typedef asio::error_code Error;
  
  Tcp_server(asio::io_service& io, unsigned port) : 
      acceptor_(io, TCP::endpoint(TCP::v4(), port))
  {
    start_accept();
  }

  static void print_asio_error(const Error& error) { std::cerr << error.message() << "\n";}

private:
  void start_accept()
  {
    Session::Pointer session = Session::create(acceptor_.get_io_service());
    acceptor_.async_accept(session->socket(),
      boost::bind(&Tcp_server::handle_accept, this, session, asio::placeholders::error));
  }
  
  void handle_accept(Session::Pointer session, const Error& error)
  {
    if (error) return print_asio_error(error);
    session->start();
    start_accept();
  }
  
  TCP::acceptor acceptor_;
};


int main()
{
  std::cout << "Auto receive files and save then in current directory.\n";
  asio::io_service io;
  Tcp_server receiver(io, 1345);  
  io.run();
}





boost:asio编译 参考:http://hi.baidu.com/need_for_dream/blog/item/c14a28086a504c33e92488b5.html 环境: VS2010,          boost1.38.0,解压缩后放在,D:/boost_1_38_0。  編譯bjam(这个我没有试过,转过来以后参考)利用Visual Studio 2005 Command 阅读详情

相关推荐

【软件下载】音频ASIO驱动下载

本文主要介绍如何下载和安装windows ASIO驱动,,供参考。

专注音频,高效工作,快乐生活! 2万+

c++ boost asio网络库 异步tcp方式文件传输 速度在10M左右.zip

c++ boost asio网络库 异步tcp方式传文件 速度在10M左右.zip

Qt中独立Asio高性能网络异步库的使用

一、Asio的简介 Boost中的boost::Asio都听过大名,Asio是什么呢?Asio就是独立于boost的库,boosty::asio引用的就是这个asio,出处都是下面的地址,Asio的库更新地址:https://sourceforge.net/projects/asio/files/ 本次介绍的都是Asio独立运行库。Boost.Asio的作者也保持了Asio。你可以用Asio的方式来思考,因为它在两种情况中都有:Asio(非Boost的)和Boost.Asio。作者声明过更新..

tyhenry的专栏 3917

【boost网络库从青铜到王者】第四篇:asio网络编程中的socket同步读(接收)写(发送)

【boost网络库从青铜到王者】第四篇:asio网络编程中的socket同步读(接收)写(发送)

森明帮大于黑虎帮的博客 2927

独立C++ asio库介绍

独立的asio库是一个跨平台的 C++ 库,用于网络和底层 I/O 编程。在 C++20 之前,asio通常作为 Boost 库的一部分存在(即 Boost.Asio)。而现在,asio已经可以独立使用,无需依赖 Boost 库,它提供了统一的异步和同步 I/O 模型,让开发者可以方便地编写高性能、可扩展的网络应用程序,支持多种网络协议,如 TCP、UDP、ICMP 等。

flysnow010的博客 1548

Boost.Asio TCP服务器与客户端开发实战

Boost.Asio是一个跨平台的C++库,它提供了进行网络和低级I/O编程的API。它主要用于构建异步I/O应用程序,适用于需要高效率和高性能I/O操作的场景。Boost.Asio为开发者提供了一系列工具,用于处理网络连接、数据传输、定时器以及异步事件处理等。在这一章节,我们将探讨Boost.Asio的来历、设计理念以及如何集成到项目中去。Boost是一个经过千锤百炼、可移植、提供源代码的C++库,它包含广泛的各种功能,用于提高C++语言的功能。

weixin_36047538的博客 652

基于boost的multipart/form-data上传文件

使用C++11,基于boost.asio封装的http上传库,支持普通post和multipart/form-data这两种

Where there is life, there is hope. 1215

foobar2000的ASIO插件:优化音频体验

ASIO(Audio Stream Input/Output)是一种音频驱动标准,专为音频制作和播放设计,它通过减少延迟和避免不必要的数据转换,为用户提供更优质、更直接的音频体验。ASIO的低延迟特性在录音和实时音频处理中尤为重要,它允许音频信号在软件和硬件之间实现几乎无延迟的传输。"ASIO for foobar2000"是一个专为foobar2000设计的插件,其设计初衷是为了提供一个更加直接且高效的音频数据传输途径给音频设备。

weixin_31591833的博客 4971

19.10 Boost Asio 同步文件传输

在原生套接字编程中我们介绍了利用文件长度来控制文件传输的方法,本节我们将采用另一种传输方式,我们通过判断字符串是否包含`goodbye lyshark`关键词来验证文件是否传输结束了,当然了这种传输方式明显没有根据长度传输严谨,但使用这种方式也存在一个有点,那就是无需确定文件长度,因为无需读入文件所以在传输速度上要快一些,尤其是面对大文件时。

微软技术分享 1万+

传输文件实例(boost)

网络通信,使用boost实现,是学习网络通信以及boost库的实例。完成自我测试。

FileTransfer:通过boost.asio通过异步TCP连接进行文件传输

文件传输 简单的客户端服务器应用程序即可传输文件。 要求 或更高版本。 C ++ 11编译器。 Windows版 安装boost.asio。 使用更新5安装MS Visual Studio 2015。 将带有boost的目录路径的BOOST_ROOT添加到环境变量。 打开解决方案FileTransfer.sln并进行构建。 为Linux构建 安装cmake。 在项目根目录中打开终端: mkdir build && cd build cmake .. make 为OS X构建 安装cmake: brew install cmake 安装增强功能: brew install boost 在项目根目录中打开终端: mkdir build && cd build cmake .. make 跑步 启动服务器以接受文件: server <port> <outDirecto

TCP文件传输程序异步版

我用VC6.0和MFC编写的一个TCP文件传输程序异步版,Windows界面版WSAAsyncSelect模型的程序,能自动接收文件,当服务端发送文件时,客户端将自动弹出确认框,询问是否接收文件,如果点击是,则自动弹出保存文件对话框,用户可选择文件的保存位置。

ASIO文件传输DEMO

文件传输,展示了异步操作的几个函数的用法。

【亲测免费】 RS ASIO 项目使用教程

RS ASIO 项目的目录结构如下: ``` rs_asio/ ├── Assets/ ├── Docs/ ├── RS_ASIO/ ├── RS_ASIO.sln ├── RS_ASIO.vcxproj ├── RS_ASIO.vcxproj.filters ├── RS_ASIO.vcxproj.user ├── README.md └── rs_asio.ini ``` ### 目录介绍...

gitblog_01073的博客 1005

boost::asio写的文件上传下载程序

boost::asio完成了通讯模块的编写,界面用MFC简单做了一下。 局域网的测试结果: 传输速度在6-7m/s 并发到500,服务器CPU和网络应用均出现使用99%的情况出现硬件瓶颈,新连接无法建立(测试服务器比较差,CPU:赛扬1.6,100M网卡) 换更好的配置和网络环境,特别要是能换个1000M的网卡,并发支持应该可以到2000以上 第一版,有些地方还要改善,高手可以不用看了。 主要时服务器在关闭时回收资源还需要优化一下。

TCP三次握手,四次挥手的全过程,为什么需要三次握手,四次挥手

文章目录TCP介绍三次握手四次挥手滑动窗口拥塞避免算法 TCP介绍 三次握手 四次挥手

热爱编程的菜鸟 1万+
上一篇: IT面试——激情的重要性
下一篇: 我的Linux书架
Qicz
博客等级 码龄16年 56粉丝 122原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值