C++ 服务器,System.10014 错误,使用 Boost

标签 c++ networking boost boost-asio

更新:我明白了!有点...我不确定这是如何解决的,但确实如此。而不是使用:

NetworkMessage msg;
msg.AddByte(0x01);
sendmessage(msg);

我试过了并且成功了(对某些功能进行了一些改动)

NetworkMessage* msg = new NetworkMessage();
msg.AddByte(0x01);
sendmessage(msg);

这修复了它,但仍然希望任何人都能解释为什么会发生这种情况。将其发布为答案,以便我对其进行标记。谢谢。

我一直在 TCP 服务器上工作,但遇到了一些小问题..

有一个发送大约 600 的循环?消息,一次发送 1 条(从排队的消息列表中读取)。

出于某种原因,大约有 200 个没有错误地到达我的客户端,然后我收到一个 System.10014 错误。每次都在不同的消息上,即使消息每次都相同。另外,如果我只是在 System.10014 错误后重新发送消息,它就可以正常工作。所以很明显消息不是问题所在。但我不知道是什么。我昨天花了一整天试图弄清楚,但仍然没有运气。所以我在这里。再次。

void outputMessage(NetworkMessage& msg, bool forceTrue = false)
{
    if(!connectionLocked || forceTrue) {
        connectionLocked = true;

        std::cout << "Message: ";
        char* buf = msg.getOutputBuffer();
        for (int i = 0; i < msg.size(); i++){
            std::cout << (buf[i] + 0) << ":"; //Never any errors
        }

        boost::asio::async_write(socket_, boost::asio::buffer(msg.getOutputBuffer(), msg.size()),boost::bind(&Session::handle_write, shared_from_this(), msg, boost::asio::placeholders::error));

    }
    else {
        //Queue message
        _msgqueue.push_back(msg);
    }

}
void handle_write(NetworkMessage& msg, const boost::system::error_code& error)
{
    if (error)
    {
        cout << "Error: " << error << endl;
        outputMessage(msg, true); //works, even though it's the same message
    }
    else {
        if(_msgqueue.size() != 0){
            //cout << "Sending queued message #" << _msgqueue.size() << endl;
            outputMessage(_msgqueue.front(), true);
            _msgqueue.pop_front();
        }
        else
            connectionLocked = false;
    }
}

这基本上是我的发送功能的代码。它工作正常,通常。出于某种原因,当我连续发送大量消息时,会发生此错误 (System.10014)。我尝试阅读有关 Winsock 中的错误的信息,但我真的不明白它(它说了一些关于无效指针的内容,但我很确定该消息是有效的,因为再次发送它就可以了?)。而且我在编程方面经验很少,尤其是在 C++ 和指针方面,所以我遇到了一些麻烦。

生成消息的循环有点像这样。我验证了 X 和 Y 是有效的,所以我很确定问题不存在。

map->cursor = map->begin;
while(map->cursor != NULL)
{
    //I'm not sure if pointers like this are supposed to be deleted?
    //I suck when it comes to memory management, and most other things :D
    Tile* tile = map->cursor->tile;
    if(tile){
        NetworkMessage msg;
        msg.AddByte(0x03);
        msg.AddByte(tile->posx);
        msg.AddByte(tile->posy);
        msg.AddByte(1);
        msg.AddByte(2);
        outputMessage(msg);
    }
    else
        break;
    map->cursor = map->cursor->next;

}

此外,这可能看起来不相关,但如果我尝试将我的 outputMessage 更改为:

void outputMessage(NetworkMessage& msg)
{
    boost::asio::async_write(socket_, boost::asio::buffer(msg.getOutputBuffer(), msg.size()),boost::bind(&Session::handle_write, shared_from_this(), msg, boost::asio::placeholders::error));
}
void handle_write(NetworkMessage& msg, const boost::system::error_code& error)
{
    if (error)
    {
        cout << "Error: " << error << endl;
    }
}

我没有收到任何错误,但发送的消息都是克隆的。所以这 600 条消息看起来都一样。这看起来很奇怪,所以我认为这可能与我现在遇到的问题有关。

还有 NetworkMessage.h,我也把它贴在了 pastebin 上,你可以在评论中看到。

#ifndef _NETWORK_MESSAGE_H
#define _NETWORK_MESSAGE_H
class NetworkMessage
{
    public:
        enum { header_length = 2 };
        enum { max_body_length = NETWORKMESSAGE_MAXSIZE - header_length};
        NetworkMessage()
        {
            buf_size=0;
            m_ReadPos=header_length;
        }
        void AddByte(char byte_)
        {
            if (!canAdd(1)) return;
            data_[m_ReadPos++] = byte_;
            //data_[m_ReadPos] = '\0';
            buf_size++;
        }
        uint16_t PeekU16(){
            return (data_[1] | uint16_t(data_[0]) << 8);
        }
        uint16_t GetU16(){
            m_ReadPos += 2;
            return (data_[m_ReadPos+1]) | (uint16_t(data_[m_ReadPos]) << 8);
        }

        uint8_t  GetByte(){return data_[m_ReadPos++];}
        char* getBuffer()
        {
            return (char*)&data_[m_ReadPos];
        }
        char* getOutputBuffer()
        {
            writeMessageLength();
            return (char*)&data_[0];
        }

        void setMessageLength(uint16_t v)
        {
            buf_size=v;
        }
        void writeMessageLength()
        {
            *(uint8_t*)(data_) = (buf_size >> 8);
            *(uint8_t*)(data_+1) = buf_size;
        }
        void reset()
        {
            m_ReadPos = 0;
            buf_size = 0;
        }
        uint16_t size(){return buf_size+header_length;}
    protected:
        inline bool canAdd(uint32_t size)
        {
            return (size + m_ReadPos < max_body_length);
        };
    private:
        uint8_t data_[NETWORKMESSAGE_MAXSIZE];
        uint16_t buf_size;
        uint16_t m_ReadPos;
};
#endif //_NETWORK_MESSAGE_H

更新:好吧,遇到了一些奇怪的事情......

function error_func(NetworkMessage& msg){
    cout << &msg << endl; //0x2882e8(not 0x274c0e8)
    send(msg.getOutputBuffer(), msg.size(), error_func, msg); //no error
}
cout << &msg << endl; //0x274c0e8
send(msg.getOutputBuffer(), msg.size(), error_func, msg); //error system.10014

显然这不是真正的代码,但你明白了......我想这就是为什么从 error_func 重新发送它的原因。毕竟问题可能出在 NetworkMessage 中。我一直在搞错所有的地方 :D 不过仍然需要帮助,哈哈。

非常感谢任何帮助,我被卡住了。如果你走到这一步,感谢阅读..

最佳答案

void outputMessage(NetworkMessage& msg, bool forceTrue = false)
{
    if(!connectionLocked || forceTrue) {
        connectionLocked = true;

        std::cout << "Message: ";
        char* buf = msg.getOutputBuffer();
        for (int i = 0; i < msg.size(); i++){
            std::cout << (buf[i] + 0) << ":"; //Never any errors
        }

        boost::asio::async_write(socket_, boost::asio::buffer(msg.getOutputBuffer(), msg.size()),boost::bind(&Session::handle_write, shared_from_this(), msg, boost::asio::placeholders::error));

    }
    else {
        //Queue message
        _msgqueue.push_back(msg);
    }
}

传递给 async_write 的缓冲区需要在整个操作期间有效。文档是 very explicit here

One or more buffers containing the data to be written. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called.

您传递的指针在 NetworkMessage 对象被销毁时不再有效,我猜这是在 async_write 操作完成之前。 NetworkMessage 对象在传递给您的 handle_write() 完成处理程序时被复制。

关于C++ 服务器,System.10014 错误,使用 Boost,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10140813/

相关文章:

linux:禁用环回并通过电线在一个 comp 的 2 个 eth 卡之间发送数据

java - 注册。 Linux 中的防火墙

c++ - 返回对 boost::any 持有的数据的引用

C++ 模板化工厂构造函数/反序列化

c++ - 是否有计算在单色背景上绘制的 Sprite 边界矩形的算法?

c++ - 异步事件循环设计和问题

使用 GNU gettext、libunistring 的 C++ l10n、i18n 解决方案

c++ - 如何在 OpenCV 中访问多维 Mat 中的二维矩阵

c++ - 为客户端/服务器程序编写单元测试

c++ - boost/property_tree/xml_parser.hpp : No such file or directory