Dela via


Windows Sockets: Så här fungerar socketar med arkiv

Den här artikeln förklarar hur ett CSocket-objekt , ett CSocketFile-objekt och ett CArchive-objekt kombineras för att förenkla sändning och mottagning av data via en Windows Socket.

I artikeln Windows Sockets: Exempel på sockets som använder arkiv presenteras PacketSerialize funktionen. Arkivobjektet i PacketSerialize exemplet fungerar ungefär som ett arkivobjekt som skickas till en MFC Serialize-funktion . Den viktigaste skillnaden är att arkivet för sockets inte är kopplat till ett CFile-standardobjekt (vanligtvis associerat med en diskfil) utan till ett CSocketFile objekt. I stället för att ansluta till en diskfil CSocketFile ansluter objektet till ett CSocket objekt.

Ett CArchive objekt hanterar en buffert. När bufferten i ett arkiv för lagring (sändning) är full skriver ett associerat CFile objekt ut buffertens innehåll. Att rensa bufferten för ett arkiv som är kopplat till en socket motsvarar att skicka ett meddelande. När bufferten för ett inläsningsarkiv (mottagande) är full CFile slutar objektet att läsa tills bufferten är tillgänglig igen.

Klassen CSocketFile härleds från CFile, men den stöder inte CFile-medlemsfunktioner , till exempel positioneringsfunktionerna (Seek, GetLength, SetLengthoch så vidare), låsningsfunktionerna (LockRange, UnlockRange) eller GetPosition funktionen. Allt CSocketFile-objektet måste göra är att skriva eller läsa sekvenser med byte till eller från det associerade CSocket objektet. Eftersom en fil inte är involverad är åtgärder som Seek och GetPosition inte meningsfulla. CSocketFile härleds från CFile, så det ärver normalt alla dessa medlemsfunktioner. För att undvika detta åsidosätts de medlemsfunktionerna i CFile och CSocketFile som inte stöds, för att utlösa en CNotSupportedException.

Objektet CSocketFile anropar medlemsfunktioner i objektet CSocket för att skicka eller ta emot data.

Följande bild visar relationerna mellan dessa objekt på båda sidor av kommunikationen.

CArchive, CSocketFile och CSocket.
CArchive, CSocketFile och CSocket

Syftet med denna uppenbara komplexitet är att skydda dig från nödvändigheten av att hantera detaljerna i socketen själv. Du skapar socketen, filen och arkivet och börjar sedan skicka eller ta emot data genom att infoga dem i arkivet eller extrahera dem från arkivet. CArchive, CSocketFile och CSocket hanterar informationen i bakgrunden.

Ett CSocket objekt är faktiskt ett tvåtillståndsobjekt: ibland asynkront (det vanliga tillståndet) och ibland synkront. I sitt asynkrona tillstånd kan en socket ta emot asynkrona meddelanden från ramverket. Men under en åtgärd som att ta emot eller skicka data blir socketen synkron. Det innebär att socketen inte får några ytterligare asynkrona meddelanden förrän den synkrona åtgärden har slutförts. Eftersom den växlar lägen kan du till exempel göra något som liknar följande:

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

      ar >> str;
   }
}

Om CSocket inte implementerades som ett tvåtillståndsobjekt skulle det kunna vara möjligt att ta emot ytterligare aviseringar för samma typ av händelse medan du behandlar en tidigare avisering. Du kan till exempel få ett OnReceive meddelande när du bearbetar en OnReceive. I kodfragmentet ovan kan extrahering str från arkivet leda till rekursion. Genom att växla tillstånd CSocket förhindrar du rekursion genom att förhindra ytterligare meddelanden. Den allmänna regeln är inga meddelanden inom meddelanden.

Anmärkning

En CSocketFile kan också användas som en (begränsad) fil utan ett CArchive objekt. Som standard är konstruktorns CSocketFileTRUE. Detta anger att filobjektet ska användas med ett arkiv. Om du vill använda filobjektet utan arkiv skickar du FALSE i parametern bArchiveCompatible .

I sitt "arkivkompatibla" läge ger ett CSocketFile objekt bättre prestanda och minskar risken för ett "dödläge". Ett dödläge uppstår när både de sändande och mottagande socketarna väntar på varandra eller väntar på en gemensam resurs. Den här situationen kan inträffa om CArchive objektet fungerar som CSocketFile det gör med ett CFile objekt. Med CFilekan arkivet anta att om det tar emot färre byte än det begärde har filslutet nåtts. Med CSocketFileär dock data meddelandebaserade, bufferten kan innehålla flera meddelanden, så att ta emot färre än antalet begärda byte innebär inte filslut. Programmet blockerar inte i det här fallet som det kan med CFile, och det kan fortsätta att läsa meddelanden från bufferten tills bufferten är tom. Funktionen IsBufferEmpty i CArchive är användbar för att övervaka tillståndet för arkivets buffert i ett sådant fall.

Mer information finns i Windows Sockets: Using Sockets with Archives (Använda socketar med arkiv)

Se även

Windows Sockets i MFC
CObject::Serialize