2010-11-21 8 views

Antwort

8

Versuchen Sie einfach, bind an den Port und wenn es fehlschlägt, überprüfen Sie EADDRINUSE in errno. Dies ist der einzige Weg, denn um korrekt zu sein, muss eine solche Überprüfung atomar sein. Wenn Sie eine separate Überprüfung durchgeführt haben und dann versucht haben, an den Port zu binden, nachdem Sie festgestellt haben, dass er nicht verwendet wurde, konnte ein anderer Prozess in der Zwischenzeit an den Port gebunden werden, was wiederum dazu führte, dass er fehlschlug. Wenn Sie eine separate Überprüfung durchgeführt und festgestellt haben, dass der Port bereits verwendet wird, konnte der Prozess, der ihn verwendete, den Port schließen, beenden oder in der Zwischenzeit abstürzen, wodurch das Ergebnis erneut falsch angezeigt wurde.

Der Punkt, der all dies (der Grund schrieb ich eine lange Antwort eher als eine kurze Antwort) ist, dass die korrekte und robuste Möglichkeit zu überprüfen, „Kann ich so und so?“ ist fast immer zu versuchen, es zu tun und auf Fehler zu überprüfen. Jede andere Herangehensweise kann zu Rennbedingungen führen, und in vielen Fällen sind die Race Conditions (obwohl wahrscheinlich nicht Ihre) Sicherheitsschwachstellen.

5

bind() fehl:

Bei Erfolg Null zurückgeführt wird. Bei einem Fehler wird -1 zurückgegeben und errno wird entsprechend gesetzt.

EADDRINUSE Die angegebene Adresse ist bereits im Einsatz.

+0

Aber auf diese Weise muss ich einen Server-Socket erstellen ... bind() ... dann schließe es .. Gibt es einen einfacheren Weg? – wong2

+2

Nein, das ist der einzig richtige Weg. Warum willst du es trotzdem schließen? Verwenden Sie es einfach zum Abhören, wenn Sie es bereits gebunden haben - Sie können nicht wissen, ob es später noch verfügbar ist, da ein anderer Prozess in der Zwischenzeit an diesen Port gebunden sein könnte. – ThiefMaster

+0

@ wong2: Lesen Sie meine Antwort. Es gibt keine Möglichkeit, die Antwort auf Ihre Frage zu ermitteln ("Wird der Port bereits verwendet?"), Ohne dass es möglicherweise falsch ist, es sei denn, Sie binden den Port und halten ihn gebunden, bis Sie ihn verwenden können. Im Voraus zu überprüfen (und dann freizugeben) unterliegt falschen Antworten. –

0

Ein anderer Ansatz: Versuchen Sie, eine Verbindung zu diesem Port unter localhost herzustellen.

+1

Fügen Sie einige der Gründe, dass es eine schlechte Idee ist und Möglichkeiten, dass dieser Test fehlschlagen könnte, und Ihre Antwort könnte sich lohnen ... –

+1

a) der laufende Server kann eine bestimmte Schnittstelle hören, und die Verbindung zu 'localhost' wird es nicht überprüfen ; b) Zeitüberschreitungen; c) Ich habe diese Methode verwendet, um den Port zu überprüfen, um einen TCP-Server als separaten Prozess zu starten (es gab keine korrekten Fehlercodes bei Fehlern zurück, so dass dies der einzige Weg war, dies zu überprüfen). – khachik

+0

Übrigens, (a) ist ein Problem, selbst wenn Sie atomar testen, indem Sie den Port binden. Selbst wenn es Ihnen gelingt, eine Verbindung in 0.0.0.0: port herzustellen, hat möglicherweise ein anderer Prozess aaa.bbb.ccc.ddd: port (die IP der externen Netzwerkadresse) bereits gebunden. –

0

Erstellen Sie einfach einen Socket und rufen Sie bind() auf. Wenn bind() Erfolg, dann weiter zu listen(), andernfalls sollten Sie einige Fehlerbehandlungsprozedur durchführen, wie zum Beispiel zu einem Standard-Port wechseln, Fehlermeldung ausgeben und auf Benutzerinteraktion warten oder zumindest loggen und beenden.

Verwandte Themen