16 Stimmen

Ablehnen einer TCP-Verbindung, bevor sie angenommen wird?

Es gibt 3 verschiedene accept Versionen in Winsock. Abgesehen von den grundlegenden accept die für die Einhaltung von Standards vorgesehen ist, gibt es auch AcceptEx welche die fortschrittlichste Version zu sein scheint (aufgrund der überlappenden io-Fähigkeiten), und WSAAccept . Letztere unterstützt einen Bedingungs-Callback, der, soweit ich das verstehe, die Ablehnung von Verbindungsanfragen ermöglicht, bevor sie akzeptiert werden (wenn die SO_CONDITIONAL_ACCEPT Option aktiviert ist). Keine der anderen Versionen unterstützt diese Funktion.

Da ich es vorziehe, die AcceptEx mit überlappenden io, frage ich mich, warum diese Funktion nur in der einfacheren Version verfügbar ist?

Ich weiß nicht genug über das Innenleben von TCP, um sagen zu können, ob es tatsächlich einen Unterschied gibt zwischen dem Zurückweisen einer Verbindung, bevor sie angenommen wurde, und dem Trennen eines Sockets direkt nach dem Aufbau einer Verbindung? Und wenn ja, gibt es eine Möglichkeit, den Vorgang zu imitieren? WSAAccept Funktionalität mit AcceptEx ?

Kann jemand etwas Licht in diese Angelegenheit bringen?

23voto

Nakedible Punkte 3907

Wenn eine Verbindung hergestellt ist, sendet die Gegenseite ein Paket mit dem SYN Flagge gesetzt. Der Server antwortet mit einer SYN,ACK Paket, und danach sendet die Gegenstelle ein ACK Paket, das bereits Daten enthalten kann.

Es gibt zwei Möglichkeiten, eine TCP-Verbindung zu unterbrechen. Die erste ist das Zurücksetzen der Verbindung - dies entspricht der üblichen Meldung "Verbindung verweigert", die man erhält, wenn man sich mit einem Anschluss verbindet, den niemand abhört. In diesem Fall wird die ursprüngliche SYN Paket wird beantwortet mit einer RST Paket, das die Verbindung sofort beendet und zustandslos ist. Wenn das SYN wird widersprochen, RST wird aus jedem empfangenen SYN Päckchen.

Die zweite besteht darin, die Verbindung zu schließen, sobald sie zustande gekommen ist. Auf TCP-Ebene gibt es keine Möglichkeit, die Verbindung in beide Richtungen sofort zu schließen - das Einzige, was man sagen kann, ist: "Ich werde keine Daten mehr senden". Dies geschieht so, dass, wenn die erste SYN , SYN,ACK , ACK Austausch beendet ist, sendet der Server eine FIN Paket an das entfernte Ende. In den meisten Fällen wird das andere Ende mit FIN Ich werde keine weiteren Daten mehr senden" veranlasst die andere Seite, die Verbindung ebenfalls zu beenden und ihre eigenen Daten zu senden. FIN Päckchen. Eine auf diese Weise beendete Verbindung unterscheidet sich nicht von einer normalen Verbindung, bei der aus irgendeinem Grund keine Daten gesendet wurden. Das bedeutet, dass die normale Zustandsverfolgung für TCP-Verbindungen und die verweilenden Schließzustände bestehen bleiben, genau wie bei normalen Verbindungen.

Auf der C-API-Seite sieht das ein wenig anders aus. Beim Aufruf von listen() auf einem Port, beginnt das Betriebssystem, Verbindungen auf diesem Port zu akzeptieren. Das bedeutet, dass es anfängt zu antworten SYN,ACK Pakete zu Verbindungen, unabhängig davon, ob der C-Code die accept() noch nicht. Auf der TCP-Seite macht es also keinen Unterschied, ob die Verbindung vor oder nach dem Akzeptieren geschlossen wird. Das einzige zusätzliche Problem ist, dass ein lauschender Socket einen Backlog hat, d.h. die Anzahl der nicht akzeptierten Verbindungen, die er warten lassen kann, bevor er anfängt zu sagen RST zum fernen Ende.

Unter Windows wird jedoch die SO_CONDITIONAL_ACCEPT Aufruf kann die Anwendung die Kontrolle über die Backlog-Warteschlange übernehmen. Dies bedeutet, dass der Server nicht antwortet alles zu einer SYN Paket, bis die Anwendung etwas mit der Verbindung macht. Das bedeutet, dass das Zurückweisen von Verbindungen auf dieser Ebene tatsächlich RST Pakete an das Netz, ohne einen Status zu erzeugen.

Wenn Sie also nicht die SO_CONDITIONAL_ACCEPT Funktionalität auf dem von Ihnen verwendeten Socket irgendwie aktiviert AcceptEx eingeschaltet ist, wird es im Netz anders angezeigt. Allerdings verwenden nicht viele Stellen die unmittelbare RST Funktionalität, so dass ich denke, dass die Voraussetzung dafür ein sehr spezielles System sein muss. Für die meisten üblichen Anwendungsfälle ist das Akzeptieren eines Sockets und das anschließende Schließen die normale Vorgehensweise.

2voto

jldupont Punkte 87330

Zur Windows-Seite kann ich mich nicht äußern, aber was TCP betrifft, Ablehnung eine Verbindung ist ein wenig anders als Trennen der Verbindung von ihm.

Zum einen, Trennen der Verbindung von einer Verbindung bedeutet, dass bereits mehr Ressourcen "verbraucht" wurden (z. B. der Status von Ports in Firewalls und Endpunkten, die Weiterleitungskapazität von Switches/Routern usw.), sowohl im Netz als auch in den Hosts. Ablehnung von eine Verbindung ist weniger ressourcenintensiv.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X