如何在 C++ Builder 中使用 Indy TCP Client 写入原始二进制数据
How to write raw binary data using Indy TCP Client in C++ Builder
使用 Embarcadero C++ Builder 10.3。
我有一个 DynamicArray<uint8_t> myData
对象。我想 send/write 它的原始二进制内容(字节)到使用 TIdTcpClient
组件的服务器。我打算这样做:
TIdTcpClient tcpClient1;
// Bla Bla Bla
tcpClient1->IOHandler->Write(rawData);
其中 rawData
应为 TIdBytes
或 TIdStream
类型
所以基本上,它归结为以下内容:如何将 myData
对象转换为 TIdBytes
或 TIdStream
的 rawData
类型?
首先,TIdStream
已经很长时间没有成为 Indy 的一部分了,这让我想知道您是否使用的是非常旧的 Indy 版本,而不是 C++ 附带的版本生成器 10.3。 Indy 已经支持 RTL 的标准 TStream
class 很长时间了。
话虽这么说...
TIdBytes
是 System::DynamicArray<System::Byte>
的别名,其中 System::Byte
是 unsigned char
的别名,大小和 sign-ness 与 uint8_t
(取决于编译器,uint8_t
甚至可能只是 unsigned char
的别名)。
因此,最简单的解决方案,无需 单独复制您的数据,就是简单地type-cast 它,例如:
tcpClient1->IOHandler->Write(reinterpret_cast<TIdBytes&>(myData));
这在技术上是 未定义的行为,因为 DynamicArray<uint8_t>
和 DynamicArray<Byte>
是不相关的类型(除非 uint8_t
和 Byte
是unsigned char
) 的两个别名),但它适用于您的情况,因为它是两个数组背后的相同底层代码,并且 uint8_t
和 Byte
具有相同的底层内存布局。
或者,下一个最简单的解决方案,没有复制数据或调用未定义的行为,是在IdGlobal.hpp
中使用Indy的TIdReadOnlyMemoryBufferStream
class ,例如:
TIdReadOnlyMemoryBufferStream *ms = new TIdReadOnlyMemoryBufferStream(&myData[0], myData.Length);
try {
tcpClient1->IOHandler->Write(ms);
}
__finally {
delete ms;
}
或者:
{
auto ms = std::make_unique<TIdReadOnlyMemoryBufferStream>(&myData[0], myData.Length);
tcpClient1->IOHandler->Write(ms.get());
}
否则,最后的解决方案就是直接将数据复制到一个TIdBytes
中,eg:
{
TIdBytes bytes;
bytes.Length = myData.Length;
memcpy(&bytes[0], &myData[0], myData.Length);
or:
std::copy(myData.begin(), myData.end(), bytes.begin());
tcpClient1->IOHandler->Write(bytes);
}
使用 Embarcadero C++ Builder 10.3。
我有一个 DynamicArray<uint8_t> myData
对象。我想 send/write 它的原始二进制内容(字节)到使用 TIdTcpClient
组件的服务器。我打算这样做:
TIdTcpClient tcpClient1;
// Bla Bla Bla
tcpClient1->IOHandler->Write(rawData);
其中 rawData
应为 TIdBytes
或 TIdStream
所以基本上,它归结为以下内容:如何将 myData
对象转换为 TIdBytes
或 TIdStream
的 rawData
类型?
首先,TIdStream
已经很长时间没有成为 Indy 的一部分了,这让我想知道您是否使用的是非常旧的 Indy 版本,而不是 C++ 附带的版本生成器 10.3。 Indy 已经支持 RTL 的标准 TStream
class 很长时间了。
话虽这么说...
TIdBytes
是 System::DynamicArray<System::Byte>
的别名,其中 System::Byte
是 unsigned char
的别名,大小和 sign-ness 与 uint8_t
(取决于编译器,uint8_t
甚至可能只是 unsigned char
的别名)。
因此,最简单的解决方案,无需 单独复制您的数据,就是简单地type-cast 它,例如:
tcpClient1->IOHandler->Write(reinterpret_cast<TIdBytes&>(myData));
这在技术上是 未定义的行为,因为 DynamicArray<uint8_t>
和 DynamicArray<Byte>
是不相关的类型(除非 uint8_t
和 Byte
是unsigned char
) 的两个别名),但它适用于您的情况,因为它是两个数组背后的相同底层代码,并且 uint8_t
和 Byte
具有相同的底层内存布局。
或者,下一个最简单的解决方案,没有复制数据或调用未定义的行为,是在IdGlobal.hpp
中使用Indy的TIdReadOnlyMemoryBufferStream
class ,例如:
TIdReadOnlyMemoryBufferStream *ms = new TIdReadOnlyMemoryBufferStream(&myData[0], myData.Length);
try {
tcpClient1->IOHandler->Write(ms);
}
__finally {
delete ms;
}
或者:
{
auto ms = std::make_unique<TIdReadOnlyMemoryBufferStream>(&myData[0], myData.Length);
tcpClient1->IOHandler->Write(ms.get());
}
否则,最后的解决方案就是直接将数据复制到一个TIdBytes
中,eg:
{
TIdBytes bytes;
bytes.Length = myData.Length;
memcpy(&bytes[0], &myData[0], myData.Length);
or:
std::copy(myData.begin(), myData.end(), bytes.begin());
tcpClient1->IOHandler->Write(bytes);
}