傳送和接收 PGM 資料
傳送和接收 PGM 資料類似于在任何通訊端上傳送或接收資料。 下列段落概述 PGM 的特定考慮。
傳送 PGM 資料
建立 PGM 傳送者會話之後,會使用各種 Windows 通訊端傳送函式來傳送資料:send、sendto、WSASend和WSASendTo。 因為 Windows Sockets 控制碼是檔案系統控制碼,所以 WriteFile 和 CRT 函式等其他函式也可以傳輸資料。 下列程式碼片段說明 PGM 傳送者作業:
LONG error;
//:
error = send (s, pSendBuffer, SendLength, 0);
if (error == SOCKET_ERROR)
{
fprintf (stderr, "send() failed: Error = %d\n",
WSAGetLastError());
}
使用訊息模式 (SOCK_RDM) 時,對傳送函式的每個呼叫都會產生不想要的離散訊息;應用程式可能會想要傳送 2 MB 的訊息,並有多個呼叫來 傳送。 在這種情況下,寄件者可以設定 RM_SET_MESSAGE_BOUNDARY 通訊端選項,以指出下列訊息的大小。
如果傳送視窗已滿,則除非視窗已進階,否則不接受來自應用程式的新傳送。 嘗試在非封鎖通訊端上傳送失敗,WSAEWOULDBLOCK;封鎖通訊端只會封鎖,直到視窗前進到可緩衝和傳送要求資料的點為止。 在重迭的 I/O 中,作業不會完成,直到視窗前進到足以容納新資料為止。
接收 PGM 資料
建立 PGM 接收者會話之後,就會使用各種 Windows 通訊端接收函式來接收資料:recv、recvrom、WSARecv 和 WSARecvFrom。 因為 Windows Sockets 控制碼也是檔案控制代碼, 所以 ReadFile 和 CRT 函式也可以用來接收 PGM 會話資料。 只要資料依序傳送,傳輸就會將資料轉送至接收者。 傳輸保證傳回的資料連續且沒有重複專案。 下列程式碼片段說明 PGM 接收作業:
LONG BytesRead;
//:
BytesRead = recv (sockR, pTestBuffer, MaxBufferSize, 0);
if (BytesRead == 0)
{
fprintf(stdout, "Session was terminated\n");
}
else if (BytesRead == SOCKET_ERROR)
{
fprintf(stderr, "recv() failed: Error = %d\n",
WSAGetLastError());
}
使用訊息模式 (SOCK_RDM) 時,傳輸會指出何時收到部分訊息,並出現 WSAEMSGSIZE 錯誤,或在從 WSARecv 和 WSARecvFrom 函式傳回時設定MSG_PARTIAL旗標。 當完整訊息的最後一個片段傳回用戶端時,不會指出錯誤或旗標。
當會話正常終止時,接收作業會因 WSAEDISCON 而失敗。 當傳輸中發生資料遺失時,PGM 會暫時緩衝過期的封包,並嘗試復原遺失的資料。 如果無法復原資料遺失,接收作業會因為 WSAECONNRESET 而失敗,而會話會終止。 會話可能會因為各種條件而重設,包括下列各項:
- 接收者或連入連線速率太慢,無法跟上傳入資料速率的步調。
- 發生過多的資料遺失,可能是因為暫時性網路狀況,例如路由問題、網路不穩定等等。
- 寄件者上發生無法復原的錯誤。
- 本機電腦上發生過多的資源使用率,例如超過允許的內部緩衝區儲存體上限,或遇到資源不足的狀況。
- 發生資料一致性檢查錯誤。
- 元件 PGM 失敗取決於,例如 TCP/IP 或 Windows 通訊端。
上述清單中的第一個專案和第二個專案可能會導致接收者在資源用盡之前執行過多的緩衝,或最後移出傳送者的視窗之前。
終止 PGM 會話
PGM 傳送者或接收者可以呼叫 closesocket來停止傳送或接收資料。 接收者必須在接聽和接收通訊端上呼叫 closesocket ,以防止處理流失。 呼叫closesocket之前,在傳送者上呼叫關機可確保傳送所有資料,並確保修復資料會維持到傳送視窗超過最後一個資料序列為止,即使應用程式本身終止也一樣。