2017-03-28 7 views
2

Ich bemerkte etwas seltsam bei der Arbeit mit einem einfachen C-basierten Server Programm auf meinem Linux (4.10.3) -System. Ich habe versehentlich am Telefon listen() zweimal auf einem Socket (aus dem Server-Prozess) genannt bind() auf früher aufgerufen. Mir ist aufgefallen, dass die beiden Listen ohne Fehler abgehört haben. In der Tat scheint es egal zu sein, wie viele Anrufe zu hören ich mache, alle Anrufe zu hören, gelingen.hören angerufen Socket mehr als einmal - erwartetes Verhalten?

Ich erwartete alle Anrufe zu hören, nachdem die erste fehlgeschlagen mit EADDRINUSE. Fehle ich etwas? Linux/POSIX man pages nicht scheinen dazu etwas zu sagen. Ich habe einen Hinweis über dieses Verhalten auf der folgenden Web-Seite finden:

https://www.mkssoftware.com/docs/man3/listen.3.asp

Eine Anwendung kann mithören() mehr als einmal auf dem gleichen Sockel. Dadurch wird der aktuelle Rückstand für den abhörenden Socket aktualisiert. Sollten mehr Verbindungen als der neue Backlog-Wert vorhanden sein, werden die überschüssigen ausstehenden Verbindungen zurückgesetzt und gelöscht.

Es ist mir unklar, ob dies auch für Linux gilt. Und so ist meine Frage: was passiert, wenn auf dieselbe Buchse mehr als einmal von der gleiche Prozess aufgerufen wird? (Anscheinend gibt es keine sichtbaren Nebenwirkungen im Benutzerraum, aber tut der Linuxkernel etwas spezielles im Kernraum?)

Thanks.

+0

Die [POSIX-Spezifikation für 'hören'] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html), wie ich es lese, gibt das Verhalten für diesen Fall nicht an, was bedeutet Portabler Code sollte dies vermeiden. – zwol

+0

Ich würde EADDRINUSE nicht erwarten. Das würde beim vorhergehenden 'bind()' Schritt passieren. Vielleicht EINVAL. – EJP

+0

@zwol: Sie haben Recht, ein tragbares Programm sollte es vermeiden. Ich war nur neugierig, was der Linux-Kernel macht. – userRG

Antwort

2

Der Linux-Kernel passt die Länge der Backlog-Warteschlange mit dem neuen Backlog-Wert an, jedoch nur für zukünftige Verbindungsanforderungen. Es verwirft keine ausstehenden Verbindungen, die sich bereits in der Warteschlange befinden.

Zweite und nachfolgende Aufrufe listen() haben keine andere Wirkung, und werden nicht fehlschlagen, wenn der Socket vom falschen Typ ist (nicht SOCK_STREAM) oder im falschen Zustand (bereits zu einem bestimmten Peer verbunden, oder ist bereits in der Prozess des Schließens).

+0

Danke, @Gil, das scheint die wahrscheinlichste Erklärung zu sein. Ich versuche, dies durch den Kernel zu verfolgen. – userRG