提升asio网络分开发送和接收

时间:2015-11-12 07:58:03

标签: c++ multithreading sockets boost network-programming

  • 服务器可以随时向客户端发送数据。就像在服务器中一样,服务器包含某种其他类可能调用的发送函数。
  • 服务器永远异步读取
  • 同样适用于客户。

我对boost :: asio中的网络相当新。我理解TCP异步服务器和客户端上的示例,但这些是回显客户端/服务器。如果服务器接收数据,它将立即发回。但我需要服务器接收数据,为另一个类做一些其他操作,然后发送给特定客户端(服务器将连接多个客户端)。此发送可能在1秒或任何给定的时间后发送。

在使用GNU Library的套接字编程中,我实现了这一点。您在服务器中有一个线程用于侦听,另一个线程用于发送。对于客户来说也是如此我已经在boost中研究了这种方法:Asio但是却无法了解如何实现它。任何人都可以指出正确的方向吗?

1 个答案:

答案 0 :(得分:2)

全双工插座不需要多个线程。事实上,如果你不这样做会更容易。

如果你有多个线程,你必须使用一个strand来协调套接字上的所有异步操作。

除此之外,它真的就是这么简单:

最简单的例子:

<强> Live On Coliru

#include <boost/asio.hpp>
#include <memory>
#include <iostream>

namespace io = boost::asio;
using tcp = io::ip::tcp;
using boost::system::error_code;

struct session : std::enable_shared_from_this<session> {

    session(io::io_service& svc) : _sock(svc), _tim(svc) {}

    void run() {
        ping_loop();
        receive_loop();
    }

  private:
    friend class server;
    tcp::socket        _sock;
    io::deadline_timer _tim;
    io::streambuf      _buf;

    void receive_loop() {
        auto This = shared_from_this();
        io::async_read_until(_sock, _buf, "\n", [This,this](error_code ec, size_t) {
                if (ec)
                    std::cerr << "Receive error: " << ec.message() << "\n";
                else {
                    std::cout << "Received '" << &_buf << "'\n";

                    // chain
                    receive_loop();
                }
            });
    }

    std::string _ping = "ping\n";

    void ping_loop() {
        _tim.expires_from_now(boost::posix_time::millisec(100));
        auto This = shared_from_this();

        _tim.async_wait([This,this](error_code ec) {
                if (!ec) {
                    io::async_write(_sock, io::buffer(_ping), [This,this](error_code,size_t) {});

                    // chain
                    ping_loop();
                }
            });
    }
};

class server {
  public:

    void start() {
        _acc.bind({ io::ip::address_v4{}, 6768 });
        _acc.listen(5);
        accept_loop();

        _svc.run(); // TODO thread? shutdown?
    }

  private:

    void accept_loop() {
        auto sess = std::make_shared<session>(_svc);

        _acc.async_accept(sess->_sock, [this,sess](error_code ec){
                if (ec) {
                    std::cerr << "Accept error: " << ec.message() << "\n";
                } else {
                    sess->run();

                    // chain
                    accept_loop();
                }
            });
    }

    io::io_service _svc;
    tcp::acceptor _acc { _svc, tcp::v4() };
};

int main() {
    server s;
    s.start();
}

运行这样的客户端/客户端时:

while sleep 1; do date; done | nc localhost 6767

服务器输出如:

Received 'Thu Nov 12 10:24:08 CET 2015
'
Received 'Thu Nov 12 10:24:09 CET 2015
'
Received 'Thu Nov 12 10:24:10 CET 2015
'
Received 'Thu Nov 12 10:24:11 CET 2015
'
Received 'Thu Nov 12 10:24:12 CET 2015
'
Received 'Thu Nov 12 10:24:13 CET 2015
'
Received 'Thu Nov 12 10:24:14 CET 2015
'
Received 'Thu Nov 12 10:24:15 CET 2015
'
Receive error: End of file

客户收到连续

ping
ping
...