共用方式為


Windows Sockets:套接字與檔案封存的運作方式

本文說明如何結合 CSocket 物件、CSocketFile 物件和 CArchive 物件,以簡化透過 Windows Socket 傳送和接收數據的方式。

Windows Sockets:使用封存的套接字範例介紹了PacketSerialize函式。 此範例中的 PacketSerialize 封存對象的運作方式非常類似傳遞至 MFC Serialize 函式的封存物件。 基本差異在於,對於套接字而言,封存不會附加至標準 CFile 物件(通常與磁碟檔案相關聯),而是附加至 CSocketFile 物件。 CSocketFile 物件不是連線到磁碟檔案,而是連線到 CSocket 物件。

CArchive物件會管理緩衝區。 當儲存(傳送)封存的緩衝區已滿時,相關聯的 CFile 物件會寫出緩衝區的內容。 清除附加於套接字的存檔緩衝區相當於發送一則訊息。 當載入(接收) 封存的緩衝區已滿時, CFile 物件會停止讀取,直到緩衝區再次可用為止。

類別CSocketFile衍生自 CFile,但不支援 CFile 成員函式,例如定位函式 (、SeekGetLength等等)、鎖定函式 (SetLengthLockRangeUnlockRangeGetPosition 函式。 所有 CSocketFile 物件都必須寫入或讀取相關聯 CSocket 物件的位元組序列。 因為檔案未涉及,因此這類SeekGetPosition作業並無意義。 CSocketFile 衍生自 CFile,因此通常會繼承所有這些成員函式。 若要避免這種情況,系統會覆CFile寫不支持CSocketFile的成員函式,以擲回 CNotSupportedException

物件 CSocketFile 會呼叫其 CSocket 對象的成員函式來傳送或接收數據。

下圖顯示通訊兩端這些對象之間的關聯性。

CArchive、CSocketFile 和 CSocket。
CArchive、CSocketFile 和 CSocket

這種明顯的複雜性的目的是讓您不必自行管理套接字的細節。 您可以建立套接字、檔案和封存,然後藉由將數據插入封存或從封存擷取來開始傳送或接收數據。 CArchiveCSocketFileCSocket 會管理幕後的詳細數據。

對象 CSocket 實際上是兩種狀態對象:有時是異步的(一般狀態),有時是同步的。 在其異步狀態中,套接字可以從架構接收異步通知。 不過,在接收或傳送數據等作業期間,套接字會轉為同步。 這表示在同步操作完成之前,套接字不會再收到任何非同步通知。 因為它切換模式,例如,您可以執行類似下列動作:

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

      ar >> str;
   }
}

如果未 CSocket 實作為雙狀態物件,則在處理先前的通知時,可能會收到相同事件類型的其他通知。 例如,您可能會在 OnReceive 處理 OnReceive時收到通知。 在上述代碼段中,從封存擷取 str 可能會導致遞歸。 藉由切換狀態, CSocket 藉由防止其他通知來防止遞歸。 一般規則是通知裡不再有通知。

備註

CSocketFile也可以當做沒有 CArchive 物件的 (有限) 檔案使用。 根據預設,建 CSocketFile 構函式的 bArchiveCompatible 參數為 TRUE。 這會指定檔案對象用於封存。 若要使用不含封存的檔案物件,請在 bArchiveCompatible 參數中傳遞 FALSE

在其「封存相容」模式中, CSocketFile 物件可提供更佳的效能,並減少「死結」的危險。當傳送和接收套接字彼此等候或等候一般資源時,就會發生死結。 如果 CArchive 物件像對待 CSocketFile 物件一樣處理 CFile 物件,就可能發生這種情況。 使用 CFile 時,存檔程式可以假設,如果收到的位元組少於所要求的數量,則已到達文件結尾。 不過,使用 CSocketFile時,數據是以訊息為基礎;緩衝區可以包含多個訊息,因此接收的位元組數目少於要求的位元組數目,並不表示檔案結尾。 在此情況下,應用程式不會封鎖,如同使用CFile時會發生的情況,而且它可以繼續從緩衝區讀取訊息,直到緩衝區清空。 中的 CArchive函式有助於監視封存緩衝區在這類情況下的狀態。

如需詳細資訊,請參閱 Windows 套接字:使用套接字與存檔

另請參閱

MFC 中的 Windows 套接字
CObject::Serialize