7

IndyTCPサーバー/クライアントを介してレコードを転送する方法を理解するのに助けが必要です。私は2つのプログラムを持っています。クライアントと別のサーバーを配置します。クライアントのボタンに接続します:クライアントはTIdTCPClientです

Client.Connect();

そしてサーバー側では、ServerConnectイベントで、クライアントが接続されていることをメモする行を追加しています

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

クライアントからデータを送信するために、送信したいレコードがあります。

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

そして、私はそこに送信ボタンを持っています:

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;

サーバー側のonexecuteには、次のコードがあります。サーバー側でも同じ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要素を読み取りたい。クライアント側から送信ボタンを押すと、アプリケーションがハングし、サーバー部分がハングします。

よろしくお願いします

4

1 に答える 1

11

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

のデフォルトのパラメータ値は、データの長さを指定するストリーム データの前にorが続くTIdIOHandler.ReadStream()ことを期待するように指示します(プロパティの値に応じて)。IntegerInt64TIdIOHandler.LargeStream

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

TMemoryStreamIndy 以外のオブジェクトを使用するコードには、その他のマイナーなバグやタイプミスもあります。

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

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; 
于 2012-06-05T00:30:56.490 に答える