c++ - Boost asio, shared_from_this() error R6010, and async_read() eof

标签 c++ boost asynchronous boost-asio

我正在尝试与 boost asio 聊天,有官员 example作为引用。但实际上我在使用 async_read 时遇到了两个问题,首先,为什么我的 EoF(文件结尾)和我的连接(和应用程序)在客户端中关闭得如此之快?

然后我在 ChatParticipant 的 async_read 中遇到问题:如果我将“Shared_from_this()”作为 boost::bind 的第二个参数传递,我会得到错误 R6010,但如果我传递一个简单的“this”,我不会没有它。

感谢您的帮助:)

这是我关心的代码:

聊天服务器

    class ChatServer
    {
    public:
        ChatServer(boost::asio::io_service& io_service, const tcp::endpoint& endpoint): _io_service(io_service), _acceptor(io_service, endpoint)
        {
            startAccept();
        }

        void startAccept()
        {
            std::cout << "accepting a new client" << std::endl;
            shared_ptr<ServerParticipant> newParticipant(new ServerParticipant(_io_service, &_room));
            _acceptor.async_accept(newParticipant->getSocket(), boost::bind(&ChatServer::handleAccept, this, boost::asio::placeholders::error, newParticipant));
        }

        void handleAccept(const boost::system::error_code& e, shared_ptr<ServerParticipant> newParticipant)
        {
            if (!e)
            {

                std::cout << "accepted a new client" << std::endl;
                boost::asio::async_read(newParticipant->getSocket(),
                    boost::asio::buffer(_readMsgCache.getAllMessage(), ChatMessage::header_length),
                    boost::bind(&ChatServer::read, this,
                boost::asio::placeholders::error));
                //newParticipant->start();
                startAccept();
            }
            else
            {
                std::cerr << e.message() << std::endl;
            }
        }

        void read(const boost::system::error_code& e)
        {
            if (e && e == boost::asio::error::eof)
            {
                std::cerr << "closed" << std::endl;
            }
            if (e)
            {
                std::cerr << e.message() << std::endl;
            }

            else
            {
                std::cout << "Reaaad" << std::endl;
            }

        }
    private:
        boost::asio::io_service& _io_service;
        tcp::acceptor _acceptor;
        ChatMessage _readMsgCache;
}

聊天参与者

    class ChatParticipant : public boost::enable_shared_from_this<ChatParticipant>
    {
    public :
        ChatParticipant(boost::asio::io_service& service) : _id(0), _service(service), _socket(service)
        {}

        virtual void start()
        {
            startRead();
        }

        void startRead()
        {
            std::cout << "Start read" << std::endl;
            boost::asio::async_read(_socket,
                boost::asio::buffer(_readMsgCache.getAllMessage(), 4),
            boost::bind(
            &ChatParticipant::readHeader, shared_from_this(),
              boost::asio::placeholders::error));
        }
// some functions about decoding the message...

protected:
    int _id;
    boost::asio::io_service& _service;
    tcp::socket _socket;


    std::deque<ChatMessage> _writeMsgCache;
    ChatMessage _readMsgCache;

聊天客户端

using boost::asio::ip::tcp;

class ChatClient
{
public:
    ChatClient(boost::asio::io_service& service, tcp::endpoint& endpoint) : _service(service), _client(service)
    {
        _client.getSocket().async_connect(endpoint, boost::bind(&ChatClient::handleConnect, this, boost::asio::placeholders::error));
    }


    void handleConnect(const boost::system::error_code& err)
    {

        if (err)
        {
            std::cerr << err.message();
        }
        else
        {
            _client.start();

            /*
            ChatMessage message;
            message.setMessage("hello");
            _client.speak(message);
            */
        }
    }

    void read(const boost::system::error_code& e)
    {
        if (e)
        {
            std::cerr << e.message() << std::endl;
        }
        else
        {
            std::cout << "Reaaad" << std::endl;
        }

    }
protected :
    boost::asio::io_service& _service;
    ChatParticipant _client;
};

聊天消息

#pragma once
#include <stdlib.h>
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>

using namespace std;
class ChatMessage
{
public :
    enum{header_length = 4};
    static const size_t headerLength = 4; 
    static const size_t maxMsgLength = 512;

    ChatMessage()
    {
        clear();
    }

    void clear()
    {
        for (size_t i = 0; i <= maxLength() ; ++i)
            _allMessage[i] = '\0';
    }

    char* getAllMessage()
    {
        return _allMessage;
    }

    const char* getAllMessage() const
    {
        return _allMessage;
    }

    char* getBody()
    {
        return _allMessage + headerLength;
    }

    size_t getBodyLength()
    {
        return _bodyLength;
    }

    size_t length()
    {
        return headerLength + _bodyLength;
    }

    const size_t length() const
    {
        return headerLength + _bodyLength;
    }

    size_t maxLength()
    {
        return headerLength + maxMsgLength;
    }

    bool setBody(const char* message)
    {
        _bodyLength = strlen(message);
        if (_bodyLength > maxMsgLength)
            return false;
        memcpy(getBody(), message, _bodyLength);
        return true;
    }

    bool setMessage(const char* message)
    {
        clear();
        if (!setBody(message))
            return false;
        encodeHeader();
        return true;
    }
    #pragma warning(disable: 4996) /* Disable deprecation */
    bool decodeHeader()
    {
        char header[headerLength + 1] = "";
        strncat(header, _allMessage, headerLength);
        _bodyLength = atoi(header);
        if (_bodyLength > maxMsgLength)
            return false;
        return true;
    }

    void encodeHeader()
    {
        stringstream ss;
        ss << setw(headerLength) << _bodyLength;
        string s(ss.str());
        memcpy(_allMessage,s.c_str(), headerLength);

    }

private :
    char _allMessage[headerLength + maxMsgLength];
    size_t _bodyLength;
};

主要

#include "ChatMessage.h"


#define IsServer true
#ifdef IsServer
    #include "ChatServer.h"
#else
    #include "ChatCLient.h"
#endif

using boost::asio::ip::tcp;
int main()
{
    boost::asio::io_service service;

    #ifdef IsServer
        tcp::endpoint endpoint(tcp::v4(), 13);
        std::cout << "Server start" << std::endl;
        ChatServer server(service, endpoint);
    #else
        tcp::endpoint endpoint(boost::asio::ip::address_v4::from_string("127.0.0.1"), 13);
        std::cout << "Client start" << std::endl;
        ChatClient client(service, endpoint);
    #endif

    service.run();
    return 0;
}

最佳答案

R6010 错误可能是由未捕获的异常引起的。 shared_from_this() 基于弱指针,其操作取决于作为共享指针目标的对象。

即:

 shared_ptr<ChatClient> client1 (new ChatClient);
 // this client can use shared_from_this()

但是

ChatClient client2;
// this client cannot use shared_from_this().

关于c++ - Boost asio, shared_from_this() error R6010, and async_read() eof,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19732628/

相关文章:

c++ - 关于套接字编程和多线程的面试问题

c++ - 'ClassName' 和 'ClassInstance' 未在此范围内声明

C++,为什么数组的元素会自己改变?

multithreading - 有没有办法监控resilience4j线程池?

c++ - 如何使用 QPainter 缩放文本以适应边界框?

c++ - 在 dll 接口(interface)中使用 shared_ptr

c++ - 使用 boost 生成一组矩形以在不规则多边形中形成网格

python - Tornado 异步 HTTP 递增返回结果

javascript - await 仅在异步函数中有效 - eval 在异步中

python - 带有来自 boost 预处理器的预处理器宏的 SWIG