を呼び出すたびにConnect()
、新しい接続が作成され、TIdTCPServer
その接続を処理するために新しいスレッドが開始されます(つまり、スレッドプールを有効にしない限り)。それはあなたが本当に欲しいものですか?クライアントに一定期間接続を開いたままにして、既存の接続を可能な限り再利用する方が効率的です。しばらくアイドル状態になっている場合など、本当に必要なくなった場合にのみ接続を切断してください。新しい接続を確立することは、両端でコストのかかる操作であるため、そのオーバーヘッドを可能な限り減らす必要があります。
クライアント側では、を呼び出すとWrite(data)
、全体が送信されTIdBytes
ますが、その長さTIdBytes
はサーバーに送信されないため、予想されるバイト数がわかります。 TIdIOHandler.Write(TIdBytes)
あなたのためにそれをしません、あなたはそれを手動でしなければなりません。
サーバー側ではReadBytes()
、一度に4バイトのみを読み取るように指示しています。4バイトの各ブロックの後、OnExecute
イベントハンドラーを終了し、次の4バイトのブロックを読み取るためにイベントハンドラーが再度呼び出されるのを待ちます。クライアントのソースの長さがTIdBytes
4の偶数倍でない限り、 ReadBytes()
4バイト未満のクライアントの最後のブロックを読み取ろうとすると、例外が発生し(サーバーが接続を切断します)、サーバーコードは受信しません。そのブロック。
代わりにこれを試してください:
procedure SendData(var data: TIdBytes) ;
begin
FormMain.IdTCPClient.Connect;
try
FormMain.IdTCPClient.IOHandler.Write(Longint(Length(data)));
FormMain.IdTCPClient.IOHandler.Write(data);
finally
FormMain.IdTCPClient.Disconnect;
end;
end;
procedure TFormMain.IdTCPServerMainExecute(AContext: TIdContext);
var
data: TIdBytes;
begin
with AContext.Connection.IOHandler do
ReadBytes(data, ReadLongint, false);
// process data
end;
そうは言っても、TIdBytes
長さを送信するようにクライアントコードを変更することが何らかの理由でオプションではない場合は、代わりにこのサーバーコードを使用してください。
procedure TFormMain.IdTCPServerMainExecute(AContext: TIdContext);
var
LBytes: Integer;
data: TIdBytes;
begin
// read until disconnected. returns -1 on timeout, 0 on disconnect
repeat until AContext.Connection.IOHandler.ReadFromSource(False, 250, False) = 0;
AContext.Connection.IOHandler.InputBuffer.ExtractToBytes(data);
// process data
end;
または:
procedure TFormMain.IdTCPServerMainExecute(AContext: TIdContext);
var
strm: TMemoryStream;
data: TIdBytes;
begin
strm := TMemoryStream.Create;
try
// read until disconnected
AContext.Connection.IOHandler.ReadStream(strm, -1, True);
strm.Position := 0;
ReadTIdBytesFromStream(strm, data, strm.Size);
finally
strm.Free;
end;
// process data
end;
または:
procedure TFormMain.IdTCPServerMainExecute(AContext: TIdContext);
var
strm: TMemoryStream;
begin
strm := TMemoryStream.Create;
try
// read until disconnected
AContext.Connection.IOHandler.ReadStream(strm, -1, True);
// process strm.Memory up to strm.Size bytes
finally
strm.Free;
end;
end;