単純なリクエストとレスポンスが完了するまでに 400 ミリ秒かかる理由がわかりません。ローカルホスト (ループバック) で完了するのに 1 ミリ秒未満しか必要ありません。仮想マシンからメインの開発マシンにリクエストを送信すると、完了するまでに 400 ミリ秒かかります。最大 40 ミリ秒かかります。これは、HTTP リクエストに最大でかかる量なので、TCP の方が高速なはずです。クライアントとサーバーのコードは次のとおりです。どこで時間を失っているのかわかりません。さらに情報が必要な場合は、プロフィールを作成できます。
コードは Indy 9 および 10 と互換性があるため、IFDEF-s が使用されます。また、接続はすでに確立されており、接続部分がなく、データの送信と応答のみで 400 ミリ秒かかります。
function TIMCClient.ExecuteConnectedRequest(const Request: IMessageData): IMessageData;
var
DataLength: Int64;
FullDataSize: Int64;
IDAsBytes: TIdBytes;
IDAsString: ustring;
begin
Result := AcquireIMCData;
FAnswerValid := False;
with FTCPClient{$IFNDEF Indy9}.IOHandler{$ENDIF} do
begin
Request.Data.Storage.Seek(0, soFromBeginning);
DataLength := Length(Request.ID) * SizeOf(uchar);
FullDataSize := DataLength + Request.Data.Storage.Size + 2 * SizeOf(Int64);
SetLength(IDAsBytes, DataLength);
Move(Request.ID[1], IDAsBytes[0], DataLength);
// write data
{$IFDEF Indy9}WriteInteger{$ELSE}Write{$ENDIF}(FullDataSize);
{$IFDEF Indy9}WriteInteger{$ELSE}Write{$ENDIF}(DataLength);
{$IFDEF Indy9}WriteBuffer{$ELSE}Write{$ENDIF}(IDAsBytes{$IFDEF Indy9}[0]{$ENDIF}, DataLength);
{$IFDEF Indy9}WriteInteger{$ELSE}Write{$ENDIF}(Request.Data.Storage.Size);
{$IFDEF Indy9}WriteStream{$ELSE}Write{$ENDIF}(Request.Data.Storage);
// set the read timeout
ReadTimeout := FExecuteTimeout;
FullDataSize := ReadInt(FTCPClient);
// read the message ID
SetLength(IDAsBytes, 0);
DataLength := ReadInt(FTCPClient);
ReadBuff(FTCPClient, DataLength, IDAsBytes);
if DataLength > 0 then
begin
SetLength(IDAsString, DataLength div SizeOf(uchar));
Move(IDAsBytes[0], IDAsString[1], DataLength);
Result.ID := IDAsString;
end;
// read the message data
DataLength := ReadInt(FTCPClient);
ReadStream(Result.Data.Storage, DataLength, False);
Result.Data.Storage.Seek(0, soFromBeginning);
// we were succesfull
FAnswerValid := True;
end;
end;
サーバー側:
procedure TIMCServer.OnServerExecute(AContext: TIMCContext);
var
Request: IMessageData;
Response: IMessageData;
DataLength: Int64;
FullDataSize: Int64;
IDAsBytes: TIdBytes;
IDAsString: ustring;
begin
with AContext.Connection{$IFNDEF Indy9}.IOHandler{$ENDIF} do
begin
ReadTimeout := FExecuteTimeout;
//read the data length of the comming response
FullDataSize := ReadInt(AContext.Connection);
// Acquire the data objects
Request := AcquireIMCData;
Response := AcquireIMCData;
// read the message ID
DataLength := ReadInt(AContext.Connection);
ReadBuff(AContext.Connection, DataLength, IDAsBytes);
if DataLength > 0 then
begin
SetLength(IDAsString, DataLength div SizeOf(uchar));
Move(IDAsBytes[0], IDAsString[1], DataLength);
Request.ID := IDAsString;
end;
// read the message data
DataLength := ReadInt(AContext.Connection);
ReadStream(Request.Data.Storage, DataLength, False);
Request.Data.Storage.Seek(0, soFromBeginning);
try
// execute the actual request handler
FOnExecuteRequest(Request, Response);
finally
// write the data stream to TCP
Response.Data.Storage.Seek(0, soFromBeginning);
DataLength := Length(Response.ID) * SizeOf(uchar);
FullDataSize := DataLength + Response.Data.Storage.Size + 2 * SizeOf(Int64);
// write ID as binary data
SetLength(IDAsBytes, DataLength);
Move(Response.ID[1], IDAsBytes[0], DataLength);
// write data
{$IFDEF Indy9}WriteInteger{$ELSE}Write{$ENDIF}(FullDataSize);
{$IFDEF Indy9}WriteInteger{$ELSE}Write{$ENDIF}(DataLength);
{$IFDEF Indy9}WriteBuffer{$ELSE}Write{$ENDIF}(IDAsBytes{$IFDEF Indy9}[0]{$ENDIF}, DataLength);
{$IFDEF Indy9}WriteInteger{$ELSE}Write{$ENDIF}(Response.Data.Storage.Size);
{$IFDEF Indy9}WriteStream{$ELSE}Write{$ENDIF}(Response.Data.Storage);
end;
end;
同じ遅い通信が私のコードのユーザーの 1 人から報告されました。また、仮想マシンから物理マシンへのテストも行いました。
アップデート:
次のコードは、同じ 2 台のマシン間で 2 ~ 3 ミリ秒で実行されます。そのIndy10、可能な限り最小のケース。
procedure TForm2.Button1Click(Sender: TObject);
var
MyVar: Int64;
begin
TCPClient.Host := Edit1.Text;
TCPClient.Port := StrToInt(Edit2.Text);
TCPClient.Connect;
try
stopwatch := TStopWatch.StartNew;
MyVar := 10;
TCPClient.IOHandler.Write(MyVar);
TCPClient.IOHandler.ReadInt64;
stopwatch.Stop;
Caption := IntToStr(stopwatch.ElapsedMilliseconds) + ' ms';
finally
TCPClient.Disconnect;
end;
end;
procedure TForm2.TCPServerExecute(AContext: TIdContext);
var
MyVar: Int64;
begin
if AContext.Connection.IOHandler.InputBuffer.Size > 0 then
begin
MyVar := 10;
AContext.Connection.IOHandler.ReadInt64;
AContext.Connection.IOHandler.Write(MyVar);
end;
終わり;