如何在 Poco C++ 中复制缓冲区字节块?
How to copy Buffer bytes block in Poco C++?
您好,我正在尝试在 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 不是预期的。我尝试在没有块复制的情况下对其进行流式传输,并在没有循环的情况下手动接收每个字段,这很好并且有预期的数据。但是当我尝试将传入的字节存储到一个数组中,然后将该数组传递给内存流以读取它时,我只有第一个块正确且符合预期!!
我真的需要将所有传入的字节存储到一个数组中,然后读取整个数组,我应该如何更改我的代码?
非常感谢
我发现您的代码中有两个错误。或者,更准确地说,一个错误你犯了两次。
您将 char[]
的 sizeof
与 char *
的 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;
您好,我正在尝试在 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 不是预期的。我尝试在没有块复制的情况下对其进行流式传输,并在没有循环的情况下手动接收每个字段,这很好并且有预期的数据。但是当我尝试将传入的字节存储到一个数组中,然后将该数组传递给内存流以读取它时,我只有第一个块正确且符合预期!!
我真的需要将所有传入的字节存储到一个数组中,然后读取整个数组,我应该如何更改我的代码?
非常感谢
我发现您的代码中有两个错误。或者,更准确地说,一个错误你犯了两次。
您将 char[]
的 sizeof
与 char *
的 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;