尝试将数据发送到另一台计算机。我使用的是C ++ Builder XE6和Indy10。
TMemoryStream *sms = new TMemoryStream();
sms->Write(msgData, msgSize);
Form1->IdTCPClient1->IOHandler->WriteBufferOpen();
Form1->IdTCPClient1->IOHandler->Write(sms, 0, true);
Form1->IdTCPClient1->IOHandler->WriteBufferFlush();
delete sms;
当我检查使用Wireshark发送数据时,我将附加数据和msgData的数据发送到机器。 附加数据是“00 00 00 20”,它处于发送数据的前面。
IdTcpClient通常会发送这样的其他数据吗?
答案 0 :(得分:2)
由于您将AWriteByteCount
Write(TStream)
参数设置为true,因此正在发送额外数据。 00 00 00 20
是网络字节顺序中的流大小。 msgSize
为0x00000020,即32。如果您不希望发送流大小,则需要将AWriteByteCount
参数设置为false:
Form1->IdTCPClient1->IOHandler->Write(sms, 0, false);
此外,您应该使用WriteBufferClose()
而不是WriteBufferFlush()
,如果WriteBufferCancel()
引发异常,请不要忘记致电Write()
。 WriteBufferClose()
将缓冲的数据发送到套接字,然后关闭缓冲区,以便后续写入不被缓冲。 WriteBufferFlush()
将缓冲的数据发送到套接字,但不关闭缓冲区,因此后续写入将被缓冲。
此外,您可以通过将TMemoryStream
替换为TIdMemoryBufferStream
来简化开销,这样您就不必在内存中单独复制邮件数据了:
TIdMemoryBufferStream *sms = new TIdMemoryBufferStream(msgData, msgSize);
try
{
Form1->IdTCPClient1->IOHandler->WriteBufferOpen();
try
{
Form1->IdTCPClient1->IOHandler->Write(sms, 0, true); // or false
Form1->IdTCPClient1->IOHandler->WriteBufferClose();
}
catch (const Exception &)
{
Form1->IdTCPClient1->IOHandler->WriteBufferCancel();
throw;
}
}
__finally
{
delete sms;
}
或者,使用RAII方法:
class BufferIOWriting
{
private:
TIdIOHandler *m_IO;
bool m_Finished;
public:
BufferIOWriting(TIdIOHandler *aIO) : m_IO(aIO), m_Finished(false)
{
IO->WriteBufferOpen();
}
~BufferIOWriting()
{
if (m_Finished)
m_IO->WriteBufferClose();
else
m_IO->WriteBufferCancel();
}
void Finished()
{
m_Finished = true;
}
};
{
std::auto_ptr<TIdMemoryBufferStream> sms(new TIdMemoryBufferStream(msgData, msgSize));
BufferIOWriting buffer(Form1->IdTCPClient1->IOHandler);
Form1->IdTCPClient1->IOHandler->Write(sms.get(), 0, true); // or false
buffer.Finished();
}
话虽如此,我建议完全摆脱写缓冲:
TIdMemoryBufferStream *sms = new TIdMemoryBufferStream(msgData, msgSize);
try
{
Form1->IdTCPClient1->IOHandler->Write(sms, 0, true); // or false
}
__finally
{
delete sms;
}
或者:
{
std::auto_ptr<TIdMemoryBufferStream> sms(new TIdMemoryBufferStream(msgData, msgSize));
Form1->IdTCPClient1->IOHandler->Write(sms.get(), 0, true); // or false
}
当您需要进行多个相关的Write()
调用时,写缓冲非常有用,这些调用应该尽可能少地在TCP帧中传输数据(换句话说,让Nagle算法更好地完成工作)。例如,如果您需要Write()
消息的各个字段。写单缓冲在进行单个Write()
调用时使用起来没什么意义,尤其是这么小的调用。让Write(TStream)
在内部为您处理自己的缓冲。