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! ";
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_ << ") ";
fp_ = fopen(basename, "wb");
if (fp_ == NULL) {
std::cerr << "Failed to open file to write ";
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 << " ";
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() << " ";}
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. ";
asio::io_service io;
Tcp_server receiver(io, 1345);
io.run();
}