Vor etwa 18 Monaten schrieb ich einen Blog, in dem ich über Änderungen in der Funktionsweise von accept in OpenVOS Version 17.1 sprach. Dabei habe ich vergessen, darauf hinzuweisen, dass diese Änderungen nur wirksam werden, wenn der Anwendungscode POSIX-basiert ist. Um es noch einmal zusammenzufassen: Vor 17.1 antwortete STCP nur auf eine Client-Verbindungsanfrage, wenn der Server-Anwendungscode die accept-Routine aufgerufen hatte. Wenn der Code accept nicht aufgerufen hatte, wurde die Verbindungsanforderung des Clients in eine Warteschlange gestellt, aber nicht beantwortet. Sobald die Anwendung accept aufgerufen hat, sendet STCP eine Verbindungsantwort. Wenn der Client noch wartet, wird die Verbindung zu diesem Zeitpunkt beendet. Hätte der Client bereits aufgegeben, würde er auf die Verbindungsantwort mit einem Reset reagieren, STCP würde die Verbindung wegwerfen und accept würde hängen bleiben (unter der Annahme eines blockierenden Modus) und auf eine andere Verbindung warten.
Abbildung 1 zeigt dieses Szenario; die linksbündigen Textzeilen sind Statusmeldungen der Serveranwendung, die eingerückten packet_monitor-Zeilen (leicht verändert) sind das Ergebnis der Client-Aktivität. Die Anwendung (acceptTestnoPosix) wird gestartet, lauscht auf Port 12345 und geht nach dem Lauschen für 300 Sekunden in den Ruhezustand. Der Client stellt dann eine Verbindung zu Port 12345 her, indem er ein TCP-Segment mit gesetztem Syn (S)-Flag an Port 12345 sendet. Er versucht es dreimal, bevor er aufgibt. Nach 300 Sekunden wacht die Anwendung auf und ruft accept auf. Der STCP-Stack antwortet dem Client mit einem TCP-Segment, bei dem die Flaggen Syn und Ack (SA) gesetzt sind. Da der Client keine Aufzeichnung der Verbindung mehr hat, wenn er ein Reset (R) sendet, blockiert STCP an diesem Punkt. Wäre der Socket im Non-Blocking-Modus, hätte accept mit einem EAGAIN-Fehler geantwortet.
acceptTestnoPosix 12345 Ausführen von acceptTestnoPosix 12345 Schläft für 300 Sekunden 11:04:45.923 R TCP 164.152.77.50 164.152.77.217 11071 12345 S 11:04:48.925 R TCP 164.152.77.50 164.152.77.217 11071 12345 S 11:04:54.937 R TCP 164.152.77.50 164.152.77.217 11071 12345 S Bereit zur Annahme einer Verbindung über Portnummer 12345 11:09:41.852 T TCP 164.152.77.217 164.152.77.50 12345 11071 SA 11:09:41.854 R TCP 164.152.77.50 164.152.77.217 11071 12345 R |
Abbildung 1 - Akzeptanz vor 17.1 oder nicht-POSIX nach 17.1
Ist die Anwendung POSIX-basiert, liegen die Dinge anders (Abbildung 2). STCP antwortet sofort auf die Verbindungsanfrage (S) (SA). Dann wacht die Anwendung nach 300 Sekunden auf, ruft accept auf und STCP gibt den akzeptierten Socket zurück.
acceptTestmitPosix 12345 Ausführen von acceptTestnoPosix 12345 Schlafend für 300 Sekunden 10:58:43.962 R TCP 164.152.77.50 164.152.77.217 11024 12345 S 10:58:43.964 T TCP 164.152.77.217 164.152.77.50 12345 11024 SA 10:58:43.964 R TCP 164.152.77.50 164.152.77.217 11024 12345 A Bereit zur Annahme einer Verbindung über Portnummer 12345 Verbindung angenommen |
Abbildung 2 - POSIX-basierte Post 17.1 akzeptieren
Der Unterschied im Verhalten kann kritisch sein. Wenn der Client nach dem Verbindungsaufbau eine Antwort von der Serveranwendung erwartet, kann es zu einer Zeitüberschreitung und zum Schließen der Verbindung kommen, bevor die Anwendung tatsächlich accept aufruft.
Wie erstellt man eine Anwendung mit POSIX? Zuerst die Zeile
#define _POSIX_C_SOURCE 200112L |
sollte die erste Zeile des Quelltextes der Anwendung sein. Zweitens der Bibliothekspfad
(master_disk)>system>posix_object_library
muss in den Pfaden der Objektbibliotheken nach den STCP-Bibliotheken und vor der C-Bibliothek liegen.
Wie können Sie feststellen, ob dies geschehen ist? Sie können sich die Objektbibliotheken ansehen, mit denen die Anwendung gebunden wurde, indem Sie den Befehl display_program_module -object_dirs verwenden
display_program_module acceptTestwithPosix -object_dirs
%azvos#m17_mas>SysAdmin>Noah_Davids>temp>acceptTestmitPosix.pm
Objektverzeichnis-Map:
11 Suchverzeichnisse
0 Nicht-Suchverzeichnisse
11 Verzeichnisse insgesamt
DTC-Verzeichnispfad
1 %azvos#m17_mas>SysAdmin>Noah_Davids>temp
2 %azvos#m17_mas>System>stcp>Objekt_Bibliothek
3 %azvos#m17_mas>System>stcp>Objekt_Bibliothek>Socket
4 %azvos#m17_mas>System>stcp>Objekt_Bibliothek>Netz
5 %azvos#m17_mas>system>stcp>objekt_bibliothek>gemeinsam
6 %azvos#m17_mas>System>posix_Objekt_Bibliothek
7 %azvos#m17_mas>System>c_Objekt_Bibliothek
8 %azvos#m17_mas>System>Objekt_Bibliothek
9 %azvos#m17_mas>opt>apache>lib
10 %azvos#m17_mas>opt>openssl>Bibliothek
11 %azvos#m17_mas>opt>mysql>lib>mysql
|
Das sagt aber nichts darüber aus, ob die #define Teil des Quellcodes ist.
Wenn Sie den Code ausführen können, können Sie sich die Socket-Flags ansehen. Bei einem POSIX-basierten Programm ist das Socket-Flag SF_POSIX gesetzt. Ich habe zum Beispiel drei Programme: acceptTestnoPosix, acceptTestwithPosix und acceptTestwithPosixPathOnly. Das letztgenannte Programm hatte das Verzeichnis >system>posix_object_library in den Bibliothekspfaden, aber die #define nicht in den Quellcode aufgenommen. Beachten Sie, dass dies eine ungültige Kombination ist. Nur die Anwendung, die mit der POSIX-Bibliothek verbunden war und die #define-Anweisung POSIX_SOURCE im Code hatte, erzeugte einen Socket mit dem SF_POSIX-Flag.
acceptTestnoPosix.pm 12345 Ausführen von acceptTestnoPosix 12345 Schläft für 300 Sekunden as: match posix; dump_stcbq -full -lport 12345 as: |
acceptTestmitPosix.pm 12345
Ausführen von acceptTestnoPosix 12345
Schläft für 300 Sekunden
as: match posix; dump_stcbq -full -lport 12345
SF_POSIX
as:
|
acceptTestmitPosixPfadNur.pm 12345 Ausführen von acceptTestnoPosix 12345 Schlafen für 300 Sekunden as: match posix; dump_stcbq -full -lport 12345 as: |
Es gibt noch eine vierte Möglichkeit: Die #define wurde in den Quellcode aufgenommen, aber die posix_object_library wurde nicht verwendet. In diesem Fall wird die Socket-Routine einen Fehler zurückgeben.
acceptTestmitPosixDefineNur 12345 Ausführen von acceptTestnoPosix 12345 acceptTestnoPosix: kann keinen abhörenden Socket erstellen: Anwendung gebaut + falsch: POSIX-Laufzeit muss vor der C-Laufzeit durchsucht werden. |
Alle STCP-Befehle und -Hilfsprogramme basieren auf POSIX, und ich empfehle dringend, dass alle von Ihnen erstellten Anwendungen ebenfalls POSIX verwenden.