![]() |
Ersetzen nicht-blockierender TServerSocket durch Indy
Ich habe eine ganz simple funktionierende Anwendung mit TServerSocket (hier zudem vereinfacht dargestellt):
Delphi-Quellcode:
Nun soll das Ganze mit Indy, also wohl TIdTCPServer, ersetzt werden. Ich lese, dass Indy kein nicht-blockierend kann bzw. man sich was mit Threads etc. ausdenken muss.
TMainForm = class(TForm)
ServerSocket1: TServerSocket; procedure FormCreate(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); end; procedure TMainForm.FormCreate(Sender: TObject); begin ServerSocket1.ServerType := stNonBlocking; ServerSocket1.Port := 4711; ServerSocket1.Open; end; procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction); begin ServerSocket1.Close; end; procedure TMainForm.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); var nachricht: string; begin nachricht:= string(Socket.ReceiveText); if nachricht = 'hallo' then Socket.SendText(ansistring('hallo empfangen')); end; end; Kann mir jemand das obige Beispiel mit Indy aufzeigen? Ich finde immer reichlich Kompliziertes, wäre aber an einer einfachen Lösung interessiert. Falls jemand meint, ich sollte TServerSocket weiterverwenden, wäre ich natürlich interessiert, wie man das mit FMX einbindet. - Uli |
AW: Ersetzen nicht-blockierender TServerSocket durch Indy
Zitat:
|
AW: Ersetzen nicht-blockierender TServerSocket durch Indy
Vermutlich weil die Anwendung auf Firemonkey umgestellt werden soll.
|
AW: Ersetzen nicht-blockierender TServerSocket durch Indy
Zitat:
- Uli |
AW: Ersetzen nicht-blockierender TServerSocket durch Indy
Hier ist ein kleines Beispiel für ein Indy 10 basiertes Programm mit Server und Client, mit "Request/Reply" (Anfrage/Antwort) Kommunikation.
Das Programm verwendet als einziges GUI Bestandteil ein TMemo namens "MemoLog".
Was man je nach gewählten Werten für die Pausen leicht erkennen kann, ist es möglich, dass der Client mehr Requests sendet als der Server abarbeiten kann. (Die Requests sind dazu nummeriert). Das bedeutet, dass sich am Server unbeantwortete Anfragen aufhäufen können, was schliesslich zu einer Überlastung des Servers führen kann. Der Beispielcode enthält keinerlei Fehlerbehandlung: falls der Client die Verbindung verliert, wird der Thread einfach beendet und freigegeben.
Delphi-Quellcode:
Beispielausgabe:
unit Unit1;
interface uses IdCustomTCPServer, IdTCPClient, IdContext, SysUtils, Classes, Forms, StdCtrls, Controls; type TClientThread = class(TThread) private TCPClient: TIdTCPClient; FLog: TStrings; public constructor Create(AHost: string; APort: Word; ALog: TStrings); destructor Destroy; override; procedure Execute; override; end; TMyServer = class (TIdCustomTCPServer) protected function DoExecute(AContext: TIdContext): Boolean; override; end; TServerPushExampleForm = class(TForm) MemoLog: TMemo; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private ExampleClient: TClientThread; ExampleServer: TMyServer; end; var ServerPushExampleForm: TServerPushExampleForm; implementation uses IdGlobal; {$R *.dfm} procedure TServerPushExampleForm.FormCreate(Sender: TObject); begin MemoLog.Clear; ExampleServer := TMyServer.Create; ExampleServer.DefaultPort := 8088; ExampleServer.Active := True; ExampleClient := TClientThread.Create('localhost', 8088, MemoLog.Lines); end; procedure TServerPushExampleForm.FormDestroy(Sender: TObject); begin ExampleServer.Free; ExampleClient.Terminate; ExampleClient.WaitFor; ExampleClient.Free; end; { TMyServer } function TMyServer.DoExecute(AContext: TIdContext): Boolean; var Request: string; begin Result := inherited; Request := AContext.Connection.IOHandler.ReadLn(IndyTextEncoding_UTF8); // simulate hard work Sleep(Random(4000)); AContext.Connection.IOHandler.WriteLn('reply for ' + Request, IndyTextEncoding_UTF8); end; { TClientThread } constructor TClientThread.Create(AHost: string; APort: Word; ALog: TStrings); begin inherited Create(False); FLog := ALog; TCPClient := TIdTCPClient.Create; TCPClient.Host := AHost; TCPClient.Port := APort; TCPClient.ReadTimeout := 500; end; destructor TClientThread.Destroy; begin TCPClient.Free; inherited; end; procedure TClientThread.Execute; var Request, Reply: string; RequestNr: Integer; begin RequestNr := 0; TCPClient.Connect; while not Terminated do begin Inc(RequestNr); Request := Format ('request %d', [RequestNr]); TThread.Queue(nil, procedure begin FLog.Append('send: ' + Request); end); TCPClient.IOHandler.WriteLn(Request, IndyTextEncoding_UTF8); Reply := TCPClient.IOHandler.ReadLn(IndyTextEncoding_UTF8); if not TCPClient.IOHandler.ReadLnTimedout then begin TThread.Queue(nil, procedure begin FLog.Append('recv: ' + Reply); end); end; Sleep(2000); end; TCPClient.Disconnect; end; end.
Code:
send: request 1
recv: reply for request 1 send: request 2 recv: reply for request 2 send: request 3 send: request 4 send: request 5 recv: reply for request 3 send: request 6 recv: reply for request 4 send: request 7 recv: reply for request 5 send: request 8 recv: reply for request 6 send: request 9 recv: reply for request 7 |
AW: Ersetzen nicht-blockierender TServerSocket durch Indy
Schau mal, ob Dir das Beispiel hilft:
![]() |
AW: Ersetzen nicht-blockierender TServerSocket durch Indy
ICS v8 gibt's doch auch für Firemonkey / POSIX und co
![]() |
AW: Ersetzen nicht-blockierender TServerSocket durch Indy
Die für mich vielleicht die einfachste Lösung ist:
TServerSocket einfach wie gehabt weiterverwenden. Es muss ja kein Icon im Designer verwendet werden, man kann das Socket ja auch zur Laufzeit erzeugen. Wie das so immer mit dem Bäumen im Wald ist. Also
Delphi-Quellcode:
Damit läuft es auch. Die Frage hat sich somit erledigt.
TMainForm = class(TForm)
procedure FormCreate(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); public procedure ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); end; procedure TMainForm.FormCreate(Sender: TObject); begin ServerSocket1 := TServerSocket.Create(self); try ServerSocket1.Port := 4711; ServerSocket1.OnClientRead := ServerSocket1ClientRead; ServerSocket1.Open; except on E: Exception do irgendetwas; end; end; procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction); begin if ServerSocket1 <> nil then begin ServerSocket1.Close; ServerSocket1.Free; end; end; procedure TMainForm.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); var nachricht: string; begin nachricht:= string(Socket.ReceiveText); if nachricht = 'hallo' then Socket.SendText(ansistring('hallo empfangen')); end; end; |
AW: Ersetzen nicht-blockierender TServerSocket durch Indy
Zitat:
![]() |
AW: Ersetzen nicht-blockierender TServerSocket durch Indy
Zitat:
*SCNR* Sherlock -der sich schon mal in die Ecke stellt |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:20 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz