Als Lösung dafür habe ich es so programmiert, dass ich bei Auftreten des Fehler die komplette TIdTCPClient Instanz lösche und neu instanziiere, um einen ganz frischen neuen Socket zu bekommen. Leider gibt es mit der neuen Instanz genau dasselbe Problem: Es geht sofort mit Error 10054 weiter.
Aber! Starte ich mein Programm neu, geht es völlig problemlos!
Was macht ein Programmneustart mehr, was ein IdTCPClient.Free;
nicht zu leisten vermag?
Das ist in der Tat seltsam. Ich kann es mir nur damit erklären, dass es etwas mit der Zeit zu tun hat, die zwischen dem Free und dem Neuerzeugen vergeht. Es gibt das manchmal bei Servern, dass eine Verbindung, nachdem sie beendet (besser gesagt abgebrochen) wurde, erst mal eine Weile weiter bestehen bleibt (
TIME-WAIT). Während der alte Socket im TIME-WAIT-Zustand ist, kann man keinen neuen Socket auf dem Port erstellen.
Eigentlich sollte das nach meinem begrenzten Wissen nur bei Servern ein Problem sein und nicht bei Clients. Aber ich könnte mir vorstellen, dass es dennoch irgendwas damit zu tun hat.¹ Du kannst ja mal zum Testen nach dem Free ein Sleep o.ä. einbauen, das ungefähr so lange dauert wie ein Programmneustart dauern würde.
Oder kann es sein, dass irgendeine Firewall oder Virenscanner auf dem Client verrückt spielt?
Edit ¹: Jetzt wo ich noch mal darüber nachdenke: Vermutlich ist der Server oder die Verbindung zum Server irgendwie abgeschmiert (wurde nicht korrekt beendet), und der Socket bleibt deshalb im TIME-WAIT-Zustand. Der Server versucht einen neuen Listener-Socket zu erstellen, kann er aber nicht, weil der alte Socket noch im TIME-WAIT-Zustand ist. Natürlich lässt das Betriebssystem des Servers keine neuen Verbindungen zu dem alten Socket zu, weil der ja tot ist, weshalb die Verbindungsversuche deines Clients mit "Connection reset by peer" zurückgewiesen werden. Wenn du eine Weile wartest, ist der alte Socket weg, der Server kann einen neuen erstellen, und dann klappen die Verbindungen wieder.