Upload files using asio

Source: Internet
Author: User

After reading the asio document for a few days, you can write a small program. I still haven't figured out some details. Does synchronous I/O seem to be unable to set a timeout? The server adopts asynchronous IO, while the client adopts synchronous IO. When transferring files, you have to note the limitations on C/C ++ 2G files. It seems that there is no common solution.


 

First, define the header file and unify asio and 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 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 ";
Return;
}

// Use a smart pointer to prevent the fclose from being called in case of a program exception.
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 (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 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 <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;

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 <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! ";
Return;
}
// Async_read is used, and async_read_some cannot be used to prevent the path name from being too long and cannot be received at a time
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 _;
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 _;
};


Int main ()
{
Std: cout <"Auto receive files and save then in current directory .";
Asio: io_service io;
Tcp_server receiver (io, 1345 );
Io. run ();
}


 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.