FD_READ:
当有数据发送过来时, WinSock 会以 FD_READ 事件通知你。
对于每一个 FD_READ 事件, 你需要像下面这样调用 recv() :
int bytes_recv = recv(wParam, &data, sizeof(data), 0);
注意:不一定每一次调用 recv() 都会接收到一个完整的数据包, 因为数据可能不会一次性全部发送过来. 所以在开始处理接收到的数据之前, 最好对接收到的字节数 ( 即 recv() 的返回值) 进行判断, 看看是否收到的是一个完整的数据包.
FD_WRITE
首先, 当你建立了一个连接时, 会产生一个 FD_WRITE 事件. 但是如果你认为在收到 FD_WRITE 时调用 send() 就万事大吉, 那就错了. FD_WRITE 事件只在发送缓冲区有多出的空位, 可以容纳需要发送的数据时才会触发.
说明一下 FD_WRITE 事件的使用时机. 如果你不是一次性发送大批量的数据的话, 就别想着使用 FD_WRITE 事件了。
原因很简单 - 如果你寄期望于在收到 FD_WRITE 事件时发送数据, 但是却又不能发送足够的数据填满发送缓冲区, 那么你就只能收到连接刚刚建立时触发的那一次 FD_WRITE - 系统不会触发更多的 FD_WRITE 了. 所以当你只是发送尽可能少的数据的时候, 就忘掉 FD_WRITE 机制吧, 在任何你想发送数据的时候直接调用 send() .
下面是一个处理 FD_WRITE 事件的例子.
case FD_WRITE: // 可以发送数据了
{
// 进入无限循环
while(TRUE)
{
// 从文件中读取数据, 保存到 packet.data 里面.
in.read((char*)&packet.data, MAX_PACKET_SIZE);
// 发送数据
if (send(wparam, (char*)(&packet), sizeof(PACKET), 0) == SOCKET _ERROR)
{
if (WSAGetLastError() == WSAEWOULDBLOCK)
{
// 发送缓冲区已经满了, 退出循环.
break;
}
else // 其他错误
{
// 显示出错信息然后退出.
CleanUp();
return(0);
}
}
}
} break;