Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Error Event für TIdTCPClient (https://www.delphipraxis.net/170948-error-event-fuer-tidtcpclient.html)

ByTheTime 11. Okt 2012 22:44

Error Event für TIdTCPClient
 
Hallo,
Ich habe mich in Sachen Netzwerk (TCP) fast ausschließlich mit den Sockets befasst. Dort kann ich im OnError-Event einfach "ErrorCode := 0;" setzen um den Benutzer nicht mit dieser unverständlichen Exception zu konfrontieren, sondern sie zu behandeln... Gibt es soetwas auch für den TCPClient von INDY? Oder etwas ähnliches? So das der Nutzer NICHT diese für den "Normalen PC-Benutzer" unverständliche Exception angezeigt bekommt?

Dankeschön :)

DataCool 12. Okt 2012 00:00

AW: Error Event für TIdTCPClient
 
Hi,

ganz einfach die Passagen die Deiner Meinung nach kritisch sind
einfach mit Try Finally / try except kapseln.
Ein explizites "OnError" der "OnException" gibt es beim IdTcpClient nicht, nur beim Server.
Ich sehe ehrlich gesagt beim Client auch keinen Grund für diese Ereignisse,
der Client sollte jederzeit seinen "Zustand" kennen und wissen wann er zu Lesen/zu Schreiben hat
und was er im Fehlerfall zu tuen hat.

Was soll Dein Client den konkret machen ?
Und warum kommen überhaupt Exceptions ?

Greetz Data

ByTheTime 14. Okt 2012 15:48

AW: Error Event für TIdTCPClient
 
Ich bastel gerade mit der WebCam und der Übertragung via TCPClient an den TCPServer von INDY. Ich bekomme auch ein Bild, wenn ich das Video mit einem Button starte und stoppe es über einen anderen Button. Allerdings ist das stoppen immer etwas heikel, denn ich schicke zum beenden des Streams dem Clienten eine Nachricht, der trennt sich dann. Dann beendet sich der Server und die Buttons nehmen wieder den Anfangszustand an (Start ist aktiv, Stop ist inaktiv). Aber was ist, wenn das Internet mal stutzt? Dann beendet sich der Server, bevor der Client die Nachricht erhalten hat und es gibt eine Exception. Ich habe mir auch überlegt, die Verbindung vom Server aus sauber zu trennen:

Delphi-Quellcode:
procedure TfrmCam.CamStop;
var
  Clients: TList;
  i: Integer;
begin
  BtnStop.Enabled := false;
  Clients := CamServer.Contexts.LockList;
  try
    for i := 0 to Clients.Count - 1 do
      TIdContext(Clients[i]).Connection.Disconnect;
  finally
    CamServer.Contexts.UnlockList;
  end;
  CamServer.Active := false;
  RVideo.Picture := BImage.Picture; {Das VideoFenster bekommt eine WebCam als Icon aus einem anderen Image, damit es nciht so langweilig aussieht :)}
  BtnStart.Enabled := true; //  Buttons anpassen.
Aber hier gibt es auch eine Exception. Da steht dann, das die Software einen Verbindungsabbruch verursacht (SocketFehler #10053).

DataCool 15. Okt 2012 10:53

AW: Error Event für TIdTCPClient
 
Hi,

beim Code den Du da gepostet hast gehe ich mal davon aus, das es sich um den Server-Code beim
Beenden des Servers/des Streams handelt.

Dazu folgende Anmerkungen:
- Die Liste der Client am besten Rückwärts durchlaufen (Count-1 downto 0), weil wen ein Client seine Verbindung trennt wird er aus der Liste entfernt, ich bin mir nicht sicher ob das in diesem Fall durch das Locken der Liste komplett abgefangen wird.
- Du schreibst Du schickst den Clients eine Nachricht das der Server beendet wird, davon sehe ich in dem Code nichts, dort disconnectest Du die Clients nur, ohne Sie(die Clients) zu informieren, dann kommt es ziemlich sicher bei den Clients zu Exceptions, weil Du denen sozusagen die Verbindung "unterm Arsch" wegziehst. Ich würde den Clients vorher ein Kommando schicken, das der Streams Server um Abmeldung bittet, so das sich die Clients dann von selber beim Server abmelden das ist dann sauberer.

Ein bisschen Client-Code wäre bei der ganzen Sache auch sehr hilfreich ;-)

Greetz Data

ByTheTime 25. Okt 2012 17:16

AW: Error Event für TIdTCPClient
 
Sorry, das ich mich so lange nicht gemeldet habe, ich wa rim Urlaub und habe in dieser Zeit den Laptop mal ruhen lassen. Aber hier noch mal das Problem und etwas Code:

Ich kann dem Clienten eine Nachricht senden, das er sich beenden soll. Das klappt auch wunderbar, alle Buttons nehmen den Amfangszustand wieder an und die Lampe an meiner WebCam geht aus. Srücke ich jetzt erneut den Start-Button, geht zwar die WebCam an, allerdings bekomme ich kein Bild. Drücke ich dan den Stop-Button, bleibt mein Server-Programm hängen.

Client:

Delphi-Quellcode:
//Adressen, etc. werden schon beim OnCreate gesetzt!

//Erhält Steuerkommandos vom Server

cmdSTARTCAM:
      CamClient.Connect;
    cmdSTOPCAM:
      try
        CamClient.Disconnect;
      except
        ClientSend(Syntax[cmdCAMMSG].Text + #13 + 'Es ist ein Fehler beim trennen der Verbindung aufgetreten.' + #13);
      end;

//Benötiger Code

procedure TfrmMain.CamClientConnected(Sender: TObject);
begin
  fActivated := False;
  fVideoImage := TVideoImage.Create;
  fVideoImage.SetDisplayCanvas(GVideo.Canvas);
  CamExecute;
  TimerList.Events[4].Enabled := TRUE;
end;

procedure TfrmMain.CamClientDisconnected(Sender: TObject);
begin
  TimerList.Events[4].Enabled := False;
  fVideoImage.VideoStop;
  fVideoImage.Free;
  fActivated := TRUE;
  UploadProgress := False;
end;

procedure TfrmMain.CamClientWorkBegin(ASender: TObject; AWorkMode: TWorkMode;
  AWorkCountMax: Int64);
begin
  UploadProgress := TRUE;
end;

procedure TfrmMain.CamClientWorkEnd(ASender: TObject; AWorkMode: TWorkMode);
begin
  UploadProgress := False;
end;

procedure TfrmMain.CamExecute;
var
  DeviceList: TStringList;
begin
  if fActivated then
    Exit;
  fActivated := TRUE;

  DeviceList := TStringList.Create;
  fVideoImage.GetListOfDevices(DeviceList);

  if not DeviceList.Count < 1 then
    fVideoImage.VideoStart(DeviceList[0])
  else
    ClientSend(Syntax[cmdCAMMSG].Text + #13 +
      'Es wurde kein Gerät gefunden!' + #13);
end;

procedure TfrmMain.TimerListEvents4Timer(Sender: TObject);
begin
  if CamClient.Connected then
    if UploadProgress = False then
      CamSend(GVideo.Picture.Bitmap); //Image mit Bild der WebCam
end;

procedure TfrmMain.CamSend(Pic: TBitmap);
var
  MStream: TMemoryStream;
begin
  MStream := TMemoryStream.Create;

  try
    Pic.SaveToStream(MStream);
    MStream.Position := 0;
    try
      CamClient.Socket.Write(MStream, 0, TRUE);
    except
    end;
  finally
    MStream.Free;
  end;
end;
Server:

Delphi-Quellcode:
procedure TfrmCam.CamStop;
begin
  BtnStop.Enabled := false;

  frmMain.ClientSend(Syntax[cmdSTOPCAM].Text + #13);

  delay(500); //Sichergehen, dass das Kommando "durch die Leitung" ist

  CamServer.Active := false;

  RVideo.Picture := BImage.Picture; //Das Bild einer WebCam aus einem "Backup"-Image in das VideoFenster laden
  BtnStart.Enabled := true;
end;

procedure TfrmCam.BtnStartClick(Sender: TObject);
begin
  frmCam.CamServer.Active := true;
  frmMain.ClientSend(Syntax[cmdSTARTCAM].Text + #13);
  BtnStart.Enabled := false;
  BtnStop.Enabled := true;
end;

procedure TfrmCam.BtnStopClick(Sender: TObject);
begin
  CamStop;
end;

procedure TfrmCam.CamServerExecute(AContext: TIdContext);
var
  FStream: TMemoryStream;
begin
  FStream := TMemoryStream.Create;

  try
    AContext.Connection.Socket.ReadStream(FStream);
  finally
    try
      FStream.Position := 0;
      RVideo.Picture.Bitmap.LoadFromStream(FStream);
    finally
      FStream.Free;
    end;
  end;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:09 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz