OVERLAPPED相關的socket函數介紹


OVERLAPPED相關的socket函數介紹

  上一篇文章介紹了《Windows核心編程》OVERLAPPED結構與內核對象IOCompletionPort相關概念,見http://www.cnblogs.com/hgwang/p/6116398.html。socket也是一種設備描述符,也適用於OVERLAPPED結構相關的IO操作。除了http://www.cnblogs.com/hgwang/p/6074038.html介紹的socket、send、recv、IOCtrlSocket等函數外,windows提供一組關聯OVERLAPPED結構的套接字操作WSASocket、WSASend、WSARecv、WSAIoctl等。

1: WSASocket

Description:The WSASocket function creates a socket that is bound to a specific transport-service provider.

1 SOCKET WSASocket(
2   __in          int af,
3   __in          int type,
4   __in          int protocol,
5   __in          LPWSAPROTOCOL_INFO lpProtocolInfo,
6   __in          GROUP g,
7   __in          DWORD dwFlags
8 );

  該函數的前3個參數與socket的參數一致,見http://www.cnblogs.com/hgwang/p/6074038.html內socket介紹。WSASocket函數的后3個參數如下:

lpProtocolInfo

  A pointer to a WSAPROTOCOL_INFO structure that defines the characteristics of the socket to be created. If this parameter is not NULL, the socket will be bound to the provider associated with the indicated WSAPROTOCOL_INFO structure.

  該參數用來設置socket的屬性值。如果該參數為NULL,socket使用前3個參數作為屬性。如果該參數不是NULL,socket使用WSAPROTOCOL_INFO 結構體內值作為屬性。使用時,一般傳值為NULL。

g

  Reserved.  預留,一般傳值為0.

dwFlags

  A flag that specifies the socket attribute.

  用於指定socket的屬性。創建具有OVERLAPPED屬性的socket需要傳遞參數WSA_FLAG_OVERLAPPED。

  傳遞WSA_FLAG_OVERLAPPED標志位的說明如下:

  This flag causes an overlapped socket to be created. Overlapped sockets can utilize WSASend, WSASendTo, WSARecv, WSARecvFrom, and WSAIoctl for overlapped I/O operations, which allow multiple operations to be initiated and in progress simultaneously. All functions that allow overlapped operation (WSASend, WSARecv, WSASendTo, WSARecvFrom, WSAIoctl) also support nonoverlapped usage on an overlapped socket if the values for parameters related to overlapped operations are NULL.

  Overlapped socket能夠使用WSASend、WSARecv、WSAIoctl等函數。這些函數(提供overlapped 操作的函數)也允許非nonoverlapped 的socket使用,只要overlapped 關鍵字傳遞的值是NULL。

  由此可見,WSASocket、WSASend、WSARecv、WSAIoctl作用域大於socket、send、recv、ioctrlsocket。如果WSASocket、WSASend、WSARecv、WSAIoctl為Overlapped 傳遞的參數是NULL,等同於socket、send、recv、ioctrlsocket。

  創建一個overlapped 的socket的用法如下:

HANDLE m_Socket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);

 

 2: WSARecv

 Description:The WSARecv function receives data from a connected socket.

1 int WSARecv(
2   __in          SOCKET s,
3   __in_out      LPWSABUF lpBuffers,
4   __in          DWORD dwBufferCount,
5   __out         LPDWORD lpNumberOfBytesRecvd,
6   __in_out      LPDWORD lpFlags,
7   __in          LPWSAOVERLAPPED lpOverlapped,
8   __in          LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
9 );

 

 Parameters

s

A descriptor identifying a connected socket.

lpBuffers

A pointer to an array of WSABUF structures. Each WSABUF structure contains a pointer to a buffer and the length, in bytes, of the buffer.

指向WSABUF數組的指針,每個WSABUF含有一個buffer和buffer的長度

dwBufferCount

The number of WSABUF structures in the lpBuffers array.

lpBuffers數組的個數

lpNumberOfBytesRecvd

A pointer to the number, in bytes, received by this call if the receive operation completes immediately. If the lpOverlapped parameter is non-NULL, this parameter is optional and can be set to NULL.

WSARecv接收到數據的長度,如果WSARecv被設置了lpOverlapped (重疊IO,不會立即返回),則該參數可選且能夠被設置為NULL。

lpFlags

A pointer to flags used to modify the behavior of the WSARecv function call. For more information, see the Remarks section.

lpOverlapped

A pointer to a WSAOVERLAPPED structure (ignored for nonoverlapped sockets).

overlapped socket可用,非overlapped socket將會被忽略

lpCompletionRoutine

A pointer to the completion routine called when the receive operation has been completed (ignored for nonoverlapped sockets).

overlapped socket可用,非overlapped socket將會被忽略

Return Value

  If no error occurs and the receive operation has completed immediately, WSARecv returns zero. In this case, the completion routine will have already been scheduled to be called once the calling thread is in the alertable state. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError. The error code WSA_IO_PENDING indicates that the overlapped operation has been successfully initiated and that completion will be indicated at a later time. Any other error code indicates that the overlapped operation was not successfully initiated and no completion indication will occur.

  如果沒有錯誤且recv操作立即完成,WSARecv返回0。否則,返回SOCKET_ERROR。如果是OVERLAPPED操作且錯誤碼是WSA_IO_PENDING,表示WSARecv操作初始化成功,並將在一段時間后完成。其他錯誤只是操作沒有成功初始化不會完成。

3:WSASend

Description:The WSASend function sends data on a connected socket.

int WSASend(
  __in          SOCKET s,
  __in          LPWSABUF lpBuffers,
  __in          DWORD dwBufferCount,
  __out         LPDWORD lpNumberOfBytesSent,
  __in          DWORD dwFlags,
  __in          LPWSAOVERLAPPED lpOverlapped,
  __in          LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);

 

 WSASend的參數和WSARecv的參數一致,可參考WSARecv參數說明。

Return Value

  If no error occurs and the send operation has completed immediately, WSASend returns zero. In this case, the completion routine will have already been scheduled to be called once the calling thread is in the alertable state. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError. The error code WSA_IO_PENDING indicates that the overlapped operation has been successfully initiated and that completion will be indicated at a later time. Any other error code indicates that the overlapped operation was not successfully initiated and no completion indication will occur.

  如果沒有錯誤發生且send操作立即完成,WSASend返回0。否則,返回SOCKET_ERROR 。如果錯誤碼是WSA_IO_PENDING,說明重疊IO操作初始化成功稍后完成。如果是其他錯誤碼,則標明WSASend操作失敗。

4: WSAIoctl

Description:The WSAIoctl function controls the mode of a socket.

 1 int WSAIoctl(
 2   __in          SOCKET s,
 3   __in          DWORD dwIoControlCode,
 4   __in          LPVOID lpvInBuffer,
 5   __in          DWORD cbInBuffer,
 6   __out         LPVOID lpvOutBuffer,
 7   __in          DWORD cbOutBuffer,
 8   __out         LPDWORD lpcbBytesReturned,
 9   __in          LPWSAOVERLAPPED lpOverlapped,
10   __in          LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
11 );

 

Parameters

s

A descriptor identifying a socket.

dwIoControlCode

The control code of operation to perform.

指示WSAIoctl 操作的類型。MSDN給出了很多類型,這里不一一列舉。常用的有FIONBIO,設置socket阻塞\非阻塞模式;SIO_GET_EXTENSION_FUNCTION_POINTER,獲取winsock2擴展庫函數的指針,如ACCEPTEX函數等。

lpvInBuffer

A pointer to the input buffer輸入參數地址。

cbInBuffer

The size, in bytes, of the input buffer.輸入參數大小

lpvOutBuffer

A pointer to the output buffer.輸入參數接收地址。

cbOutBuffer

The size, in bytes, of the output buffer.輸入參數大小

lpcbBytesReturned

A pointer to actual number of bytes of output.實際輸出參數大學

lpOverlapped

A pointer to a WSAOVERLAPPED structure (ignored for non-overlapped sockets).

lpCompletionRoutine

A pointer to the completion routine called when the operation has been completed (ignored for non-overlapped sockets). See Remarks.

Return Value

  Upon successful completion, the WSAIoctl returns zero. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.

  如果lpOverlappedlpCompletionRoutine都是NULL,WSAIoCtl等價於IoCtrlSocket。如果使用SIO_GET_EXTENSION_FUNCTION_POINTER,獲取winsock2擴展庫函數的指針,可以將lpvInBuffer指向以下GUID類型的變量,取值如下:

  比如,取出AcceptEx函數可以這樣寫:

 1 LPFN_ACCEPTEX    m_lpfnAcceptEx;
 2 GUID GuidAcceptEx = WSAID_ACCEPTEX; 
 3 DWORD dwBytes = 0;  
 4 
 5 if(SOCKET_ERROR == WSAIoctl(
 6     m_Socket, 
 7     SIO_GET_EXTENSION_FUNCTION_POINTER, 
 8     &GuidAcceptEx, 
 9     sizeof(GuidAcceptEx), 
10     &m_lpfnAcceptEx, 
11     sizeof(m_lpfnAcceptEx), 
12     &dwBytes, 
13     NULL, 
14     NULL)
15 )  
16 {
17     error...
18 }

  LPFN_ACCEPTEX等函數指針定義在MSWSock.h。GUID定義在guiddef.h,結構如下:

typedef struct _GUID {
    unsigned long  Data1;
    unsigned short Data2;
    unsigned short Data3;
    unsigned char  Data4[ 8 ];
} GUID;

 5: AcceptEx

  在Mswsock.h內定義,需要包含該文件。

Description:The AcceptEx function accepts a new connection, returns the local and remote address, and receives the first block of data sent by the client application.

Note  This function is a Microsoft-specific extension to the Windows Sockets specification.

  AcceptEx函數接收新連接,返回本地和遠端地址,並且接收客戶端發來的第一包數據。AcceptEx函數是擴展庫函數,需要用WSAIoctl指定SIO_GET_EXTENSION_FUNCTION_POINTER,將lpvInBuffer指定為WSAID_ACCEPTEX才能獲取。

 1 BOOL AcceptEx(
 2   __in          SOCKET sListenSocket,
 3   __in          SOCKET sAcceptSocket,
 4   __in          PVOID lpOutputBuffer,
 5   __in          DWORD dwReceiveDataLength,
 6   __in          DWORD dwLocalAddressLength,
 7   __in          DWORD dwRemoteAddressLength,
 8   __out         LPDWORD lpdwBytesReceived,
 9   __in          LPOVERLAPPED lpOverlapped
10 );

 

Parameters

sListenSocket

A descriptor identifying a socket that has already been called with the listen function. A server application waits for attempts to connect on this socket.

監聽socket。

sAcceptSocket

A descriptor identifying a socket on which to accept an incoming connection. This socket must not be bound or connected.

待接收的socket。注意,用AcceptEx給sAcceptSocket傳入的socket必須是已用WSASocket生成的,而且是當前未被使用的。

lpOutputBuffer

A pointer to a buffer that receives the first block of data sent on a new connection, the local address of the server, and the remote address of the client. The receive data is written to the first part of the buffer starting at offset zero, while the addresses are written to the latter part of the buffer. This parameter must be specified.

必要參數。接收第一包數據的緩沖區,接受的數據分成3部分,第1部分是客戶端發來的數據,第2部分是本地地址,第3部分是遠端地址。

dwReceiveDataLength

The number of bytes in lpOutputBuffer that will be used for actual receive data at the beginning of the buffer. This size should not include the size of the local address of the server, nor the remote address of the client; they are appended to the output buffer. If dwReceiveDataLength is zero, accepting the connection will not result in a receive operation. Instead, AcceptEx completes as soon as a connection arrives, without waiting for any data.

指定lpOutputBuffer為接收客戶端傳來數據的緩沖區長度

dwLocalAddressLength

The number of bytes reserved for the local address information. This value must be at least 16 bytes more than the maximum address length for the transport protocol in use.指定lpOutputBuffer為接收本地地址的緩沖區長度

dwRemoteAddressLength

The number of bytes reserved for the remote address information. This value must be at least 16 bytes more than the maximum address length for the transport protocol in use. Cannot be zero.指定lpOutputBuffer為接收遠端地址的緩沖區長度

lpdwBytesReceived

A pointer to a DWORD that receives the count of bytes received. This parameter is set only if the operation completes synchronously. If it returns ERROR_IO_PENDING and is completed later, then this DWORD is never set and you must obtain the number of bytes read from the completion notification mechanism.

接收到的數據長度,僅同步模式下有效。如果返回值為ERROR_IO_PENDING ,該值無效。

lpOverlapped

An OVERLAPPED structure that is used to process the request. This parameter must be specified; it cannot be NULL.

Return Value

  If no error occurs, the AcceptEx function completed successfully and a value of TRUE is returned.

  If the function fails, AcceptEx returns FALSE. The WSAGetLastError function can then be called to return extended error information. If WSAGetLastError returns ERROR_IO_PENDING, then the operation was successfully initiated and is still in progress. If the error is WSAECONNRESET, an incoming connection was indicated, but was subsequently terminated by the remote peer prior to accepting the call.

  如果無錯誤發生,AcceptEx函數返回TRUE,否則,返回FALSE如果WSAGetLastError 返回ERROR_IO_PENDING,表示已初始化成功稍后會完成。

6:GetAcceptExSockaddrs

  在Mswsock.h內定義,需要包含該文件。

Description:The GetAcceptExSockaddrs function parses the data obtained from a call to the AcceptEx function and passes the local and remote addresses to a sockaddr structure.

Note  This function is a Microsoft-specific extension to the Windows Sockets specification.

 1 void GetAcceptExSockaddrs(
 2   __in          PVOID lpOutputBuffer,
 3   __in          DWORD dwReceiveDataLength,
 4   __in          DWORD dwLocalAddressLength,
 5   __in          DWORD dwRemoteAddressLength,
 6   __out         LPSOCKADDR* LocalSockaddr,
 7   __out         LPINT LocalSockaddrLength,
 8   __out         LPSOCKADDR* RemoteSockaddr,
 9   __out         LPINT RemoteSockaddrLength
10 );

 

  這個函數用於從lpOutputBuffer中解析出本地地址和遠端地址,通常和AcceptEx綁定使用。參數名也可以看出各個參數的含義,就不對各參數進行說明了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM