Boost.Asio翻译(五)
Daytime.7 - A combined TCP/UDP asynchronous server
This tutorial program shows how to combine the two asynchronous servers that we have just written, into a single server application.
本例示范了我们如何将已经实现的两种异步服务器整合为一个服务器应用程序。
The main() function
int
main()
{
try
{
boost::asio::io_service io_service;
We will begin by creating a server object to accept a TCP client connection.
我们首先创建一个用于接收TCP客户端连接的服务器对象。
tcp_server server1(io_service);
We also need a server object to accept a UDP client request.
我们也需要一个用于接收UDP客户端请求的服务器对象。
udp_server server2(io_service);
We have created two lots of work for the boost::asio::io_service object to do.
这样我们就已经创建了两个需要完成很多工作的服务器,而这些工作都由boost::asio::io_service对象完成。
io_service.run();
}
catch (std::exception & e)
{
std::cerr << e.what() << std::endl;
}
return 0 ;
}
The tcp_connection and tcp_server classes
TCP连接和TCP服务器类
The following two classes are taken from Daytime.3 .
下面的两个类实例来自例子Daytime.3。
class
tcp_connection
:
public
boost::enable_shared_from_this
<
tcp_connection
>
{
public
:
typedef boost::shared_ptr
<
tcp_connection
>
pointer;
static
pointer create(boost::asio::io_service
&
io_service)
{
return
pointer(
new
tcp_connection(io_service));
}
tcp::socket
&
socket()
{
return
socket_;
}
void
start()
{
message_
=
make_daytime_string();
boost::asio::async_write(socket_, boost::asio::buffer(message_),
boost::bind(
&
tcp_connection::handle_write, shared_from_this()));
}
private
:
tcp_connection(boost::asio::io_service
&
io_service)
: socket_(io_service)
{
}
void
handle_write()
{
}
tcp::socket socket_;
std::
string
message_;
};
class
tcp_server
{
public
:
tcp_server(boost::asio::io_service
&
io_service)
: acceptor_(io_service, tcp::endpoint(tcp::v4(),
13
))
{
start_accept();
}
private
:
void
start_accept()
{
tcp_connection::pointer new_connection
=
tcp_connection::create(acceptor_.io_service());
acceptor_.async_accept(new_connection
->
socket(),
boost::bind(
&
tcp_server::handle_accept,
this
, new_connection,
boost::asio::placeholders::error));
}
void
handle_accept(tcp_connection::pointer new_connection,
const
boost::system::error_code
&
error)
{
if
(
!
error)
{
new_connection
->
start();
start_accept();
}
}
tcp::acceptor acceptor_;
};
The udp_server class
UDP服务器类
Similarly, this next class is taken from the previous tutorial step .
同样,下面的这个类实例也是来自以前的示例程序。
class
udp_server
{
public
:
udp_server(boost::asio::io_service
&
io_service)
: socket_(io_service, udp::endpoint(udp::v4(),
13
))
{
start_receive();
}
private
:
void
start_receive()
{
socket_.async_receive_from(
boost::asio::buffer(recv_buffer_), remote_endpoint_,
boost::bind(
&
udp_server::handle_receive,
this
,
boost::asio::placeholders::error));
}
void
handle_receive(
const
boost::system::error_code
&
error)
{
if
(
!
error
||
error
==
boost::asio::error::message_size)
{
boost::shared_ptr
<
std::
string
>
message(
new
std::
string
(make_daytime_string()));
socket_.async_send_to(boost::asio::buffer(
*
message), remote_endpoint_,
boost::bind(
&
udp_server::handle_send,
this
, message));
start_receive();
}
}
void
handle_send(boost::shared_ptr
<
std::
string
>
/*
message
*/
)
{
}
udp::socket socket_;
udp::endpoint remote_endpoint_;
boost::array
<
char
,
1
>
recv_buffer_;
};
See the full source listing
全部源码:
//
// server.cpp
// ~~~~~~~~~~
//
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt )
//
#include < ctime >
#include < iostream >
#include < string >
#include < boost / array.hpp >
#include < boost / bind.hpp >
#include < boost / shared_ptr.hpp >
#include < boost / enable_shared_from_this.hpp >
#include < boost / asio.hpp >
using boost::asio::ip::tcp;
using boost::asio::ip::udp;
std:: string make_daytime_string()
{
using namespace std; // For time_t, time and ctime;
time_t now = time( 0 );
return ctime( & now);
}
class tcp_connection
: public boost::enable_shared_from_this < tcp_connection >
{
public :
typedef boost::shared_ptr < tcp_connection > pointer;
static pointer create(boost::asio::io_service & io_service)
{
return pointer( new tcp_connection(io_service));
}
tcp::socket & socket()
{
return socket_;
}
void start()
{
message_ = make_daytime_string();
boost::asio::async_write(socket_, boost::asio::buffer(message_),
boost::bind( & tcp_connection::handle_write, shared_from_this()));
}
private :
tcp_connection(boost::asio::io_service & io_service)
: socket_(io_service)
{
}
void handle_write()
{
}
tcp::socket socket_;
std:: string message_;
};
class tcp_server
{
public :
tcp_server(boost::asio::io_service & io_service)
: acceptor_(io_service, tcp::endpoint(tcp::v4(), 13 ))
{
start_accept();
}
private :
void start_accept()
{
tcp_connection::pointer new_connection =
tcp_connection::create(acceptor_.io_service());
acceptor_.async_accept(new_connection -> socket(),
boost::bind( & tcp_server::handle_accept, this , new_connection,
boost::asio::placeholders::error));
}
void handle_accept(tcp_connection::pointer new_connection,
const boost::system::error_code & error)
{
if ( ! error)
{
new_connection -> start();
start_accept();
}
}
tcp::acceptor acceptor_;
};
class udp_server
{
public :
udp_server(boost::asio::io_service & io_service)
: socket_(io_service, udp::endpoint(udp::v4(), 13 ))
{
start_receive();
}
private :
void start_receive()
{
socket_.async_receive_from(
boost::asio::buffer(recv_buffer_), remote_endpoint_,
boost::bind( & udp_server::handle_receive, this ,
boost::asio::placeholders::error));
}
void handle_receive( const boost::system::error_code & error)
{
if ( ! error || error == boost::asio::error::message_size)
{
boost::shared_ptr < std:: string > message(
new std:: string (make_daytime_string()));
socket_.async_send_to(boost::asio::buffer( * message), remote_endpoint_,
boost::bind( & udp_server::handle_send, this , message));
start_receive();
}
}
void handle_send(boost::shared_ptr < std:: string > /* message */ )
{
}
udp::socket socket_;
udp::endpoint remote_endpoint_;
boost::array < char , 1 > recv_buffer_;
};
int main()
{
try
{
boost::asio::io_service io_service;
tcp_server server1(io_service);
udp_server server2(io_service);
io_service.run();
}
catch (std::exception & e)
{
std::cerr << e.what() << std::endl;
}
return 0 ;
}
// server.cpp
// ~~~~~~~~~~
//
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt )
//
#include < ctime >
#include < iostream >
#include < string >
#include < boost / array.hpp >
#include < boost / bind.hpp >
#include < boost / shared_ptr.hpp >
#include < boost / enable_shared_from_this.hpp >
#include < boost / asio.hpp >
using boost::asio::ip::tcp;
using boost::asio::ip::udp;
std:: string make_daytime_string()
{
using namespace std; // For time_t, time and ctime;
time_t now = time( 0 );
return ctime( & now);
}
class tcp_connection
: public boost::enable_shared_from_this < tcp_connection >
{
public :
typedef boost::shared_ptr < tcp_connection > pointer;
static pointer create(boost::asio::io_service & io_service)
{
return pointer( new tcp_connection(io_service));
}
tcp::socket & socket()
{
return socket_;
}
void start()
{
message_ = make_daytime_string();
boost::asio::async_write(socket_, boost::asio::buffer(message_),
boost::bind( & tcp_connection::handle_write, shared_from_this()));
}
private :
tcp_connection(boost::asio::io_service & io_service)
: socket_(io_service)
{
}
void handle_write()
{
}
tcp::socket socket_;
std:: string message_;
};
class tcp_server
{
public :
tcp_server(boost::asio::io_service & io_service)
: acceptor_(io_service, tcp::endpoint(tcp::v4(), 13 ))
{
start_accept();
}
private :
void start_accept()
{
tcp_connection::pointer new_connection =
tcp_connection::create(acceptor_.io_service());
acceptor_.async_accept(new_connection -> socket(),
boost::bind( & tcp_server::handle_accept, this , new_connection,
boost::asio::placeholders::error));
}
void handle_accept(tcp_connection::pointer new_connection,
const boost::system::error_code & error)
{
if ( ! error)
{
new_connection -> start();
start_accept();
}
}
tcp::acceptor acceptor_;
};
class udp_server
{
public :
udp_server(boost::asio::io_service & io_service)
: socket_(io_service, udp::endpoint(udp::v4(), 13 ))
{
start_receive();
}
private :
void start_receive()
{
socket_.async_receive_from(
boost::asio::buffer(recv_buffer_), remote_endpoint_,
boost::bind( & udp_server::handle_receive, this ,
boost::asio::placeholders::error));
}
void handle_receive( const boost::system::error_code & error)
{
if ( ! error || error == boost::asio::error::message_size)
{
boost::shared_ptr < std:: string > message(
new std:: string (make_daytime_string()));
socket_.async_send_to(boost::asio::buffer( * message), remote_endpoint_,
boost::bind( & udp_server::handle_send, this , message));
start_receive();
}
}
void handle_send(boost::shared_ptr < std:: string > /* message */ )
{
}
udp::socket socket_;
udp::endpoint remote_endpoint_;
boost::array < char , 1 > recv_buffer_;
};
int main()
{
try
{
boost::asio::io_service io_service;
tcp_server server1(io_service);
udp_server server2(io_service);
io_service.run();
}
catch (std::exception & e)
{
std::cerr << e.what() << std::endl;
}
return 0 ;
}