Indy10,IdTCPClient的IOHandler发送附加数据

时间:2014-08-22 01:25:14

标签: indy10

尝试将数据发送到另一台计算机。我使用的是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通常会发送这样的其他数据吗?

1 个答案:

答案 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)在内部为您处理自己的缓冲。