【问题标题】:How to copy Buffer bytes block in Poco C++?如何在 Poco C++ 中复制缓冲区字节块?
【发布时间】:2016-03-15 09:44:46
【问题描述】:

您好,我正在尝试在 poco 中编写 TCP 连接。客户端发送带有此字段的数据包:

packetSize : int date : int ID : int

所以前 4 个字节包含数据包大小。在接收端我有这个代码:

int packetSize = 0;
char *bufferHeader = new char[4];

// receive 4 bytes that contains packetsize here
socket().receiveBytes(bufferHeader, sizeof(bufferHeader), MSG_WAITALL);

Poco::MemoryInputStream *inStreamHeader = new Poco::MemoryInputStream(bufferHeader, sizeof(bufferHeader));
Poco::BinaryReader *BinaryReaderHeader = new Poco::BinaryReader(*inStreamHeader);

(*BinaryReaderHeader) >> packetSize; // now we have the full packet size

现在我正在尝试将所有剩余的传入字节存储到一个数组中以供将来二进制读取:

int ID = 0;
int date = 0;
int availableBytes = 0;
int readedBytes = 0;
char *body = new char[packetSize - 4];

do
{
    char *bytes = new char[packetSize - 4];

    availableBytes = socket().receiveBytes(bytes, sizeof(bytes), MSG_WAITALL);

    if (availableBytes == 0)
        break;

    memcpy(body + readedBytes, bytes, availableBytes);

    readedBytes += availableBytes;

} while (availableBytes > 0);

Poco::MemoryInputStream *inStream = new Poco::MemoryInputStream(body, sizeof(body));
Poco::BinaryReader *BinaryReader = new Poco::BinaryReader(*inStream);

(*BinaryReader) >> date;
(*BinaryReader) >> ID;

cout << "date :" << date << endl;
cout << "ID :" << ID << endl;

问题是 body 的字节块没有存储剩余的字节,它总是只有前 4 个字节(日期)。所以在输出中日期是正确的,但 ID 与预期不符。我尝试在没有块复制的情况下对其进行流式传输,并在没有循环的情况下手动接收每个字段,这很好并且有预期的数据。但是当我尝试将传入的字节存储到一个数组中,然后将该数组传递给内存流来读取它时,我只有第一个块是正确的和预期的!!

我真的需要将所有传入的字节存储到一个数组中,然后读取整个数组,我应该如何更改我的代码?

非常感谢

【问题讨论】:

    标签: c++ sockets poco-libraries


    【解决方案1】:

    我在您的代码中看到两个错误。或者,更准确地说,你犯了两次错误。 您将char[]sizeofchar *sizeof 混淆了;第一个是数组中的字符数,第二个是指针的大小:通常为 4 或 8 个字节,具体取决于内存模型。

    所以,当你写作时

    availableBytes = socket().receiveBytes(bytes, sizeof(bytes), MSG_WAITALL);
    

    您要求 4 个(我想是)字节。这并不严重,因为您会继续询问其他字节,直到消息完成。

    真正的问题是下面的指令

    Poco::MemoryInputStream *inStream = new Poco::MemoryInputStream(body, sizeof(body));
    

    您只在inStream 中传输sizeof(char *) 字节

    您应该将sizeof(body)sizeof(bytes) 替换为packetSize - 4

    P.s.:对不起我的英语不好

    编辑:我看到了另一个错误。在本说明中

     char *bytes = new char[packetSize - 4];
    

    您分配 packetSize - 4 字符。此内存从未被删除并在do ... while() 循环中分配。

    您可以在循环之外分配bytes(与body 一起)。

    编辑 2016.03.17

    建议的解决方案(注意:未经测试)

    size_t  toRead  = packetSize - 4U;
    size_t  totRead = 0U;
    size_t  nowRead;
    
    char * body = new char[toRead];
    
    do 
    {
      nowRead += socket().receiveBytes(body+totRead, toRead-totRead,
                    MSG_WAITALL);
    
      if ( 0 == nowRead )
         throw std::runtime_error("shutdown from receiveBytes()");
    
      totRead += nowRead;
    
    } while ( totRead < toRead );
    
    Poco::MemoryInputStream *inStream = new Poco::MemoryInputStream(body, 
                                               toRead);
    
    delete[] body;
    
    body = NULL;
    

    【讨论】:

    • 感谢您的回复。是的,我对此感到困惑,毕竟当我将 char * 更改为 char [ ] 时,我在那里得到了完整的数据包。但实际上,当我试图为我的缓冲区考虑 packetSize 时,我无法调整 Char [ ] 的大小,实际上 c++ 不接受它的数组大小,它需要常量值,但它接受它为:char * buffer = new char[packetSize] 当我考虑 char * ,我每次只得到 4 个字节,而不是完整的数据包。我该如何解决这个问题?
    • @AmirHasanHesam:我认为你应该避免使用sizeof();你有预期的字节数:使用它。而且您只能使用一个缓冲区。我将编辑我的答案以显示可能的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2012-07-17
    • 2014-09-11
    • 2010-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多