1

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

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 不过仍然需要帮助,大声笑。

真的很感激任何帮助,我被困住了。感谢阅读,如果你已经走到这一步了..

4

1 回答 1

3
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需要在整个操作期间有效。文档在这里非常明确

包含要写入的数据的一个或多个缓冲区。尽管缓冲区对象可以根据需要被复制,但底层内存块的所有权由调用者保留,它必须保证它们在调用处理程序之前保持有效

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

于 2012-04-13T21:46:36.903 回答