再起動/シャットダウンの目的で、2 つ以上の異なるマシンで実行される小さなクライアント サーバー アプリケーションを作成しました。私はクライアント サーバー アプリに比較的慣れていないので、ここで Delphi についてのアプローチを採用しました。簡単に言うと、サーバー アプリはポート 7676 で接続を待機し、クライアントをクライアント リストに追加してから何もしません (後でシャットダウンと再起動の手順を実装します)。ただし、パッシブであっても、クライアントが 2 つしか接続されていない場合、CPU の最大 90% を消費します。TidTCPServer と TidAntiFreeze で構成されるクライアント コードは次のとおりです。
type
PClient = ^TClient;
TClient = record
PeerIP : string[15]; { Client IP address }
HostName : String[40]; { Hostname }
Connected, { Time of connect }
LastAction : TDateTime; { Time of last transaction }
AContext : Pointer; { Pointer to thread }
end;
[...]
procedure TForm1.StartServerExecute(Sender: TObject);
var
Bindings: TIdSocketHandles;
begin
//setup and start TCPServer
Bindings := TIdSocketHandles.Create(TCPServer);
try
with Bindings.Add do
begin
IP := DefaultServerIP;
Port := DefaultServerPort;
end;
try
TCPServer.Bindings:=Bindings;
TCPServer.Active:=True;
except on E:Exception do
ShowMessage(E.Message);
end;
finally
Bindings.Free;
end;
//setup TCPServer
//other startup settings
Clients := TThreadList.Create;
Clients.Duplicates := dupAccept;
RefreshListDisplay;
if TCPServer.Active then
begin
Protocol.Items.Add(TimeToStr(Time)+' Shutdown server running on ' + TCPServer.Bindings[0].IP + ':' + IntToStr(TCPServer.Bindings[0].Port));
end;
end;
procedure TForm1.TCPServerConnect(AContext: TIdContext);
var
NewClient: PClient;
begin
GetMem(NewClient, SizeOf(TClient));
NewClient.PeerIP := AContext.Connection.Socket.Binding.PeerIP;
NewClient.HostName := GStack.HostByAddress(NewClient.PeerIP);
NewClient.Connected := Now;
NewClient.LastAction := NewClient.Connected;
NewClient.AContext := AContext;
AContext.Data := TObject(NewClient);
try
Clients.LockList.Add(NewClient);
finally
Clients.UnlockList;
end;
Protocol.Items.Add(TimeToStr(Time)+' Connection from "' + NewClient.HostName + '" from ' + NewClient.PeerIP);
RefreshListDisplay;
end;
procedure TForm1.TCPServerDisconnect(AContext: TIdContext);
var
Client: PClient;
begin
Client := PClient(AContext.Data);
Protocol.Items.Add (TimeToStr(Time)+' Client "' + Client.HostName+'"' + ' disconnected.');
try
Clients.LockList.Remove(Client);
finally
Clients.UnlockList;
end;
FreeMem(Client);
AContext.Data := nil;
RefreshListDisplay;
end;
procedure TForm1.TCPServerExecute(AContext: TIdContext);
var
Client : PClient;
Command : string;
//PicturePathName : string;
ftmpStream : TFileStream;
begin
if not AContext.Connection.Connected then
begin
Client := PClient(AContext.Data);
Client.LastAction := Now;
//Command := AContext.Connection.ReadLn;
if Command = 'CheckMe' then
begin
{do whatever necessary in here}
end;
end;
end;
idTCPServer コンポーネントは次のように設定されています: ListenQueue := 15、MaxConnections := 0、TerminateWaitTime: 5000。
ここで何か間違ったことをしていますか?一度に約 30 ~ 40 のクライアントをサポートするには、別のアプローチを取る必要がありますか?
ありがとう、ボブ。