重叠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/