mit mehreren io_service-Objekten

8

Ich habe meine Anwendung, in der Nachrichten sowohl von Internet-Sockets als auch von Unix-Domain-Sockets gehört und verarbeitet werden. Jetzt muss ich SSL zu den Internet-Sockets hinzufügen, ich habe ein einzelnes Objekt io_service für alle Sockets in der Anwendung verwendet. Es scheint jetzt, ich muss separate io_service Objekte für Netzwerk-Sockets und Unix-Domain-Sockets hinzufügen. Ich habe keine Threads in meiner Anwendung und verwende async_send und async_recieve und async_accept , um Daten und Verbindungen zu verarbeiten. Bitte zeigen Sie mir Beispiele, die mehrere io_service -Objekte mit asynchronen Handlern verwenden.

    
Ravikumar Tulugu 19.03.2013, 10:28
quelle

2 Antworten

26

Die Frage hat einen Grad an Unsicherheit, als ob mehrere io_service Objekte benötigt werden. Ich konnte nichts in der Referenz Dokumentation oder der Übersicht für finden SSL und UNIX-Domänen-Sockets , die separate io_service -Objekte verordneten. Unabhängig davon, hier sind ein paar Optionen:

Einzel io_service :

Versuchen Sie, ein einzelnes io_service zu verwenden.

Wenn Sie kein direktes Handle für das Objekt io_service haben, aber ein Handle für ein Boost.Asio-E / A-Objekt (z. B. einen Socket) haben, kann ein Handle für das verknüpfte io_service -Objekt sein erhalten durch Aufruf von socket.get_io_service() .

Benutze einen Thread pro io_service :

Wenn mehrere io_service -Objekte erforderlich sind, dedizieren Sie jedem io_service einen Thread. Dieser Ansatz wird in Boost.Asios HTTP Server 2 verwendet Beispiel.

%Vor%

Eine Konsequenz dieses Ansatzes ist, dass die Anwendung möglicherweise Thread-Sicherheitsgarantien erfordert. Wenn beispielsweise service1 und service2 beide Completion-Handler haben, die message_processor.process() aufrufen, muss message_processor.process() entweder Thread-sicher sein oder threadsicher aufgerufen werden.

Umfrage io_service :

io_service bietet blockierungsfreie Alternativen zu %Code%. Wo als run() wird bis blockiert Alle Arbeiten sind abgeschlossen, io_service::run() führt Handler aus, die zur Ausführung bereit sind und nicht blockieren. Dadurch kann ein einzelner Thread die Ereignisschleife für mehrere io_service::poll() -Objekte ausführen:

%Vor%

Um eine Tight-Busy-Schleife zu verhindern, wenn keine Handler bereit sind, kann es sinnvoll sein, sie im Ruhezustand hinzuzufügen. Beachten Sie, dass dieser Schlaf eine Latenz bei der Gesamtbehandlung von Ereignissen verursachen kann.

Übergeben Sie Handler an ein einzelnes io_service :

Ein interessanter Ansatz ist die Verwendung eines io_service um Vervollständigungshandler auf ein einzelnes strand zu übertragen. Dies ermöglicht einen Thread pro io_service und verhindert gleichzeitig, dass die Anwendung Thread-Sicherheitsgarantien machen muss, da alle Completion-Handler über einen einzigen Dienst posten, dessen Ereignisschleife nur von einem einzelnen Thread verarbeitet wird.

> %Vor%

Dieser Ansatz hat einige Konsequenzen:

  • Es erfordert, dass Handler, die von der Haupt- io_service ausgeführt werden sollen, über io_service .
  • Die asynchrone Kette durchläuft nun zwei strand::wrap() s, wodurch eine zusätzliche Komplexitätsebene entsteht. Es ist wichtig, den Fall zu berücksichtigen, in dem die sekundäre io_service keine Arbeit mehr hat und ihre io_service zurückgibt.

Es kommt häufig vor, dass asynchrone Ketten innerhalb desselben run() auftreten. Daher ist der Dienst nie arbeitslos, da ein Completion-Handler zusätzliche Arbeit auf dem io_service veröffentlichen wird.

%Vor%

Wenn andererseits ein Strang verwendet wird, um Arbeit an ein anderes io_service zu übergeben, wird der umhüllte Handler innerhalb von io_service aufgerufen, was dazu führt, dass er den Beendigungshandler in service2 setzt. Wenn der umhüllte Handler die einzige Arbeit in service1 war, dann hat service2 keine Arbeit mehr und bewirkt, dass service2 zurückkehrt.

%Vor%

Um dies zu berücksichtigen, verwendet der Beispielcode eine servce2.run() für io_service::work , so dass service2 so lange blockiert bleibt, bis run() .

    
Tanner Sansbury 19.03.2013, 17:59
quelle
1

Sieht so aus, als ob Sie einen Server und keinen Client schreiben. Ich weiß nicht, ob das hilft, aber ich verwende ASIO, um mit 6 Servern von meinem Client zu kommunizieren. Es verwendet TCP / IP SSL / TSL. Sie finden einen Link zum Code hier

Sie sollten nur ein io_service-Objekt mit mehreren Socket-Objekten verwenden können. Wenn Sie jedoch entscheiden, dass Sie mehrere io_service-Objekte wirklich haben möchten, sollte es ziemlich einfach sein. In meiner Klasse ist das io_service-Objekt statisch. Entfernen Sie einfach das Schlüsselwort static zusammen mit der Logik im Konstruktor, die nur eine Instanz des io_service-Objekts erstellt. Abhängig von der Anzahl der Verbindungen, die für Ihren Server erwartet werden, wäre es wahrscheinlich besser, einen Thread-Pool zu verwenden, der für die Verarbeitung von Socket-E / A zuständig ist, anstatt für jede neue Socket-Verbindung einen Thread zu erstellen.

    
Bob Bryan 19.03.2013 16:13
quelle

Tags und Links