Zum Hauptinhalt springen

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.

© 2020 Stratus Technologies.