IdTCPServer, odpowiedź do serwera . IdTCPClient , odbiór od serwera
TIdTCPServer wysyła odpowiedź do konkretnego klienta za pomocąAContext.Connection.IOHandler.WriteLn(...) wewnątrz zdarzenia OnExecute, OnConnect lub w dowolnym wątku, w którym dysponujemy kontekstem danego klienta. TIdTCPClient odbiera tę odpowiedź synchronicznie wywołując jedną z metod odczytu (najczęściej ReadLn, ReadBytes, ReadStream) po wysłaniu zapytania albo w dedykowanym wątku/Timerze, gdy połączenie ma pozostawać otwarte.Kluczowe punkty
• Serwer i klient muszą uzgodnić terminator (np. CRLF) lub długość ramki.
• Read* i Write* są operacjami blokującymi – stosuj wątki albo asynchroniczne wywołania, by nie zamrozić GUI.
• Każde połączenie klienta ma własny kontekst (TIdContext); serwer może wysłać wiadomość do wszystkich lub wybranego klienta iterując po IdTCPServer.Contexts.
• Obsługuj wyjątki (EIdConnClosedGracefully, EIdReadTimeout, EIdSocketError) i zawsze zamykaj połączenie w bloku finally.
TCP zapewnia dwukierunkowy strumień bajtów. W Indy:
TIdTCPServer. AContext. TIdTCPClient. Po Connect obiekt działa synchronicznie.procedure TMainFrm.IdTCPServerExecute(AContext: TIdContext);
var
Cmd, Resp: string;
begin
try
Cmd := AContext.Connection.IOHandler.ReadLn; // blokujące
Resp := ProcessCommand(Cmd); // własna logika
AContext.Connection.IOHandler.WriteLn(Resp); // odpowiedź
except
on E: EIdConnClosedGracefully do
Exit; // klient zamknął
on E: Exception do
begin
AContext.Connection.IOHandler.WriteLn('ERROR:' + E.Message);
AContext.Connection.Disconnect;
end;
end;
end;
Procesowanie pakietów binarnych: najpierw wyślij długość (Int32 w sieciowym porządku bajtów), potem WriteBuffer.
function TClientCore.QueryServer(const ACmd: string): string;
begin
IdTCPClient.Host := '127.0.0.1';
IdTCPClient.Port := 8080;
IdTCPClient.ReadTimeout := 5000; // ms
IdTCPClient.Connect;
try
IdTCPClient.IOHandler.WriteLn(ACmd); // zapytanie
Result := IdTCPClient.IOHandler.ReadLn; // odpowiedź (blokuje)
finally
IdTCPClient.Disconnect;
end;
end;
Długotrwałe połączenie: utwórz wątek TThread i pętlę
while not Terminated do
if IdTCPClient.IOHandler.InputBufferIsEmpty then
Sleep(10)
else
HandleData(IdTCPClient.IOHandler.ReadLn);
procedure TBroadcaster.Broadcast(const AMsg: string);
var
LList: TList;
Ctx : TIdContext;
begin
LList := IdTCPServer.Contexts.LockList;
try
for Ctx in LList do
TThread.Queue(nil, procedure // wysyłanie z wątku GUI opcjonalne
begin
Ctx.Connection.IOHandler.WriteLn(AMsg);
end);
finally
IdTCPServer.Contexts.UnlockList;
end;
end;
Dbaj o synchronizację – Contexts.LockList/UnlockList zabezpiecza dostęp.
ReadTimeout/ConnectTimeout – unikasz wiecznego blokowania. TThread.Synchronize / TThread.Queue. TThreadSafeStringList.TIdIOTATCPServer z poprawkami bezpieczeństwa TLS 1.3. TIdSSLIOHandlerSocketOpenSSL.WriteStream / ReadStream. IOHandler.DefStringEncoding := IndyTextEncoding_UTF8;.finally IdTCPClient.Disconnect i OnDisconnect po stronie serwera. telnet lub openssl s_client do prostego sniffingu. GStack.CheckSocketsInitialized. TThread.Queue.TIdTCPClient). W bardzo obciążonych systemach rozważ AsyncIO (np. libuv) albo IOCP na Windows. TIdConnectionIntercept.Komunikacja Indy jest prosta: serwer w OnExecute odczytuje komendę, generuje i wysyła odpowiedź przez WriteLn; klient po Connect wykonuje WriteLn i synchronizacyjnie ReadLn, lub trwale nasłuchuje w osobnym wątku. Klucz do stabilności – poprawne zamykanie połączeń, timeouty oraz nieblokowanie wątku GUI. Dzięki tym zasadom zbudujesz bezpieczny i responsywny system klient-serwer w Delphi.