tutorial.qbk
来自「Boost provides free peer-reviewed portab」· QBK 代码 · 共 2,067 行 · 第 1/5 页
QBK
2,067 行
``''''''`` { ``''''''`` start_accept(); ``''''''`` } ``''''''``private:The function `start_accept()` creates a socket and initiates an asynchronous accept operation to wait for a new connection. ``''''''`` 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)); ``''''''`` }The function `handle_accept()` is called when the asynchronous accept operation initiated by `start_accept()` finishes. It services the client request, and then calls `start_accept()` to initiate the next accept operation. ``''''''`` void handle_accept(tcp_connection::pointer new_connection, ``''''''`` const boost::system::error_code& error) ``''''''`` { ``''''''`` if (!error) ``''''''`` { ``''''''`` new_connection->start(); ``''''''`` start_accept(); ``''''''`` } ``''''''`` }[heading The tcp_connection class]We will use `shared_ptr` and `enable_shared_from_this` because we want to keep the `tcp_connection` object alive as long as there is an operation that refers to it. ``''''''``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_; ``''''''`` }In the function `start()`, we call boost::asio::async\_write() to serve the data to the client. Note that we are using boost::asio::async\_write(), rather than [link boost_asio.reference.basic_stream_socket.async_write_some ip::tcp::socket::async_write_some()], to ensure that the entire block of data is sent. ``''''''`` void start() ``''''''`` {The data to be sent is stored in the class member `message_` as we need to keep the data valid until the asynchronous operation is complete. ``''''''`` message_ = make_daytime_string();When initiating the asynchronous operation, and if using boost::bind(), you must specify only the arguments that match the handler's parameter list. In this program, both of the argument placeholders (boost::asio::placeholders::error and boost::asio::placeholders::bytes\_transferred) could potentially have been removed, since they are not being used in `handle_write()`. ``''''''`` boost::asio::async_write(socket_, boost::asio::buffer(message_), ``''''''`` boost::bind(&tcp_connection::handle_write, shared_from_this(), ``''''''`` boost::asio::placeholders::error, ``''''''`` boost::asio::placeholders::bytes_transferred));Any further actions for this client connection are now the responsibility of `handle_write()`. ``''''''`` } ``''''''``private: ``''''''`` tcp_connection(boost::asio::io_service& io_service) ``''''''`` : socket_(io_service) ``''''''`` { ``''''''`` } ``''''''`` void handle_write(const boost::system::error_code& /*error*/, ``''''''`` size_t /*bytes_transferred*/) ``''''''`` { ``''''''`` } ``''''''`` tcp::socket socket_; ``''''''`` std::string message_; ``''''''``};[heading Removing unused handler parameters]You may have noticed that the `error`, and `bytes_transferred` parameters are not used in the body of the `handle_write()` function. If parameters are not needed, it is possible to remove them from the function so that it looks like: ``''''''`` void handle_write() ``''''''`` { ``''''''`` }The boost::asio::async\_write() call used to initiate the call can then be changed to just: ``''''''`` boost::asio::async_write(socket_, boost::asio::buffer(message_), ``''''''`` boost::bind(&tcp_connection::handle_write, shared_from_this()));See the [link boost_asio.tutorial.tutdaytime3.src full source listing]Return to the [link boost_asio.tutorial tutorial index]Previous: [link boost_asio.tutorial.tutdaytime2 Daytime.2 - A synchronous TCP daytime server]Next: [link boost_asio.tutorial.tutdaytime4 Daytime.4 - A synchronous UDP daytime client][section:src Source listing for Daytime.3] ``''''''``// ``''''''``// 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/bind.hpp> ``''''''``#include <boost/shared_ptr.hpp> ``''''''``#include <boost/enable_shared_from_this.hpp> ``''''''``#include <boost/asio.hpp> ``''''''``using boost::asio::ip::tcp; ``''''''``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(), ``''''''`` boost::asio::placeholders::error, ``''''''`` boost::asio::placeholders::bytes_transferred)); ``''''''`` } ``''''''``private: ``''''''`` tcp_connection(boost::asio::io_service& io_service) ``''''''`` : socket_(io_service) ``''''''`` { ``''''''`` } ``''''''`` void handle_write(const boost::system::error_code& /*error*/, ``''''''`` size_t /*bytes_transferred*/) ``''''''`` { ``''''''`` } ``''''''`` 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_; ``''''''``}; ``''''''``int main() ``''''''``{ ``''''''`` try ``''''''`` { ``''''''`` boost::asio::io_service io_service; ``''''''`` tcp_server server(io_service); ``''''''`` io_service.run(); ``''''''`` } ``''''''`` catch (std::exception& e) ``''''''`` { ``''''''`` std::cerr << e.what() << std::endl; ``''''''`` } ``''''''`` return 0; ``''''''``}Return to [link boost_asio.tutorial.tutdaytime3 Daytime.3 - An asynchronous TCP daytime server][endsect][endsect][section:tutdaytime4 Daytime.4 - A synchronous UDP daytime client]This tutorial program shows how to use asio to implement a client application with UDP. ``''''''``#include <iostream> ``''''''``#include <boost/array.hpp> ``''''''``#include <boost/asio.hpp> ``''''''``using boost::asio::ip::udp;The start of the application is essentially the same as for the TCP daytime client. ``''''''``int main(int argc, char* argv[]) ``''''''``{ ``''''''`` try ``''''''`` { ``''''''`` if (argc != 2) ``''''''`` { ``''''''`` std::cerr << "Usage: client <host>" << std::endl; ``''''''`` return 1; ``''''''`` } ``''''''`` boost::asio::io_service io_service;We use an [link boost_asio.reference.ip__udp.resolver ip::udp::resolver] object to find the correct remote endpoint to use based on the host and service names. The query is restricted to return only IPv4 endpoints by the [link boost_asio.reference.ip__udp.v4 ip::udp::v4()] argument. ``''''''`` udp::resolver resolver(io_service); ``''''''`` udp::resolver::query query(udp::v4(), argv[1], "daytime");The [link boost_asio.reference.ip__basic_resolver.resolve ip::udp::resolver::resolve()] function is guaranteed to return at least one endpoint in the list if it does not fail. This means it is safe to dereference the return value directly. ``''''''`` udp::endpoint receiver_endpoint = *resolver.resolve(query);Since UDP is datagram-oriented, we will not be using a stream socket. Create an [link boost_asio.reference.ip__udp.socket ip::udp::socket] and initiate contact with the remote endpoint. ``''''''`` udp::socket socket(io_service); ``''''''`` socket.open(udp::v4()); ``''''''`` boost::array<char, 1> send_buf = { 0 }; ``''''''`` socket.send_to(boost::asio::buffer(send_buf), receiver_endpoint);Now we need to be ready to accept whatever the server sends back to us. The endpoint on our side that receives the server's response will be initialised by [link boost_asio.reference.basic_datagram_socket.receive_from ip::udp::socket::receive_from()]. ``''''''`` boost::array<char, 128> recv_buf; ``''''''`` udp::endpoint sender_endpoint; ``''''''`` size_t len = socket.receive_from( ``''''''`` boost::asio::buffer(recv_buf), sender_endpoint); ``''''''`` std::cout.write(recv_buf.data(), len); ``''''''`` }Finally, handle any exceptions that may have been thrown. ``''''''`` catch (std::exception& e) ``''''''`` { ``''''''`` std::cerr << e.what() << std::endl; ``''''''`` } ``''''''`` return 0; ``''''''``}See the [link boost_asio.tutorial.tutdaytime4.src full source listing]Return to the [link boost_asio.tutorial tutorial index]Previous: [link boost_asio.tutorial.tutdaytime3 Daytime.3 - An asynchronous TCP daytime server]Next: [link boost_asio.tutorial.tutdaytime5 Daytime.5 - A synchronous UDP daytime server][section:src Source listing for Daytime.4] ``''''''``// ``''''''``// client.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 <iostream> ``''''''``#include <boost/array.hpp> ``''''''``#include <boost/asio.hpp> ``''''''``using boost::asio::ip::udp; ``''''''``int main(int argc, char* argv[]) ``''''''``{ ``''''''`` try ``''''''`` { ``''''''`` if (argc != 2) ``''''''`` { ``''''''`` std::cerr << "Usage: client <host>" << std::endl; ``''''''`` return 1; ``''''''`` } ``''''''`` boost::asio::io_service io_service; ``''''''`` udp::resolver resolver(io_service); ``''''''`` udp::resolver::query query(udp::v4(), argv[1], "daytime"); ``''''''`` udp::endpoint receiver_endpoint = *resolver.resolve(query); ``''''''`` udp::socket socket(io_service); ``''''''`` socket.open(udp::v4()); ``''''''`` boost::array<char, 1> send_buf = { 0 }; ``''''''`` socket.send_to(boost::asio::buffer(send_buf), receiver_endpoint); ``''''''`` boost::array<char, 128> recv_buf; ``''''''`` udp::endpoint sender_endpoint; ``''''''`` size_t len = socket.receive_from( ``''''''`` boost::asio::buffer(recv_buf), sender_endpoint); ``''''''`` std::cout.write(recv_buf.data(), len); ``''''''`` } ``''''''`` catch (std::exception& e) ``''''''`` { ``''''''`` std::cerr << e.what() << std::endl; ``''''''`` } ``''''''`` return 0;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?