![]() |
Drucken im Netzwerk mit TidLpr: "Socket already in use&
Ich versuche mit der TidLpr Komponente von Indy im Netzwerk zu drucken.
Einen einzelnen Druckauftrag zu senden klappt auch einwandfrei. Wenn ich aber kurz darauf noch einen Druckauftrag sende erhalte ich den Fehler "Socket already in use" bei der Methode TidLpr.Connect. Erst nach 120 Sekunden kann ich wieder drucken. Wo kann man diesen TimeOut einstellen damit Ausdrucke in kurzer Folge möglich sind?
Delphi-Quellcode:
procedure PrintLabel;
begin idlpr.Host := '192.168.0.100'; idlpr.Connect; if idlpr.Connected then begin idlpr.PrintFile('C:\Print.tmp'); idlpr.Disconnect; idlpr.DisconnectSocket; end else ShowMessage('Fehler beim Versenden des Printfiles'); end; |
Re: Drucken im Netzwerk mit TidLpr: "Socket already in
Wird auch wieder richtig getrennt? Wird das zugehörige Ereigniss ausgelöst? Was passiert, wenn du die Komponente jedes mal dynamisch erstellst und wieder frei gibst?
|
Re: Drucken im Netzwerk mit TidLpr: "Socket already in
Ich habe nach dem "Disconnecten" idLpr.Disconnected
abgefragt und es ist auch True. Komponente auflösen und jedesmal neu instanzieren habe ich noch nicht probiert (sollte bei einer Komponente eigentlich nicht erforderlich sein...). Allerdings hilft es auch nichts das ganze Delphi-Programm zu schließen und erneut zu starten (was einem Destroy/Create wohl gleichkommen sollte...) Habe im Internet nach diesem Problem gesucht und gelesen, daß der Drucker den Port wohl noch eine Weile reserviert hält um sicherzustellen, daß die Übertragung komplett ist und nicht noch etwas hinterherkommt. Dieser TimeOut soll sich angeblich beim herstellen der Vebindung über LPR-Protokoll angeben lassen... |
Re: Drucken im Netzwerk mit TidLpr: "Socket already in
Hallo skyobserver,
der Fehler kommt daher, dass der genutzte Port in den FD_WAIT State geht, um dem TCP Stack genügend Zeit zur Beendigung der Connection zu geben. Für TIdLPR und TIdRSH zwingen wir den Client dazu, sich mit einem lokalen Port in einer festen Range zu verbinden, bevor die Connection zum Server hergestellt wird. Dies ist erforderlich. Intern passiert über die Port-Range von TIdTCPClient.BoundPortMin und .BoundPortMax. Normalerweise, wenn man eine feste Client IP Adresse vorgibt, wird einfach der nächste freie Port aus der Range genommen. Wenn man jetzt aber die Wildcard-IP 0.0.0.0 nutzt (default), ist das Bind an den ursprünglichen Port erfolgreich, obwohl dieser im FD_WAIT State ist. Das führt zum "Socket already in use" (10048). Das ist also nicht Indy-spezifisch, sondern vom OS. Workaround: - ~ 60 Sekunden warten, bis der lokale Port aus dem FD_WAIT state ist - TIdTCPClient.BoundIP auf eine lokale IP setzen .BoundPort, .BoundPortMin und .BoundPortMax sollte man hingegen nur setzen, wenn man einen guten Grund hat. Bei dem zweiten Workaround gibt es das Problem, dass ein System mehrere IPs haben kann. Dort die richtige für die Connection zum LPR Server auszuwählen erfordert dann etwas Arbeit. Die TIdTCPClient Properties sollten bei TIdLPR über die Vorfahrenklasse aber erreichbar sein. Tut mir leid, dass es keinen einfacheren Weg gibt, das beste wäre für hochperformante Geschichten den LPR Drucker dem WinSpooler zuzuweisen, der hier automatisch die o.g. Workarounds implementiert. Also direkt gesagt: Nicht das Rad neu erfinden ;) Viele Grüße, Assertor |
Re: Drucken im Netzwerk mit TidLpr: "Socket already in
Zitat:
bei Windows XP nach meinen Tests genau 120 Sekunden. Das ist für meine Zwecke viel zu lang - ich muß Labels im Sekundentakt drucken können. Zitat:
Einmal "Connecten" und mehrmals Drucken geht auch nicht... |
Re: Drucken im Netzwerk mit TidLpr: "Socket already in
Zitat:
eine IP-Adresse schicken kann, ohne den Drucker auf einem Server oder einer Workstation installieren zu müssen. Wenn in einer Firma defekte Rechner getauscht werden müssen ist immer darauf zu achten das alle Einstellungen bzw. installierte Drucker beim neuen Rechner auch vorhanden sind. Es ist sehr aufwändig Ersatz-PCs bei gelegentlichen Änderungen ständig synchron zu halten - vor allem wenn der Betrieb 24 Stunden produziert und man nicht mal 10 Minuten Zeit bekommt um die Festplatte zu clonen. Wenn man Bereitschaftsdienst hat ist man außerdem sehr dankbar, wenn der Schichtelektriker Nachts um 04:00 mal eben selbst den PC umstöpselt und man weiterschlafen kann. Ich muß wohl nicht erwähnen wie "toll" es ist um die Zeit in die Firma zu fahren zu müssen um einen PC zu tauschen... Wenn sich die TimeOut-Zeit nicht einstellen läßt dann muß natürlich das "Standard-Rad" herhalten... ...aber der (EDV-)Mensch strebt ja nach Verbesserungen :) |
Re: Drucken im Netzwerk mit TidLpr: "Socket already in
Hallo skyobserver,
Zitat:
Probier mal folgendes (geht nur, wenn der Rechner nur 1 IP hat):
Delphi-Quellcode:
Du könntest dann noch beim Connect mit einer kleinen Schleife und Timeout dem Port etwas Zeit geben, frei zu werden. Das Problem mit 10048 (WSAADDRINUSE) ist leider MS bekannt und as-designed, da muß so eine Lösung herhalten.
uses
..., IdStack; // IdStack Unit einbinden ... ... procedure PrintLabel; begin idlpr.BoundIP := GStack.LocalAddress; // holt sich die lokale IP idlpr.Host := '192.168.0.100'; idlpr.Connect; if idlpr.Connected then begin idlpr.PrintFile('C:\Print.tmp'); idlpr.Disconnect; // idlpr.DisconnectSocket; // nicht nötig, gibt es in neueren Indys auch nicht mehr end else ShowMessage('Fehler beim Versenden des Printfiles'); end; Gruß Assertor |
Re: Drucken im Netzwerk mit TidLpr: "Socket already in
Habe ich auch schon probiert...Problem bleibt bestehen...
Hatte die BoundIP zur Sicherheit auch schon "hart kodiert" aber um die Wartezeit komme ich nicht herum! Habe auch schon probiert das Printfile über den DOS-Befehl "LPR" (per ShellExecute) zu versenden. Damit bekomme immerhin acht Drucke versand... |
Re: Drucken im Netzwerk mit TidLpr: "Socket already in
Hallo skyobserver,
ja, das es mit Shelltools auch nicht klappt ist klar: Die PortRange für LPR ist da auch schnell erschöpft. Ist halt eine RFC Umsetzung von Windows. Probier es doch mal andersherum:
Delphi-Quellcode:
So wird nicht immer ein neuer Port geöffnet, sondern nur wenn keine Connection besteht. Vorteil dürfte sein, dass wenn der Druck schnell hintereinander erfolgt, der vorhandene Socket genutzt wird. Wenn der Socket nicht offen ist, wird eben ein neuer geöffnet.
procedure PrintLabel;
begin // das auskommentierte mal irgendwo allgemein festlegen (Konstruktor o.ä.) // idlpr.BoundIP := GStack.LocalAddress; // holt sich die lokale IP // idlpr.Host := '192.168.0.100'; if not idlpr.Connected then idlpr.Connect; idlpr.PrintFile('C:\Print.tmp'); end; Nach RFC dürften ca. 10 Sockets für LPR da sein (iirc 721-731). Wenn Du jetzt jedesmal den Socket schließt (+ Timeout von Windows OS, überlicherweise 60-120 sek) bist Du sonst schnell am Limit. Mit o.g. dürfte es aber keine Raise Conditions mehr geben. Fehler kannst Du übrigens - so wie auch den Status - über den IdLPR.OnLPRStatus Event handeln. Gruß Assertor |
Re: Drucken im Netzwerk mit TidLpr: "Socket already in
Die Idee hatte ich auch schon...dann bekomme ich beim zweiten
Druck zwar keine Fehlermeldung aber auch keinen Ausdruck und das Programm friert ein... |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:26 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