WinsockI/O模型之重疊I/O模型

重疊I/O很多套接口I/O操作函數.
Winsock2提供了一組以WSA起頭函數,WSARecv/WSASend和WSARecvfrom/WSASendto.

幾個數據結果:

1)typedef struct _WSABUF{
       u_long len;       // 緩衝區大小.
       char FAR *buf; // 緩衝區指針.
   } WSABUF, FAR *LPWSABUF;

2)typedef struct _WSAOVERLAPPED{
        DWORD Internal;
        DWORD InternalHigh;
        DWORD Offset;
        DWORD OffsetHigh;
        WSAEVENT hEvent;
} WSAOVERLAPPED, *LPWSAOVERLAPPED;

WSAOVERLAPPED是OVERLAPPED結構移植來的,重疊I/O操作初始投遞I/O之間進行聯繫的機制.
前四個參數,由系統內部使用.hEvent設置特定的WSAEVENT對象即可.

3)typedef void(CALLBACK * LPWSAOVERLAPPED_COMPLETION_ROUTINE{
         DWORD dwError,               // 重疊操作的完成狀態;
         DWORD cbTransferred,     // 傳輸字節數
         LPWSAOVERLAPPED   lpOverlapped,   //調用I/O操作時WSAOVERLAPPED結構信息:
         DWORD dwFlags
};-
是Winsock2中重疊I/O回調函數指針,操作完成時自動調用該指針所指向完成函數.
參數分兩種情況,對於WSARecv/WSARecvfrom函數接收操作能立即結束
那麼dwFlags包含了調用接收函數時的lpFlags參數的信息,對於WSARend/WSASendto來說該參數暫時使用,系統設置爲0.
下面列出了四個Winsock2中的重疊I/O操作函數的定義:
      (1)、 int WSARecv(
              SOCKET s,
              LPWSABUP lpBuffers,
              DWORD dwBufferCount,
              LPDWORD lpNumberOfBytesRecvd,
              LPDWORD lpFlags,
              LPWSAOVERLAPPED lpOverlapped,
              LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
        );
      (2)、int WSASend(
              SOCKET s,
              LPWSABUF lpBuffers,
              DWORD dwBufferCount,
              LPDWORD lpNumberOfBytesSent,
              DWORD dwFlags,
              LPWSAOVERLAPPED lpOverlapped,
              LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
        );   
      (3)、int WSARecvFrom(
              SOCKET s,
              LPWSABUF lpBuffers,
              DWORD dwBufferCount,
              LPDWORD lpNumberOfBytesRecvd,
              DWORD dwFlags,
              struct sockaddr FAR *lpFrom,
              LPWSAOVERLAPPED lpOverlapped,
              LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
        );   
      (4)、int WSASendTo(
              SOCKET s,
              LPWSABUF lpBuffers,
              DWORD dwBufferCount,
              LPDWORD lpNumberOfBytesSent,
              DWORD dwFlags,
              struct sockaddr FAR *lpTo,
              int iToLen,
              LPWSAOVERLAPPED lpOverlapped,
              LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
        );  
   套接口s必須重疊套接口.直接調用socket函數或以參數dwFlags爲WSA_FLAG_OVERLAPPED參數調用WSASocket.
   下面兩行代碼完成同樣套接口創建工作.(代碼略)
   sock = WSASocket(AF_INEF, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
   sock = socket(AF_INET, SOCK_STREAM, 0);
   按照 lpOverlapped 和 lpCompletionRoutine3種不同工作狀態:
   1).兩種均設爲NULL非重疊I/O操作處理,發送,接收函數.
   2).lpCompletionRoutine爲NULL,調用這些I/O函數時lpOverlapped構中hEvent事件會被自動復位爲未觸發,重疊I/O操作完成被設置爲已觸發WSAWaitForMultipleEvents或者WSAGetOverlappedResult等待或論詢該事件對象的狀態.
   3).lpCompletionRoutine不爲NULL,那麼hEvent參數將被忽略,完成例程傳遞信息.
   調用WSAGetOverlappedResult應注意fWait參數不能設置爲TRUE 重疊數據發送/接收將工作非阻塞模式,函數調用能立即返回
    1.返回0 已立即完成並且無錯誤發生.
    2.返回SOCKET_ERROR,錯誤碼爲997(WSA_IO_PENDING),重疊I/O操作已成功初始化,完成後應用進程會得到系統通知.
    3.返回SOCKET_ERROR,錯誤碼不是WSA_IO_PENDING重疊I/O操作初始化失敗.
    調用WSAGetOverlappedResult函數來獲取指定套接口的最近一次重疊操作結構.
   
    BOOL WSAGetOverlappedResult(
                SOCKET s,
                LPWSAOVERLAPPED lpOverlapped,
                LPDWORD lpcbTransfer,
                BOOL fWait,LPDWORD lpdwFlags
    );
    lpdwFlags,lpcbTransfer輸出參數外,餘均勻輸入參數.
    其中s是感興趣的套接口描述字,lpOverlapped用於返回在該套接口的最近一次重疊操作時的WSAOverlapped結構數據,
    lpcbTransfer輸出重疊操作傳輸字節數,lpdwFlags用於輸出操作的參數,fWait參數是否要等待事件對象lpOverlapped->hEvnet,
    才能將fWait設置爲TRUE.如果無錯誤發生,返回TRUE,說明重疊操作已成功完成;否則返回FALSE,
    重疊操作沒有完成,重疊操作已完成但發生了錯誤,參數設置錯誤導致重疊操作的狀態無法判斷.

http://szzhliu.blog.163.com/blog/static/35130895201072111211726/

發佈了138 篇原創文章 · 獲贊 9 · 訪問量 102萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章