Windows Sockets: Wie Sockets mit Archiven arbeiten

In diesem Artikel wird erläutert, wie ein CSocket-Objekt , ein CSocketFile-Objekt und ein CArchive-Objekt kombiniert werden, um das Senden und Empfangen von Daten über einen Windows Socket zu vereinfachen.

Der Artikel Windows Sockets: Beispiel für Sockets Using Archives stellt die PacketSerialize Funktion dar. Das Archivobjekt im PacketSerialize Beispiel funktioniert ähnlich wie ein Archivobjekt, das an eine MFC Serialize-Funktion übergeben wird. Der wesentliche Unterschied besteht darin, dass das Archiv für Sockets nicht an ein standardmäßiges CFile-Objekt (in der Regel einer Datenträgerdatei zugeordnet) sondern an ein CSocketFile Objekt angefügt wird. Anstatt eine Verbindung mit einer Datenträgerdatei herzustellen, stellt das CSocketFile Objekt eine Verbindung mit einem CSocket Objekt her.

Ein CArchive Objekt verwaltet einen Puffer. Wenn der Puffer eines speicherenden (sendenden) Archivs voll ist, schreibt ein zugeordnetes CFile Objekt den Inhalt des Puffers aus. Das Leeren des Puffers eines an einen Socket angefügten Archivs entspricht dem Senden einer Nachricht. Wenn der Puffer eines Ladearchivs (Empfangen) voll ist, wird das CFile Objekt nicht mehr gelesen, bis der Puffer wieder verfügbar ist.

Die Klasse CSocketFile wird von CFile, unterstützt jedoch keine CFile-Memberfunktionen wie die Positionierungsfunktionen (Seek, GetLength, SetLengthusw.), die Sperrfunktionen (LockRange, UnlockRange) oder die GetPosition Funktion. Das gesamte CSocketFile-Objekt muss Schreib- oder Lesesequenzen von Bytes in oder aus dem zugeordneten CSocket Objekt ausführen. Da eine Datei nicht beteiligt ist, sind Vorgänge wie Seek z. B. nicht GetPosition sinnvoll. CSocketFile wird von CFileabgeleitet, sodass sie normalerweise alle diese Memberfunktionen erben würde. Um dies zu verhindern, werden die nicht unterstützten CFile Memberfunktionen überschrieben CSocketFile , um eine CNotSupportedException auszuwerfen.

Das CSocketFile Objekt ruft Memberfunktionen des CSocket Objekts auf, um Daten zu senden oder zu empfangen.

Die folgende Abbildung zeigt die Beziehungen zwischen diesen Objekten auf beiden Seiten der Kommunikation.

CArchive, CSocketFile, and CSocket.
CArchive, CSocketFile und CSocket

Der Zweck dieser scheinbaren Komplexität besteht darin, Sie vor der Notwendigkeit zu schützen, die Details des Sockets selbst zu verwalten. Sie erstellen den Socket, die Datei und das Archiv, und beginnen dann mit dem Senden oder Empfangen von Daten, indem Sie ihn in das Archiv einfügen oder aus dem Archiv extrahieren. CArchive, CSocketFile und CSocket verwalten die Details hinter den Kulissen.

Ein CSocket Objekt ist tatsächlich ein Zwei-Zustands-Objekt: manchmal asynchron (der übliche Zustand) und manchmal synchron. In seinem asynchronen Zustand kann ein Socket asynchrone Benachrichtigungen vom Framework empfangen. Während eines Vorgangs wie dem Empfangen oder Senden von Daten wird der Socket jedoch synchron. Dies bedeutet, dass der Socket keine weiteren asynchronen Benachrichtigungen empfängt, bis der synchrone Vorgang abgeschlossen ist. Da sie Modi wechselt, können Sie z. B. wie folgt vorgehen:

void CMySocket::OnReceive(int nErrorCode)
{
   if (0 == nErrorCode)
   {
      CSocketFile file(this);
      CArchive ar(&file, CArchive::load);
      CString str;

      ar >> str;
   }
}

Wenn CSocket sie nicht als Zwei-Zustands-Objekt implementiert wurden, kann es möglich sein, zusätzliche Benachrichtigungen für dieselbe Art von Ereignis zu erhalten, während Sie eine vorherige Benachrichtigung verarbeiten. Sie können z. B. beim Verarbeiten einer Benachrichtigung eine OnReceive OnReceiveBenachrichtigung erhalten. Im obigen Codefragment kann das Extrahieren str aus dem Archiv zu Rekursionen führen. Durch das Wechseln von Zuständen wird eine Rekursion verhindert, CSocket indem zusätzliche Benachrichtigungen verhindert werden. Die allgemeine Regel ist keine Benachrichtigungen innerhalb von Benachrichtigungen.

Hinweis

A CSocketFile kann auch als (eingeschränkte) Datei ohne Objekt CArchive verwendet werden. Standardmäßig ist der bArchiveCompatible-Parameter des CSocketFile Konstruktors TRUE. Dadurch wird angegeben, dass das Dateiobjekt für ein Archiv verwendet werden soll. Um das Dateiobjekt ohne Archiv zu verwenden, übergeben Sie FALSE im bArchiveCompatible-Parameter .

Im Modus "archivkompatibel" bietet ein CSocketFile Objekt eine bessere Leistung und reduziert die Gefahr eines "Deadlocks". Ein Deadlock tritt auf, wenn sowohl die sende- als auch die empfangenden Sockets aufeinander warten oder auf eine gemeinsame Ressource warten. Diese Situation kann auftreten, wenn das CArchive Objekt mit der CSocketFile Funktionsweise eines CFile Objekts gearbeitet hat. Mit CFiledem Archiv kann davon ausgegangen werden, dass das Ende der Datei erreicht wurde, wenn es weniger Bytes als angefordert empfängt. Bei CSocketFileDaten handelt es sich jedoch um nachrichtenbasierte Daten. Der Puffer kann mehrere Nachrichten enthalten, sodass der Empfang weniger als die anzahl der angeforderten Bytes nicht das Ende der Datei bedeutet. Die Anwendung wird in diesem Fall nicht blockiert, wie dies möglich CFileist, und sie kann mit dem Lesen von Nachrichten aus dem Puffer fortfahren, bis der Puffer leer ist. Die IsBufferEmpty-Funktion CArchive ist nützlich, um den Zustand des Archivpuffers in einem solchen Fall zu überwachen.

Weitere Informationen finden Sie unter Windows Sockets: Verwenden von Sockets mit Archiven

Siehe auch

Windows-Sockets in MFC
CObject::Serialize