C10k test: Using ASIO to implement multi-thread echo server (echo server) _ Runyon _ Sina Blog
C10k test: Using ASIO to implement multi-thread echo server)
(15:05:50)
Reprinted token
Tags:
Boost
ASIO
Multithreading
Echo
Server
It
Category: C/CPP
ASIO is a good library for example and documentation in the boost library. It comes with an echo server, but it is a pity that it is a single thread and cannot give full play to the power of multi-core hosts. So I transformed it into multi-thread, mainly copying the io_service_pool in HTTP server exampleCodeHey.
Of course, the test results will not be worse than the number of threads opened for each connection. The bandwidth will also be full during the 100-15000 connection.
====================================== Code separation line ============ ========================
# Include <cstdlib>
# Include <iostream>
# Include <stdexcept>
# Include <boost/Bind. HPP>
# Include <boost/ASIO. HPP>
# Include <boost/lexical_cast.hpp>
# Include <boost/thread. HPP>
Using namespace STD;
Using boost: ASIO: IP: TCP;
Class io_service_pool
: Public boost: noncopyable
{
Public:
explicit io_service_pool (STD: size_t pool_size)
: next_io_service _ (0)
{< br> for (STD: size_t I = 0; I {< br> io_service_sptr io_service (new boost: ASIO: io_service);
work_sptr work (new boost: ASIO:: io_service: Work (* io_service);
io_services _. push_back (io_service);
Work _. push_back (work);
}< BR >}
void start ()
{< br> for (STD: size_t I = 0; I {< br> boost: shared_ptr thread (new boost: thread (
boost :: BIND (& boost: ASIO: io_service: Run, io_services _ [I]);
threads _. push_back (thread);
}< BR >}
Void join ()
{
For (STD: size_t I = 0; I <threads _. Size (); ++ I)
{
Threads _ [I]-> join ();
}
}
Void stop ()
{
For (STD: size_t I = 0; I <io_services _. Size (); ++ I)
{
Io_services _ [I]-> stop ();
}
}
boost: ASIO: io_service & get_io_service ()
{< br> boost: mutex: scoped_lock lock (CTX);
boost :: ASIO: io_service & io_service = * io_services _ [next_io_service _];
++ next_io_service _;
If (next_io_service _ = io_services _. size ()
{< br> next_io_service _ = 0;
}< br> return io_service;
}
PRIVATE:
Typedef boost: shared_ptr <boost: ASIO: io_service> io_service_sptr;
Typedef boost: shared_ptr <boost: ASIO: io_service: Work> work_sptr;
Typedef boost: shared_ptr <boost: thread> thread_sptr;
Boost: mutex CTX;
STD: vector <io_service_sptr> io_services _;
STD: vector <work_sptr> Work _;
STD: vector <thread_sptr> threads _;
STD: size_t next_io_service _;
};
Boost: mutex cout_ctx;
Int packet_size = 0;
Enum {max_packet_len= 4096 };
Class session
{
Public:
Session (boost: ASIO: io_service & io_service)
: Socket _ (io_service)
, Recv_times (0)
{
}
Virtual ~ Session ()
{
Boost: mutex: scoped_lock lock (cout_ctx );
Cout <recv_times <Endl;
}
TCP: Socket & socket ()
{
Return socket _;
}
inline void start ()
{< br> boost: ASIO: async_read (socket _, boost: ASIO: buffer (Data _, packet_size ),
boost: BIND (& session: handle_read, this, boost: ASIO: placeholders: error, boost: ASIO: placeholders: bytes_transferred ));
}
void handle_read (const boost: System: error_code & error, size_t bytes_transferred)
{< br> If (! Error)
{< br> ++ recv_times;
boost: ASIO: async_write (socket _, boost: ASIO: buffer (Data _, bytes_transferred),
boost: BIND (& session: handle_write, this, boost: ASIO: placeholders: Error ));
}< br> else
{< br> Delete this;
}< BR >}
Void handle_write (const boost: System: error_code & error)
{
If (! Error)
{
Start ();
}
Else
{
Delete this;
}
}
PRIVATE:
TCP: Socket socket _;
Char data _ [max_packet_len];
Int recv_times;
};
Class Server
{
Public:
Server (short port, int thread_cnt)
: Io_service_pool _ (thread_cnt)
, Acceptor _ (io_service_pool _. get_io_service (), TCP: endpoint (TCP: V4 (), Port ))
{
Session * new_session = new session (io_service_pool _. get_io_service ());
Acceptor _. async_accept (new_session-> socket (),
Boost: BIND (& server: handle_accept, this, new_session, boost: ASIO: placeholders: Error ));
}
Void handle_accept (Session * new_session, const boost: System: error_code & error)
{
If (! Error)
{
New_session-> Start ();
New_session = new session (io_service_pool _. get_io_service ());
Acceptor _. async_accept (new_session-> socket (),
Boost: BIND (& server: handle_accept, this, new_session, boost: ASIO: placeholders: Error ));
}
Else
{
Delete new_session;
}
}
Void run ()
{
Io_service_pool _. Start ();
Io_service_pool _. Join ();
}
PRIVATE:
Io_service_pool _;
TCP: acceptor _;
};
Int main (INT argc, char * argv [])
{
Try
{
If (argc! = 4)
{
Cerr <"Usage: async_tcp_echo_server <port> <packet_size> <thread_cnt>" <Endl;
Return 1;
}
Short Port = boost: lexical_cast <short> (argv [1]);
Packet_size = boost: lexical_cast <int> (argv [2]);
Int thread_cnt = boost: lexical_cast <int> (argv [3]);
If (packet_size <= 0 | packet_size> max_packet_len)
{
Cerr <"packet_size <= 0 | packet_size> max_packet_len" <Endl;
Return 1;
}
If (thread_cnt <= 0)
{
Cerr <"thread_cnt <= 0" <Endl;
Return 1;
}
Server s (port, thread_cnt );
S. Run ();
}
Catch (STD: exception & E)
{
Cerr <"exception:" <E. What () <Endl;
Return 1;
}
Return 0;
}