首页 > 代码库 > Boost.Asio c++ 网络编程翻译(16)
Boost.Asio c++ 网络编程翻译(16)
TCP异步服务端
核心功能和同步服务端的功能类似,如下:
class talk_to_client : public boost::enable_shared_from_this<talk_to_
client>
, boost::noncopyable {
typedef talk_to_client self_type;
talk_to_client() : sock_(service), started_(false) {}
public:
typedef boost::system::error_code error_code;
typedef boost::shared_ptr<talk_to_client> ptr;
void start() {
started_ = true;
do_read(); }
static ptr new_() {
ptr new_(new talk_to_client);
return new_;
}
void stop() {
if ( !started_) return;
started_ = false;
sock_.close();
}
ip::tcp::socket & sock() { return sock_;}
...
private:
ip::tcp::socket sock_;
enum { max_msg = 1024 };
char read_buffer_[max_msg];
char write_buffer_[max_msg];
bool started_;
};
因为我们是非常简单的回显服务,这里不需要一个is_started()方法。对每个客户端,仅仅读取它的消息,回显,然后关闭它。
do_read(),do_write()和read_complete()方法和TCP同步服务端的完全一致。
主要的逻辑同样是在on_read()和on_write()方法中:
void on_read(const error_code & err, size_t bytes) {
if ( !err) {
std::string msg(read_buffer_, bytes);
do_write(msg + "\n");
}
stop(); }
void on_write(const error_code & err, size_t bytes) {
do_read();
}
对客户端的处理如下:
ip::tcp::acceptor acceptor(service, ip::tcp::endpoint(ip::tcp::v4(),
8001));
void handle_accept(talk_to_client::ptr client, const error_code & err)
{
client->start();
talk_to_client::ptr new_client = talk_to_client::new_();
acceptor.async_accept(new_client->sock(),
boost::bind(handle_accept,new_client,_1));
}
int main(int argc, char* argv[]) {
talk_to_client::ptr client = talk_to_client::new_();
acceptor.async_accept(client->sock(),
boost::bind(handle_accept,client,_1));
service.run();
}
每一次客户端连接到服务时,handle_accept被调用,它会异步地从客户端读取,然后同样异步地等待一个新的客户端。
代码
你会在这本书相应的代码中得到所有4个应用(TCP回显同步客户端,TCP回显同步服务端,TCP回显异步客户端,TCP回显异步服务端)。当测试时,你可以使用任意客户端/服务端组合(比如,一个异步客户端和一个同步服务端)。
UDP回显服务端/客户端
因为UDP不能保证所有信息都抵达接收者,我们不能保证“信息以回车结尾”。
没收到消息,我们只是回显,但是没有socket去关闭(在服务端),因为我们是UDP。
UDP同步回显客户端
UDP回显客户端比TCP回显客户端要简单:
ip::udp::endpoint ep( ip::address::from_string("127.0.0.1"), 8001);
void sync_echo(std::string msg) {
ip::udp::socket sock(service, ip::udp::endpoint(ip::udp::v4(), 0)
);
sock.send_to(buffer(msg), ep);
char buff[1024];
ip::udp::endpoint sender_ep;
int bytes = sock.receive_from(buffer(buff), sender_ep);
std::string copy(buff, bytes);
std::cout << "server echoed our " << msg << ": "
<< (copy == msg ? "OK" : "FAIL") << std::endl;
sock.close();
}
int main(int argc, char* argv[]) {
char* messages[] = { "John says hi", "so does James", "Lucy got
home", 0 };
boost::thread_group threads;
for ( char ** message = messages; *message; ++message) {
threads.create_thread( boost::bind(sync_echo, *message));
boost::this_thread::sleep( boost::posix_time::millisec(100));
}
threads.join_all();
}
所有的逻辑都在synch_echo()中;连接到服务端,发送消息,接收服务端的回显,然后关闭连接。
UDP同步回显服务端
UDP回显服务端会是你写过的最简单的服务端:
io_service service;
void handle_connections() {
char buff[1024];
ip::udp::socket sock(service, ip::udp::endpoint(ip::udp::v4(),
8001));
while ( true) {
ip::udp::endpoint sender_ep;
int bytes = sock.receive_from(buffer(buff), sender_ep);
std::string msg(buff, bytes);
sock.send_to(buffer(msg), sender_ep);
} }
int main(int argc, char* argv[]) {
handle_connections();
}
它非常简单,而且能很好的自释。
我把异步UDP客户端和服务端留给读者当作一个练习。
总结
我们已经写了完成的应用,最终让Boost.Asio得以工作。回显应用是开始学习一个库时非常好的工具。你可以经常学习和运行这个章节所展示的代码,这样你就可以非常容易地记住这个库的基础。
在下一章,我们会建立更复杂的客户端/服务端应用,我们要确保避免低级错误,比如内存泄漏,死锁等等。
Boost.Asio c++ 网络编程翻译(16)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。