Hallo,
also ich benutze seit 2 Jahren die Indy-Komponenten (aktuell 10.2) in einem größeren Projekt (ca. 10 Server und 10 Clients)
und bin sehr zufrieden damit. Allerdings habe ich die Indy-Komponenten nicht in die IDE hinein kompiliert, sondern nutze "manuell" die Units.
Beispielcode für den Server:
Code: Alles auswählen
uses
...
IdTCPServer,
IdContext,
...
type
TTestServer = class
private
fServer : TIdTCPServer;
fContext: TIdContext;
fClientIP : String;
procedure MyOnConnect(AContext: TIdContext);
procedure MyOnDisconnect(AContext: TIdContext);
procedure MyOnExecute(AContext: TIdContext);
function StartServer(Port: Integer): Boolean;
function StopServer: Boolean;
public
constructor Create(MyServerPort: Integer);
destructor Destroy; override;
end;
const
IdleWaitTime = 500;
ServerReadTimeout = 5000;
var MyServer: TTestServer; // Achtung: Objekt noch separat erzeugen mit MyServer := TTestServer(dein-Server-Port); bzw. Freigeben MyServer.Free;
implementation
...
procedure TTestServer.MyOnConnect(AContext: TIdContext);
begin
// falls sich sich nur ein Client verbindet:
fContext := AContext;
fClientIP := AContext.Connection.Socket.Binding.PeerIP;
// Der Client fClientIP ist nun verbunden
end;
procedure TTestServer.MyOnDisconnect(AContext: TIdContext);
begin
fContext := nil; // Client fClientIP ist nicht mehr verbunden
end;
procedure TTestServer.MyOnExecute(AContext: TIdContext);
// wird ständig als separater Thread (einer pro Client) ausgeführt,
// sobald ein Client verbunden wird bis er disconnected
begin
// falls irgendetwas automatisiert zu tun ist, ansonsten:
Sleep(IdleWaitTime);
end;
function TTestServer.StartServer(Port: Integer): Boolean;
begin
fServer.Active := false;
fServer.Bindings.Clear;
fServer.DefaultPort := Port;
fServer.Bindings.DefaultPort := Port;
fServer.Bindings.Add;
fServer.Active := true;
Result := fServer.Active;
end;
function TTestServer.StopServer: Boolean;
begin
Try
If Assigned(fContext) then
fContext.Yarn.Free;// dann kann auch bei verbundenen Client beendet werden
fServer.Active := false;
fServer.Bindings.Clear;
Result := not fServer.Active;
Except
Result := false;
end;
end;
constructor TTestServer.Create(MyServerPort: Integer);
begin
inherited Create;
fContext := nil; // kein Client verbunden
fServer := TIdTCPServer.Create;
fServer.OnConnect := @MyOnConnect;
fServer.OnDisconnect := @MyOnDisconnect;
fServer.OnExecute := @MyOnExecute;
// Server automatisch starten
If StartServer(MyServerPort) then begin
// ...
end;
end;
destructor TTestServer.Destroy;
begin
StopServer;
fServer.Free;
inherited Destroy;
end;
Auch mit dem Server kannst Du Nachrichten an den Client senden (sofern Assigned(fContext)=true):
Code: Alles auswählen
fContext.Connection.IOHandler.InputBuffer.Clear;
fContext.Connection.IOHandler.Write('TEST'+#10);
Die Rückantwort (s:String) gibt es dann mit:
Code: Alles auswählen
Try
s := fContext.Connection.IOHandler.ReadLn(#10,ServerReadTimeout);
If not fContext.Connection.IOHandler.ReadLnTimedOut then begin
ShowMessage(s);
end else begin
// Überprüfung auf z.B fContext.Connection.IOHandler.InputBufferIsEmpty
// oder Untersuchung von fContext.Connection.IOHandler.InputBufferAsString
end;
Except
fContext := nil;
// ...
end;
Und der Beispielcode für den Client mit Senden über SendData und Empfang mit automatischer Anzeige:
Code: Alles auswählen
uses
...
IdTCPClient;
type
TClientThread = class(TThread)
private
fData : String;
fTCPClient : TIdTCPClient;
procedure SendData(AData: String);
protected
procedure Execute; override;
public
constructor Create(AHost: String; APort: Integer);
destructor Destroy; override;
end;
const
ClientConnectTimeout = 5000; // starte aller 5s eine neue Verbindung
var ClientThread : TClientThread; // Achtung: Objekt noch separat erzeugen und freigeben
implementation
procedure TClientThread.SendData(AData: String);
begin
fTCPClient.IOHandler.Write(AData+#10);
// ...
end;
procedure TClientThread.Execute;
var DataIn : String;
begin
While not Terminated do begin
// Starte automatisch neue Verbindung
While not fTCPClient.Connected and not Terminated do begin
Sleep(ClientConnectTimeout);
Try
fTCPClient.Connect; // verbunden mit fTCPClient.Host auf fTCPClient.Port
Except
// keine Verbindung
end;
end;
Try
While fTCPClient.Connected and not Terminated do begin
DataIn := fTCPClient.IOHandler.ReadLn(#10,1000);
If not fTCPClient.IOHandler.ReadLnTimedOut then begin
ShowMessage(DataIn);
// ...
// ggf. reagieren und Antwort mit SendData schicken
end;
end;
Except
fTCPCLient.Disconnect; // wenn Disconnect während ReadLn
end;
end;
fTCPCLient.Disconnect;
end;
constructor TClientThread.Create(AHost: String; APort: Integer);
begin
inherited Create(true); // Create suspended
fTCPClient := TIdTCPCLient.Create;
fTCPClient.Host := AHost;
fTCPClient.Port := APort;
Resume; // Thread automatisch starten
end;
destructor TClientThread.Destroy;
begin
// ...
fTCPClient.Free;
Terminate;
inherited Destroy;
end;
Ich denke, dass müsste Dir erst einmal weiterhelfen, wenn Du mit Indy weiterarbeiten möchtest.
Als Abschlusszeichen habe ich LF=#10 genommen.
Dieser spezielle Beispielcode ist allerdings nicht getestet, ich hoffe er funktioniert trotzdem

Gruß Thomas