创建boost :: asio后,异步服务器立即关闭

时间:2019-02-23 14:18:46

标签: c++ boost asio

服务器启动并接受连接,即使连接了10个以上的所有客户端,也会发送一条消息,但是没有响应。
读写功能使用接收到的客户帐户的索引并对其进行处理。因此,标头中还有一个附加参数。
我们接受连接并将其编号传递到标题,然后使用该编号的套接字进行连接。

#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <clocale>
#include <vector>
#include <conio.h>

using namespace boost::asio;
using namespace std;

class tcp_server
{
private:
    io_service service;
    int port;
    enum { buff_size = 1024 };
    ip::tcp::endpoint endpoint;
    ip::tcp::acceptor acceptor;
    int countClients = 0;
    int accept_i = 0;
    struct client
    {
        ip::tcp::socket sock;
        char buff[buff_size] = { };
    };
    vector<client> clients;
public:
    tcp_server(io_service& service, int port) : service(), acceptor(service), endpoint(ip::tcp::v4(), port)
    {
        this->port;
        acceptor.open(endpoint.protocol());
        acceptor.set_option(ip::tcp::acceptor::reuse_address(true));
        acceptor.bind(endpoint);
        acceptor.listen();
        clients.reserve(10);
    }
    void start()
    {
        start_service_in_thread();
    }
    void start_service_in_thread()
    {
        for (int i = 0; i < 10; ++i)
            boost::thread(service_func_for_thread);
        for (int i = 0; i < 10; ++i)
        {
            boost::thread(acceptor_func_for_thread);
            accept_i++;
        }
    }
    void service_func_for_thread()
    {
        service.run();
    }
    void accept_handler(const boost::system::error_code& error)
    {
        if (!error)
        {
            countClients++;
            do_read_this(countClients - 1);
        }
        else
        {
            cout << "Acceptor error\n";
            cout << error.message() << endl;
        }
    }
    void acceptor_func_for_thread()
    {
        acceptor.async_accept(
            clients[accept_i].sock,
            boost::bind(&tcp_server::accept_handler, this, boost::asio::placeholders::error)
        );
    }
    void do_read_this(int thisClientIndex)
    {
        clients[thisClientIndex].sock.async_read_some(
            buffer(clients[thisClientIndex].buff),
            boost::bind(&tcp_server::read_handler,
                this,
                boost::asio::placeholders::error,
                boost::asio::placeholders::bytes_transferred,
                thisClientIndex)
        );
    }
    void read_handler(const boost::system::error_code& error, size_t bytes_transferred, int thisClientIndex)
    {
        if (!error)
        {
            clients[thisClientIndex].sock.async_write_some(
                buffer(clients[thisClientIndex].buff),
                boost::bind(&tcp_server::write_handler,
                    this,
                    boost::asio::placeholders::error,
                    boost::asio::placeholders::bytes_transferred,
                    thisClientIndex)
            );
        }
        else
        {
            cout << "Error reading from socket\n";
            cout << error.message() << endl;
        }
    }
    void write_handler(const boost::system::error_code& error, size_t bytes_transferred, int thisClientIndex)
    {
        if (!error)
        {
            do_read_this(thisClientIndex);
        }
        else
        {
            cout << "Error write in socket\n";
            cout << error.message() << endl;
        }
    }
};

int main(int argc, char *argv[])
{
    try
    {
        setlocale(LC_ALL, "Rus");
        io_service service;
        tcp_server* server = new tcp_server{ service, 5000 };
        server->start();
        service.run();
    }
    catch (exception& ex)
    {
        cout << "Exception: " << ex.what();
    }
    return 0;
}

客户端连接到服务器,并且当它发送连接时,没有收到响应。 请帮忙。

2 个答案:

答案 0 :(得分:0)

    service.run();中的
  1. main无关,因此会立即返回,因此main返回会导致程序结束。

  2. 此处无需创建后台线程。

  3. (再次)您将创建一个临时对象boost::thread,该对象立即超出范围。而且,除非指定了BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE,否则最终将导致一堆分离的线程。

答案 1 :(得分:0)

io_service::run()方法无事可做时,它会返回。

您应该

  1. post()在调用io_service之前至少要执行run()的一项任务,

  2. 或使用io_service::work

    “锁定”它
    io_service service;
    boost::asio::io_service::work work(service);
    

后者需要调用service.stop()才能导致run()退出,否则它将永久运行。

但是请注意:在异步应用程序中,您实际上不需要两个io_service或任何线程。