【问题标题】:Boost::Asio async chat client stops communicating with serverBoost::Asio 异步聊天客户端停止与服务器通信
【发布时间】:2020-04-24 15:04:07
【问题描述】:

我一直在尝试使用 Boost::asio 构建消息传递应用程序,但出于某种原因,我修改后的 chat_client 版本没有收到任何消息。我首先认为io_context 处理程序用完了,但事实并非如此。奇怪的是,如果我消除 controller.cpp 并在 main 中创建一个 chat_client 对象,我的问题就解决了。

chat_client.cpp(从示例修改)我已经硬编码了我的服务器的 IP 和端口以进行测试

#include <string.h>
#include <string>

#include "chat_client.h"

using asio::ip::tcp;

typedef std::deque<chat_message> chat_message_queue;

chat_client::chat_client(std::string ip, std::string port)
    : socket_(io_context_)
{
    tcp::resolver resolver(io_context_);
    endpoints = resolver.resolve(ip, port);

    do_connect(endpoints);
    t = new std::thread([this](){ io_context_.run(); });
}

chat_client::~chat_client()
{
    t->join();
}
void chat_client::write(const chat_message& msg)
{
    asio::post(io_context_,
        [this, msg]()
        {
            bool write_in_progress = !write_msgs_.empty();
            write_msgs_.push_back(msg);
            if (!write_in_progress)
            {
                do_write();
            }
        });
}

void chat_client::close()
{
    asio::post(io_context_, [this]() { socket_.close(); });
}


void chat_client::do_connect(const tcp::resolver::results_type& endpoints)
{
    asio::async_connect(socket_, endpoints,
        [this](std::error_code ec, tcp::endpoint)
        {
            if (!ec)
            {
            do_read_header();
            }
        });
}

void chat_client::do_read_header()
{
    asio::async_read(socket_,
        asio::buffer(read_msg_.data(), chat_message::header_length),
        [this](std::error_code ec, std::size_t /*length*/)
        {
            if (!ec && read_msg_.decode_header())
            {
                do_read_body();
            }
            else
            {
                socket_.close();
            }
        });
}

void chat_client::do_read_body()
{
    asio::async_read(socket_,
        asio::buffer(read_msg_.body(), read_msg_.body_length()),
        [this](std::error_code ec, std::size_t /*length*/)
        {
            if (!ec)
            {
                std::cout.write(read_msg_.body(), read_msg_.body_length());
                std::cout << "\n";  

                do_read_header();
            }
            else
            {
                socket_.close();
            }
        });
}

void chat_client::do_write()
{
    asio::async_write(socket_,
        asio::buffer(write_msgs_.front().data(),
            write_msgs_.front().length()),
        [this](std::error_code ec, std::size_t /*length*/)
        {
            if (!ec)
            {
                write_msgs_.pop_front();
                if (!write_msgs_.empty())
                {
                    do_write();
                }
            }
            else
            {
                socket_.close();
            }
        });
}

控制器.cpp

#include <stdexcept>
#include "controller.h"

//#include "chat_client.h" inside controller.h

/*Constructor*/
Controller::Controller() {}

void Controller::execute_cmd(int cmd)
{
    switch(cmd)
    {
        case 1: //Create chat_client
        {
            try
            {
                c = new chat_client("192.168.0.11", "5000");

                chat_message msg;
                msg.body_length(5);
                std::memcpy(msg.body(), "test", msg.body_length());
                msg.encode_header();

                c->write(msg);
            }
            catch(std::runtime_error& e)
            {
                std::cerr << "Cannot create chat_client" << std::endl;
            }
        }
        case 2: //Close chat_client
        {
            c->close();
            delete c;
        }
        case 3: //TESTING
        {
            char line[chat_message::max_body_length + 1];
            while (std::cin.getline(line, chat_message::max_body_length + 1))
            {
                chat_message msg;
                msg.body_length(std::strlen(line));
                std::memcpy(msg.body(), line, msg.body_length());
                msg.encode_header();
                c->write(msg);
            }
        }
    }
}

用于测试的main.cpp

#include "controller.h"

int main(int argc, char** argv)
{
    Controller c;
    c.execute_cmd(1); //create chat_client
    c.execute_cmd(2); //Start sending messages

    return 0;
}

【问题讨论】:

  • break 中的 switch 语句在哪里?对于1,所有的case都会被执行,所以聊天实例会立即关闭。同样对于发送消息,您应该传递 3 而不是 2。
  • @rafix07 是的!如此微不足道的错误。谢谢。

标签: c++ multithreading boost-asio


【解决方案1】:

您的 switch 语句 un execute_cmd 在 case 结束时没有中断。在 switch statemte 中,如果 case 不以 break 结尾,则继续下一个 case 的下一个句子。 c.execite_cmd(1) 真正执行 cmd 1、2 和 3。记住读写 io 是异步的,所以在 cmd 2 中关闭连接。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-03
    相关资源
    最近更新 更多