AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi Indy 10 - Adresse wird bereits verwendet
Thema durchsuchen
Ansicht
Themen-Optionen

Indy 10 - Adresse wird bereits verwendet

Ein Thema von stahli · begonnen am 8. Mär 2014 · letzter Beitrag vom 10. Mär 2014
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.343 Beiträge
 
Delphi 11 Alexandria
 
#1

Indy 10 - Adresse wird bereits verwendet

  Alt 8. Mär 2014, 23:06
Ich habe einen Indy-Server und Client.
Derzeit tausche ich nur Now und einen Counter als Strings aus.
Zusätzlich wird Now und ein Counter in jedem Client (lokal) verwaltet und in Strings gespeichert.

Zwei Probleme und eine Frage...

1) Wenn zwei Clients auf dem selben Rechner laufen gibt es nach einiger Zeit immer wieder die Fehlermeldung "Adresse wird bereits verwendet"

- Ist in meinem Code direkt etwas falsch?

2) Wenn der Server auf meinem PC und der Client auf meinem Notebook läuft hängt die Client-GUI aller paar Sekunden für ca. 2 Sekunden.
Das betrifft alle laufenden Clients synchron. Es sollte also m.E. wohl am Netzwerk liegen.
Andersrum gibt es keine Hänger, auch nicht wenn der Server und Client auf dem Laptop laufen.

- Vielleicht liegst an der Firewall? Oder liegen dafür andere Gründe nahe?

3) Wenn ich sagen wir mal 100 mögliche Commands hätte, müssten diese 100 Fälle im Server ja hintereinander geprüft werden.
Die 100 Commands nacheinander im Client-Timer zu senden, wäre aber sicher suboptimal.
Wie macht man es korrekt? Alle Commends in einer Liste verwalten und im Timer jeweils einen Schritt weiter iterieren und 1 Command senden?


Delphi-Quellcode:
// Server

procedure TForm1Server.FormCreate(Sender: TObject);
var
  Binding: TIdSocketHandle;
begin
  IdIPWatch1.Active := True;
  Memo1.Text := IdIPWatch1.LocalIP;
  Binding := IdTCPServer1.Bindings.Add;
  Binding.IP := IdIPWatch1.LocalIP;
  Binding.Port := 40000;
  IdTCPServer1.Active := True;
  IdIPWatch1.Active := False;
  Button1Click(Sender);
end;

procedure TForm1Server.IdTCPServer1Execute(AContext: TIdContext);
var
  cmd: String;
begin
  try
    Inc(Counter);
    cmd := Trim(AContext.Connection.IOHandler.ReadLn);

    if (cmd = '@Now') then
    begin
      AContext.Connection.IOHandler.WriteLn(DateTimeToStr(Now));
    end;

    if (cmd = '@Counter') then
    begin
      AContext.Connection.IOHandler.WriteLn(IntToStr(Counter));
    end;

  finally
    AContext.Connection.Disconnect;
  end;
end;

// Client

procedure TForm1Client.Timer1Timer(Sender: TObject);
begin
  Gui.sGuiNow := DateTimeToStr(Now);
  Inc(Gui.GuiCounter);
  Gui.sGuiCounter := IntToStr(Gui.GuiCounter);

  IdTCPClient1.Connect;
  try
    IdTCPClient1.IOHandler.WriteLn('@Now');
    Gui.sNow := IdTCPClient1.IOHandler.ReadLn();
  finally
    IdTCPClient1.Disconnect;
  end;

  IdTCPClient1.Connect;
  try
    IdTCPClient1.IOHandler.WriteLn('@Counter');
    Gui.sCounter := IdTCPClient1.IOHandler.ReadLn();
  finally
    IdTCPClient1.Disconnect;
  end;

  ...
end;
Miniaturansicht angehängter Grafiken
indyfehler.png  
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#2

AW: Indy 10 - Adresse wird bereits verwendet

  Alt 9. Mär 2014, 00:24
Zu 2 und 3 kann ich sagen:

Packe das in Threads (jetzt hau mich nicht gleich ) dann hat die GUI keine Hänger und die Commands kannst du weiterverarbeiten nachdem die Antwort vom Server gekommen ist (evtl. noch synchronisierte Rückmeldung an die GUI)
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo ( 9. Mär 2014 um 01:46 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.538 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Indy 10 - Adresse wird bereits verwendet

  Alt 9. Mär 2014, 01:31
Der Empfehlung von Sir Rufo schließe ich mich an.

Bei Deiner aktuellen Lösung läuft der Timer wahrscheinlich irgendwann über. D.h es kommt schon die nächste Timeranforderung, bevor der vorherige Timer- Event abgearbeitet war. So was kann man vermeiden, indem man am Anfang des Events den Timer ausschaltet und am Ende wieder einschaltet.
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 16. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#4

AW: Indy 10 - Adresse wird bereits verwendet

  Alt 9. Mär 2014, 02:25
Haut mich nicht gleich wenn ich behaupte dass man keine Threads braucht.
Man benötigt das Event OnReadData das immer dann abgefeuert wird wenn Daten angekommen sind.
(bin mir nur nicht sicher ob Indy dieses Event überhaupt hat. Die alte Unit ScktComp hat das Event jedenfalls)

Das periodische Senden von @Now und @Counter kann man problemlos mit einem Timer vornehmen; nur der Empfang der Antwort wird von dem Event getriggert.
fork me on Github
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.343 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Indy 10 - Adresse wird bereits verwendet

  Alt 9. Mär 2014, 10:47
Also erst mal sollte sich hier möglichst niemand prügeln weil sonst die nächsten Delphitage Maßnahmen bräuchten wie bisher Fußballspiele ...

Also ich nutze keine VCL-Controls und eine Synchronisation sollte nicht notwendig sein. Wenn es später komplexer wird will ich gemeinsame Zugriffe aber über critcal Sections schützen.

Ich verstehe das auch so, dass die Indy-Antwort in einem Thread kommt und Indy das kapselt. So ganz habe ich das allerdings noch nicht nachvollziehen können.
Eigentlich müsste dann die Zeile bei *1 vom Compiler ja in einen Thread gekapselt werden, was ich auch wieder nicht glauben kann.
Dafür würde es wohl eine Anweisung brauchen wie IdTCPClient1.IOHandler.ReadLnInString(S); damit ein Thread erzeugt und die Variable übergeben werden und der Mainthread weiter laufen könnte. Insofern glaube ich eher, dass der Timer eine längere Behandlung braucht und auf die Übertragung warten muss.

Daher denke ich auch nicht, dass ein weiterer Thread hilft oder das temp. Ausschalten des Timers (werde ich natürlich testen, komme ich aber erst später dazu).
M.E. feuert ein Timer ja anderseits auch nicht wenn er gerade noch läuft. Maximal sollte es so sein, dass ein Timer nach Beendigung "gleich wieder" feuert, aber zwischendrin bekommt ja der Mainthread m.E. erst mal wieder Zeit.

Es scheint so zu sein, dass Problem 1) nur entsteht, wenn mehrere Clients auf dem gleichen PC laufen.


Ich könnte mir folgendes als zweckmäßig vorstellen:

Delphi-Quellcode:
procedure TForm1Client.Timer1Timer(Sender: TObject);
begin
   Gui.sGuiNow := DateTimeToStr(Now);
   Inc(Gui.GuiCounter);
   Gui.sGuiCounter := IntToStr(Gui.GuiCounter);

  if NichtSchonEineAnFrageFürXXXLäuftUndDieLetzteAnfrageÄlterIstAlsEineHalbeSekunde then
  begin
     IdTCPClient1.Connect;
     try
       IdTCPClient1.IOHandler.WriteLn('@Now');
       Gui.sNow := IdTCPClient1.IOHandler.ReadLn(); // *1
     finally
       IdTCPClient1.Disconnect;
     end;
  end;

  if NichtSchonEineAnFrageFürXXXLäuftUndDieLetzteAnfrageÄlterIstAlsEineHalbeSekunde then
  begin
     IdTCPClient1.Connect;
     try
       IdTCPClient1.IOHandler.WriteLn('@Counter');
       Gui.sCounter := IdTCPClient1.IOHandler.ReadLn(); // *1
     finally
       IdTCPClient1.Disconnect;
     end;
  end;

  ...
end;

Ich bräuchte mal eine damit ich den rechten Weg finde...
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)

Geändert von stahli ( 9. Mär 2014 um 10:53 Uhr)
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.176 Beiträge
 
Delphi 10 Seattle Enterprise
 
#6

AW: Indy 10 - Adresse wird bereits verwendet

  Alt 10. Mär 2014, 09:24
Ich verstehe nicht- Warum disconnectest du dauernd von allen Seiten? Warum lässt du die Verbindung nicht einfach offen?
Der Socket Error 10048 bedeutet übrigens auch, dass man versucht, einen Socket an eine IP/Port-Kombo zu binden, die grade noch im Begriff ist, disconnected zu werden. Nicht dass Indy das irgendwie teilweise asynchron macht und das dann daher rührt.

PS: Ich weiß noch nicht ganz genau was du auf lange Sicht vor hast, aber ich bin mit den "Cromis IMC/IPC"-Komponenten wirklich glücklich geworden. Im Endeffekt noch eine Abstraktionsschicht auf den Indy-TCP-Komponenten obendrauf. Grade "Pures TCP" fände ich jetzt wirklich noch etwas zu grob. Das Cromis-Paket macht einem die Sache wirklich viel angenehmer.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#7

AW: Indy 10 - Adresse wird bereits verwendet

  Alt 10. Mär 2014, 09:45
Ich verstehe das auch so, dass die Indy-Antwort in einem Thread kommt und Indy das kapselt.
Das ist richtig, die Implementierung (mit einem Thread auf der Indy-Seite) ist aber für deine Fragestellung hier völlig belanglos.
Denn
Delphi-Quellcode:
// Der Befehl kehrt zurück, wenn gesendet wurde
IdTCPClient1.IOHandler.WriteLn('@Now');
// Der Befehl kehrt zurück, wenn empfangen wurde
Gui.sNow := IdTCPClient1.IOHandler.ReadLn();
Wenn das Senden und Empfangen nun 5 Minuten dauert, dann ist dein UI auch 5 Minuten blockiert!

Um diese UI-Blockade zu vermeiden, musst du das zwangsläufig in einen eigenen Thread packen.

Auf der Indy-Seite ist das (im Groben) so implementiert
Delphi-Quellcode:
procedure WriteLn;
var
  LSendThread : TSendThread;
begin
  LSendThread.Create;
  try
    LSendThread.WaitFor; // warten, bis der Thread fertig ist
  finally
    LSendThread.Free;
  end;
end;
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo (10. Mär 2014 um 09:49 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.648 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Indy 10 - Adresse wird bereits verwendet

  Alt 10. Mär 2014, 10:22
Also ich nutze keine VCL-Controls und eine Synchronisation sollte nicht notwendig sein.
Solange du auch keine Windows Controls über deren Handles in mehreren Threads nutzt (dazu gehört auch die Nachrichtenwarteschlange des jeweiligen Fensters) ist das korrekt. Ansonsten musst du auch ohne VCL synchronisieren.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.343 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: Indy 10 - Adresse wird bereits verwendet

  Alt 10. Mär 2014, 10:26
Mal schnell der aktuelle Stand:

1)

Ich habe nochmal gesucht nach "Indy 10048" (auch in der DP) und das für mich folgendermaßen interpretiert:

Indy sammelt einige tausend Verbindungen und räumt die nach dem Schließen wieder auf. Das dauert 1-2 Minuten.
Ich hatte nun einfach aller paar Millisekunden neue Daten abgerufen. Dann war der Puffer (wenn mehrere Clients liefen) irgendwann voll und neue Verbindungen wurden benötigt ehe die alten aufgeräumt waren. Das führte zu den Fehlermeldungen.
Indy arbeitet aber weiter und der nächste Verbindungsversuch klappt werden wieder Daten übertragen. Wenn nicht gibt es laufende Fehlermeldungen.

Jetzt habe ich einen erneuten Abruf eines Wertes frühestens 250ms nach dem letzten Aufruf ausgeführt (so eine Unterbrechungsregelung will ich ja real ohnehin managen) und jetzt liefen dutzende Clients auf einem Rechner und im Netzwerk problemlos über lange Zeit.

Das Problem war also die zu häufige Datenübertragung (was verständlich ist, ich dachte nur das ginger wegen der kurzen Strings schon gut).

2)

Die Hakler bei Client auf NB und Server auf PC scheint Kaspersky auf dem PC zu verursachen. Jedenfalls hat das einige kritische Netzwerkzugriffe gemeldet. Ich werde das mal noch in Ruhe ansehen.
Alle anderen C/S-Konfigurationen laufen absolut flüssig.

3)

Die TCP-Übertragung will ich ohnehin einem Manager übertragen, der die Ergebnisse für die GUI dann puffert und verwaltet. Insofern kann ich ich die reale Datenübertragung danach optimieren, welche Daten wirklich neu benötigt werden.


--

Also insgesamt sieht das jetzt schon ganz gut aus.
Die GUI (nicht VCL) läuft sehr flüssig. Blockiert würde sie wenn Indy hängen würde.

Ich werde später die Übertragung wohl noch in einen Thread packen (insbesondere wie jaenicke schreibt, weil ich auf Maus- und Tastatur reagieren will), aktuell ist das in der derzeitigen Phase aber erst mal nicht erforderlich damit alles flüssig läuft.

Ich halte Euch auf dem Laufenden.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
mjustin

Registriert seit: 14. Apr 2008
3.006 Beiträge
 
Delphi 2009 Professional
 
#10

AW: Indy 10 - Adresse wird bereits verwendet

  Alt 10. Mär 2014, 10:48
Hier wird der Hintergrund erläutert und für einen Beispielserver die maximale Anzahl gleichzeitig geöffneter Ports berechnet (470):

http://www.fromdual.com/huge-amount-...it-connections

Müssen die Verbindungen sofort geschlossen werden? In der Praxis hält zum Beispiel HTTP 1.1 die Verbindung längere Zeit aufrecht und sendet über sie mehrere Requests. (Das ist im o.g. Artikel die erste Lösung: put more workload in one connection)
Michael Justin
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:50 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