Могу ли я иметь блокирующий ввод / вывод в асинхронном io_machine? - PullRequest
1 голос
/ 28 июня 2011

У меня есть сервер, который в настоящее время использует асинхронный ввод-вывод, чтобы (1) принимать данные из cin и отправлять эти данные через сокет UNIX и (2) принимать данные из сокета UNIX, анализировать эти данные и отправлять ответ. 1001 *

Когда я анализирую данные, как я могу заблокировать ввод / вывод, который происходит в синтаксическом анализаторе (ParseJSON(data_.data()) в примере ниже)? Он должен задавать вопросы и собирать ответы на эти вопросы через cin, прежде чем возвращать parsed для async_write; в настоящее время вопросы печатаются, но ответ отправляется до того, как ответы введены в cin.

socket_ - это stream_protocol::socket от boost::asio, FWIW.

void handle_read(const boost::system::error_code& error,
                 size_t bytes_transferred)
{
    if (!error)
    {
        string parsed = ParseJSON(data_.data());
        async_write(socket_,
            buffer(parsed),
            boost::bind(&session::handle_write,
                shared_from_this(),
                placeholders::error));
    }
}

void handle_write(const boost::system::error_code& error)
{
    if (!error)
    {
        socket_.async_read_some(buffer(data_),
            boost::bind(&session::handle_read,
                shared_from_this(),
                placeholders::error,
                placeholders::bytes_transferred));
    }
}

Сокращенная версия того, что происходит в ParseJSON (некоторые строки заменены на <> для конфиденциальности):

string ParseJSON(string input)
{
    int status;
    string toWrite;

    JSONNode parsed = libjson::parse(input);
    JSONNode::const_iterator iter = parsed.begin(); 
    json_string node_name = iter -> as_string();

    if (node_name.compare("<>") == 0)   
    {
        cout << "<>" << endl;
        cout << "<>";
        cout.flush();
        cin >> status;

        JSONNode n(JSON_NODE);
        n.push_back(JSONNode("<>","<>"));
        JSONNode c(JSON_NODE);
        c.set_name("args");
        c.push_back(JSONNode("<>",status));
        n.push_back(c);
        toWrite = n.write();
        return toWrite;
    }
}

1 Ответ

1 голос
/ 29 июня 2011

Если ParseJSON() делает блокирующее чтение из cin, то оно блокируется, что означает, что handle_read() не выполнит async_write(), пока не вернется ParseJSON().

Мне кажется, проблема в том, что parsed является переменной стека.handle_read() скорее всего вернется до того, как данные действительно будут записаны, а parsed будет уничтожено.Данные, передаваемые в async_write(), должны быть действительными до вызова обработчика завершения (handle_write).

Если handle_read() и и handle_write() являются функциями-членами, вы можете добавить член parsed вдержать данные.В качестве альтернативы, вы можете заключить parsed в shared_ptr, который связан с handle_write() примерно так:

void handle_read(const boost::system::error_code& error,
                 size_t bytes_transferred)
{
    if (!error)
    {
        string *ps = new string(ParseJSON(data_.data()));
        boost::shared_ptr<string> pParsed(ps);
        async_write(socket_,
            buffer(*pParsed),
            boost::bind(&session::handle_write,
                shared_from_this(),
                pParsed,
                placeholders::error));
    }
}

void handle_write(boost::shared_ptr<string> pParsed, 
                  const boost::system::error_code& error)
{
    if (!error)
    {
        socket_.async_read_some(buffer(data_),
            boost::bind(&session::handle_read,
                shared_from_this(),
                placeholders::error,
                placeholders::bytes_transferred));
    }
}

Когда завершится обработчик завершения, последняя ссылка на shared_ptr исчезнет и ps будетуничтожены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...