提升asio,shared_from_this()错误R6010和async_read()eof

时间:2013-11-01 18:05:02

标签: 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;
};

ChatMessage

#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;
}

2 个答案:

答案 0 :(得分:1)

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().

答案 1 :(得分:0)

变化

ChatParticipant _client;

boost::shared_ptr<ChatParticipant> _client;

并初始化ctor初始化列表中的_client指针。这样您就可以调用shared_from_this()获取shared_ptr_client