2012-06-03 7 views
6

Indy TCP Server/Clientを介してレコードを転送する方法を理解する上で助けが必要です。私はクライアントと別のサーバに2つのプログラムを持っています。私は接続入れるボタン上のクライアントで :クライアントはTIdTCPClientDelphi TidTCPServerとTidTCPClientレコードを転送する

Client.Connect(); 

であり、サーバー側で私はからのデータを送信するにはServerConnectイベント

Protocol.Lines.Add(TimeToStr(Time)+' connected '); 

に、クライアントが接続されていることをメモに行を追加していますクライアント私が送信したいレコードを、持っている:

Tmyrecord = record 
IPStr: string[15]; 
end; 

をそして私はそこに送信ボタンがあります。

01私は、次のコードを持っているONEXECUTE
procedure Tform1.ButtonSendClick(Sender: TObject); 
    var 
    MIRec: Tmyrecord; 
msRecInfo: TMemoryStream; 
begin 
    MIRec.IPStr := '172.0.0.1'; 
    msRecInfo := TMemoryStream.Create; 
    msRecInfo.Write(MIRec, SizeOf(MIRec)); 
    msRecInfo.Position := 0; 
    Client.IOHandler.Write(msRecInfo); 
end; 

は、サーバー側では、私はあまりにもサーバ側で同じtmyrecordを宣言している:

procedure TServerFrmMain.ServerExecute(AContext: TIdContext); 
var 
    MIRec: Tmyrecord; 
    msRecInfo: TMemoryStream; 
begin 
if AContext.Connection.Connected then 
    begin 
    AContext.Connection.IOHandler.CheckForDataOnSource(10); 
    if not AContext.Connection.IOHandler.InputBufferIsEmpty then 
    begin 
    msRecInfo:= TMemoryStream.Create; 
     AContext.Connection.IOHandler.ReadStream(msRecInfo); 
    msRecInfo.Read(MIRec, sizeOf(msRecInfo)); 
    ShowMessage(MIRec.IPStr); 
end; 
end; 
end 

私はそれが動作していない理由を、なぜ私は私が書いたのIPアドレスを表示しカント知りませんクライアント側から クライアント側から送信しているサーバー側のレコード(msRecInfo)を読みたい。私は自分のレコード要素にアクセスしたい、この場合は私のレコードのIPSTR要素を読みたい。クライアント側から送信ボタンを押すと、アプリケーションがハングします。

事前にどうもありがとう

+0

レコード、msRecInfoは、どの要素にIPSTR要素があるかを示します。私はそのレコードを送って、それをサーバーから読みたいと思います。私はサーバ側の私の記録からIPSTRを読んでほしい –

+0

あなたの質問をきれいにしてこれがあなたの1つの質問であることを明確にするためのちょっとした提案。 –

+0

提案のおかげで、私の質問が編集されました。今はもっと良いと思っています。 –

答えて

10

あなたは、古典的な初心者の間違いを作っている - あなたはTIdIOHandler.Write(TStream)TIdIOHandler.ReadStream()メソッドのデフォルトの動作が一致することを期待されているが、彼らは実際にはしません。 TIdIOHandler.ReadStream()

デフォルトのパラメータ値は、データの長さを指定するストリームデータをpreceedする(TIdIOHandler.LargeStreamプロパティの値に応じて)Integer又はInt64を期待することを伝えます。

ただし、デフォルトのパラメータ値TIdIOHandler.Write(TStream)は、そのようなInteger/Int64値を送信するようには指定しません。したがって、TIdIOHandler.ReadStream()を使用すると、レコードの最初の数バイトが読み取られ、Integer/Int64(送信している文字列の値が与えられている926036233)と解釈され、その多くのバイトが到着するまで待っています。TIdIOHandler.ReadStream()終了します(TIdIOHandler.ReadTimeoutプロパティを無限値に設定しない限り)。

インディーズ以外のTMemoryStreamオブジェクトを使用するコードには、マイナーなバグや誤字がいくつかあります。

代わりにこれを試してみてください:

procedure Tform1.ButtonSendClick(Sender: TObject); 
var 
    MIRec: Tmyrecord; 
    msRecInfo: TMemoryStream; 
begin 
    MIRec.IPStr := '172.0.0.1'; 
    msRecInfo := TMemoryStream.Create; 
    try 
    msRecInfo.Write(MIRec, SizeOf(MIRec)); 

    // writes the stream size then writes the stream data 
    Client.IOHandler.Write(msRecInfo, 0, True); 
    finally 
    msRecInfo.Free; 
    end; 
end; 

procedure TServerFrmMain.ServerExecute(AContext: TIdContext); 
var 
    MIRec: Tmyrecord; 
    msRecInfo: TMemoryStream; 
begin 
    msRecInfo := TMemoryStream.Create; 
    try 
    // reads the stream size then reads the stream data 
    AContext.Connection.IOHandler.ReadStream(msRecInfo, -1, False); 

    msRecInfo.Position := 0; 
    msRecInfo.Read(MIRec, SizeOf(MIRec)); 
    ... 
    finally 
    msRecInfo.Free; 
    end; 
end; 

またはこの:また

procedure Tform1.ButtonSendClick(Sender: TObject); 
var 
    MIRec: Tmyrecord; 
    msRecInfo: TMemoryStream; 
begin 
    MIRec.IPStr := '172.0.0.1'; 
    msRecInfo := TMemoryStream.Create; 
    try 
    msRecInfo.Write(MIRec, SizeOf(MIRec)); 

    // does not write the stream size, just the stream data 
    Client.IOHandler.Write(msRecInfo, 0, False); 
    finally 
    msRecInfo.Free; 
    end; 
end; 

procedure TServerFrmMain.ServerExecute(AContext: TIdContext); 
var 
    MIRec: Tmyrecord; 
    msRecInfo: TMemoryStream; 
begin 
    msRecInfo := TMemoryStream.Create; 
    try 
    // does not read the stream size, just the stream data 
    AContext.Connection.IOHandler.ReadStream(msRecInfo, SizeOf(MIRec), False); 

    msRecInfo.Position := 0; 
    msRecInfo.Read(MIRec, SizeOf(MIRec)); 
    ... 
    finally 
    msRecInfo.Free; 
    end; 
end; 

を、あなたはTIdBytes代わりTStreamの使用してレコードを送信することができます:私は、送信しようとしています

procedure Tform1.ButtonSendClick(Sender: TObject); 
var 
    MIRec: Tmyrecord; 
    Buffer: TIdBytes; 
begin 
    MIRec.IPStr := '172.0.0.1'; 
    Buffer := RawToBytes(MIRec, SizeOf(MIRec)); 
    Client.IOHandler.Write(Buffer); 
end; 

procedure TServerFrmMain.ServerExecute(AContext: TIdContext); 
var 
    MIRec: Tmyrecord; 
    Buffer: TIdBytes; 
begin 
    AContext.Connection.IOHandler.ReadBytes(Buffer, SizeOf(MIRec)); 
    BytesToRaw(Buffer, MIRec, SizeOf(MIRec)); 
    ... 
end; 
+0

最後のものを試します。 –

関連する問題