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 ();
}