设为首页 加入收藏

TOP

用asio传文件(一)
2014-11-23 22:25:22 来源: 作者: 【 】 浏览:3
Tags:asio 文件

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


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

#ifndef _FILE_INFO_H_
#define _FILE_INFO_H_

#if USE_ASIO_ALONE
#include
#else
#include
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
#include
#include
#include
#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 ";
return;
}

//使用智能指针,防止程序出现异常时,fclose未被调用。
boost::shared_ptr 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 << " ";
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 "
<< "speed: " << speed << " MB/s ";
}

int main(int args, char* argc[])
{
if (args < 3) {
std::cerr << "Usage: " << argc[0] << " ip_address filename1 filename2 ";
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() << " ";
}
}
}


server_receiver

//www.cnblogs.com/flyinghearts
#include
#include
#include
#include
#include

#include "file_info.h"

class Session : public boost::enable_shared_from_this {
public:
typedef asio::ip::tcp TCP;
typedef asio::error_code Error;
typedef boost::shared_ptr Pointer;
typedef File_info::Size_type Size_type;

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

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 "
<< "speed: " << speed << " MB/s ";
}

void start()
{
clock_ = clock();
std::cout << "client: " << socket_.remote_endpoint().address() << " ";
socket_.async_receive(
asio::buffer(reinterpret_cast(&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)
{

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇判断一个点是否在指定三角形内(1.. 下一篇来自chrome的代码里的一个模板

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: