From: http://blog.chinaunix.net/uid-1720597-id-85507.html
客户端:
- #include <iostream>
- #include <boost/asio.hpp>
- #include <boost/bind.hpp>
- #include <boost/shared_ptr.hpp>
- #include <boost/enable_shared_from_this.hpp>
-
- using boost::asio::ip::tcp;
- using boost::asio::ip::address;
-
- class session: public boost::enable_shared_from_this<session> {
- public:
- session(boost::asio::io_service &io_service, tcp::endpoint &endpoint)
- : io_service_(io_service), socket_(io_service), endpoint_(endpoint)
- {
- }
-
- void start() {
- socket_.async_connect(endpoint_,
- boost::bind(&session::handle_connect,
- shared_from_this(),
- boost::asio::placeholders::error));
- }
-
- private:
- void handle_connect(const boost::system::error_code &error) {
- if (error) {
- if (error.value() != boost::system::errc::operation_canceled) {
- std::cerr << boost::system::system_error(error).what() << std::endl;
- }
-
- socket_.close();
- return;
- }
-
- static tcp::no_delay option(true);
- socket_.set_option(option);
-
- strcpy(buf, "Hello World!\n");
- boost::asio::async_write(socket_,
- boost::asio::buffer(buf, strlen(buf)),
- boost::bind(&session::handle_write,
- shared_from_this(),
- boost::asio::placeholders::error,
- boost::asio::placeholders::bytes_transferred));
- }
-
- void handle_write(const boost::system::error_code& error, size_t bytes_transferred) {
- memset(buf, sizeof(buf), 0);
- boost::asio::async_read_until(socket_,
- sbuf,
- "\n",
- boost::bind(&session::handle_read,
- shared_from_this(),
- boost::asio::placeholders::error,
- boost::asio::placeholders::bytes_transferred));
- }
-
- void handle_read(const boost::system::error_code& error, size_t bytes_transferred) {
- std::cout << buf << std::endl;
- }
-
- private:
- boost::asio::io_service &io_service_;
- tcp::socket socket_;
- tcp::endpoint &endpoint_;
- char buf[1024];
- boost::asio::streambuf sbuf;
- };
-
- typedef boost::shared_ptr<session> session_ptr;
-
- int main(int argc, char* argv[])
- {
- boost::asio::io_service io_service;
- tcp::endpoint endpoint(address::from_string("192.168.1.1"), 10028);
-
- session_ptr new_session(new session(io_service, endpoint));
- new_session->start();
- io_service.run();
- return 0;
- }
服务器:
- #include <string.h>
- #include <boost/asio.hpp>
- #include <boost/bind.hpp>
- #include <boost/shared_ptr.hpp>
- #include <boost/enable_shared_from_this.hpp>
-
- using boost::asio::ip::tcp;
- using boost::asio::ip::address;
-
- class session: public boost::enable_shared_from_this<session> {
- public:
- session(boost::asio::io_service &io_service): socket_(io_service)
- {
- }
-
- void start() {
- static tcp::no_delay option(true);
- socket_.set_option(option);
-
- boost::asio::async_read_until(socket_,
- sbuf_,
- "\n",
- boost::bind(&session::handle_read,
- shared_from_this(),
- boost::asio::placeholders::error,
- boost::asio::placeholders::bytes_transferred));
- }
-
- tcp::socket &socket() {
- return socket_;
- }
-
- private:
- void handle_write(const boost::system::error_code& error, size_t bytes_transferred) {
- boost::asio::async_read_until(socket_,
- sbuf_,
- "\n",
- boost::bind(&session::handle_read,
- shared_from_this(),
- boost::asio::placeholders::error,
- boost::asio::placeholders::bytes_transferred));
- }
-
- void handle_read(const boost::system::error_code& error, size_t bytes_transferred) {
- boost::asio::async_write(socket_,
- sbuf_,
- boost::bind(&session::handle_write,
- shared_from_this(),
- boost::asio::placeholders::error,
- boost::asio::placeholders::bytes_transferred));
- }
-
- private:
- tcp::socket socket_;
- boost::asio::streambuf sbuf_;
- };
-
- typedef boost::shared_ptr<session> session_ptr;
-
- class server {
- public:
- server(boost::asio::io_service &io_service, tcp::endpoint &endpoint)
- : io_service_(io_service), acceptor_(io_service, endpoint)
- {
- session_ptr new_session(new session(io_service_));
- acceptor_.async_accept(new_session->socket(),
- boost::bind(&server::handle_accept,
- this,
- new_session,
- boost::asio::placeholders::error));
- }
-
- void handle_accept(session_ptr new_session, const boost::system::error_code& error) {
- if (error) {
- return;
- }
-
- new_session->start();
- new_session.reset(new session(io_service_));
- acceptor_.async_accept(new_session->socket(),
- boost::bind(&server::handle_accept,
- this,
- new_session,
- boost::asio::placeholders::error));
- }
-
- void run() {
- io_service_.run();
- }
-
- private:
- boost::asio::io_service &io_service_;
- tcp::acceptor acceptor_;
- };
-
- int main(int argc, char* argv[])
- {
- boost::asio::io_service io_service;
- tcp::endpoint endpoint(address::from_string("192.168.1.1"), 10028);
-
- server s(io_service, endpoint);
- s.run();
- return 0;
- }
编译:
g++ -Wall -o client client.cpp -lboost_system
g++ -Wall -o server server.cpp -lboost_system
这里需要注意的是: async_write, async_read, async_read_until 都是需要达到特定条件才会调用回调函数,
在调用回调函数之前, 不能再次调用, 否则接收到的数据很可能是乱的. 所以, 在实际代码当中, 会有一个写缓冲队列, 当需要write的时, 先放到队列中, 如果队列个数为1, 则调用async_write, 否则等待函数回调, 当函数回调时将首个元素从队列中移除, 然后接着发送下一个, 直到队列为空.
对于client, 由于is_open在async_connect之后就是true状态了, 因此在async_connect回调返回之前没有方法知道是否已经连接成功, 实际代码当中一般会增加一个变量以表示该套接字是否已经允许发送数据.