【问题标题】:Reading stream of Data using TIdIOHandlerStream and TIdTCPClient使用 TIdIOHandlerStream 和 TIdTCPClient 读取数据流
【发布时间】:2018-11-30 12:45:38
【问题描述】:

我有一个应用程序需要使用 TCP/IP 连接到服务器,然后等待服务器发送数据,服务器发送的任何内容都应保存到文件中。

这是我所做的:

头文件

#ifndef MainH
#define MainH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <FMX.Controls.hpp>
#include <FMX.Forms.hpp>
#include <FMX.Controls.Presentation.hpp>
#include <FMX.StdCtrls.hpp>
#include <FMX.Types.hpp>
#include <IdBaseComponent.hpp>
#include <IdComponent.hpp>
#include <IdIOHandler.hpp>
#include <IdIOHandlerStream.hpp>
#include <IdTCPClient.hpp>
#include <IdTCPConnection.hpp>
#include <boost/scoped_ptr.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE-managed Components
    TIdTCPClient *pTCP;
    TIdIOHandlerStream *IdIOHandlerStream;
    TButton *Button1;
    void __fastcall Button1Click(TObject *Sender);
    void __fastcall IdIOHandlerStreamGetStreams(TIdIOHandlerStream *ASender, TStream *&VReceiveStream, TStream *&VSendStream);
private:    // User declarations
    boost::scoped_ptr<TFileStream> mFile;
    boost::scoped_ptr<TMemoryStream> mMem;

    void __fastcall StopTcpClick(TObject* Sender);
public:     // User declarations
    __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

和 CPP 文件:

include <fmx.h>
#pragma hdrstop

#include "Main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.fmx"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner),
                            mFile(new TFileStream(L"C:\\IbsData.txt", fmCreate | fmOpenReadWrite | fmShareDenyWrite)),
                            mMem(new TMemoryStream())
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    pTCP->Connect();
    Button1->Text = L"Stop";
    Button1->OnClick = StopTcpClick;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::StopTcpClick(TObject* Sender)
{
    pTCP->Disconnect();
    Button1->Text = L"Start";
    Button1->OnClick = Button1Click;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::IdIOHandlerStreamGetStreams(TIdIOHandlerStream *ASender, TStream *&VReceiveStream, TStream *&VSendStream)
{
    VReceiveStream = mFile.get();
    VSendStream = mMem.get();
}

我必须注意IdIOHandlerStream 已设置为pTCPIOHandler

问题是,我知道服务器正在发送大量数据,但没有写入文件。

有人知道为什么吗?

【问题讨论】:

  • 在进行了更多挖掘之后,我也意识到netstat 没有显示任何活动连接。但如果我断开IdIOHandlerStreamTIdTCPClient 的连接,则连接会显示在netstat 中。

标签: delphi c++builder indy10 c++builder-10.2-tokyo c++builder-tokyo


【解决方案1】:

您使用了错误的 IOHandler 类。

TIdIOHandlerStream 使用 TStream 对象执行 I/O。它通常用于重放先前捕获的会话以进行调试,而无需与真实服务器建立物理连接。

您需要改用TIdIOHandlerStack,它使用 TCP/IP 套接字连接执行 I/O。它是 Indy 的默认 IOHandler 类,因此您甚至不需要创建它的实例1,如果您不分配自己的,TIdTCPClient::Connect() 会在内部为您创建一个。

1:除非您需要更高级的用法,例如通过代理连接到服务器等,否则您需要自己的实例,以便根据需要进行配置。

对于您正在尝试的内容,让TIdTCPClient 使用TIdIOHandlerStack,然后您可以在连接到服务器后调用TIdIOHandler::ReadStream() 方法。传入一个TFileStream 让它读入,并将它的AByteCount 参数设置为-1,将AReadUntilDisconnect 参数设置为True,这样它将持续读取直到套接字连接关闭。

此外,与 Indy 中的大多数操作一样,ReadStream() 会阻塞调用线程直到完成,因此为避免阻塞您的 UI,您应该在工作线程中调用 ReadStream()。但是,如果您不想使用线程,您也可以在 Form 上放置一个 TIdAntiFreeze 组件。

【讨论】:

    猜你喜欢
    • 2013-06-26
    • 1970-01-01
    • 2017-10-27
    • 1970-01-01
    • 1970-01-01
    • 2020-10-20
    • 1970-01-01
    • 2012-03-15
    • 2015-06-16
    相关资源
    最近更新 更多