Windows Sockets:如何搭配使用通訊端與封存
本文說明 如何結合 CSocket 物件、 CSocketFile 物件和 CArchive 物件,以簡化透過 Windows Socket 傳送和接收資料的方式。
Windows Sockets:使用封存 的通訊端範例提供函 PacketSerialize
式。 此範例中的 PacketSerialize
封存物件的運作方式非常類似傳遞至 MFC Serialize 函式的封存 物件。 基本差異在於,對於通訊端而言,封存不會附加至標準 CFile 物件(通常與磁片檔案相關聯),而是附加至 CSocketFile
物件。 物件不是連線到磁片檔案,而是 CSocketFile
連接到 CSocket
物件。
CArchive
物件會管理緩衝區。 當儲存(傳送)封存的緩衝區已滿時,相關聯的 CFile
物件會寫出緩衝區的內容。 清除附加至通訊端之封存的緩衝區相當於傳送訊息。 當載入(接收) 封存的緩衝區已滿時, CFile
物件會停止讀取,直到緩衝區再次可用為止。
類別 CSocketFile
衍生自 CFile
,但不支援 CFile 成員函式,例如定位函式 (、 GetLength
、 SetLength
等等)、鎖定函式 ( Seek
LockRange
、 UnlockRange
或 GetPosition
函式。 所有 CSocketFile 物件都必須寫入或讀取相關聯 CSocket
物件的位元組序列。 因為檔案未涉及,因此這類 Seek
GetPosition
作業並無意義。 CSocketFile
衍生自 CFile
,因此通常會繼承所有這些成員函式。 若要避免這種情況,系統會覆寫不支援 CFile
的成員函式,以擲回 CNotSupportedException 。 CSocketFile
物件 CSocketFile
會呼叫其 CSocket
物件的成員函式來傳送或接收資料。
下圖顯示通訊兩端這些物件之間的關聯性。
CArchive、CSocketFile 和 CSocket
這種明顯的複雜性的目的是要保護您不要自行管理通訊端的詳細資料。 您可以建立通訊端、檔案和封存,然後藉由將資料插入封存或從封存擷取來開始傳送或接收資料。 CArchive 、 CSocketFile 和 CSocket 會管理幕後的詳細資料。
物件 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
IsBufferEmpty 函式有助於監視封存緩衝區在這類情況下的狀態。
如需詳細資訊,請參閱 Windows 通訊端:搭配封存使用通訊端