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.
如果lpOverlapped和lpCompletionRoutine都是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绑定使用。参数名也可以看出各个参数的含义,就不对各参数进行说明了。