请留步,问个WSARecv/Send的问题

skykeen 2005-10-11 12:47:11
WSARecv/Send好像与Recv Send不太一样啊?

DWORD WINAPI ServerWorkerProc(LPVOID lParam)
{
CIocpModeSvr* pSvr=(CIocpModeSvr*)lParam;
HANDLE CompletionPort=pSvr->CompletionPort;
DWORD ByteTransferred;
LPPER_HANDLE_DATA PerHandleData;
PPER_IO_OPERATION_DATA PerIoData;
DWORD RecvByte;
while(true)
{
bool bSuccess=GetQueuedCompletionStatus(CompletionPort,
&ByteTransferred,
(LPDWORD)&PerHandleData,
(LPOVERLAPPED* )&PerIoData,
INFINITE);
//退出信号到达,退出线程
if(ByteTransferred==-1 && PerIoData==NULL)
{
return 1L;
}
//客户机已经断开连接或者连接出现错误
if(ByteTransferred==0 &&
(PerIoData->OperType==RECV_POSTED || PerIoData->OperType==SEND_POSTED))
{
//将该客户端数据删除
int arrSize=0;
bool bFind=false;
::EnterCriticalSection(&pSvr->cInfoSection);
while(arrSize<pSvr->ClientInfo.GetSize())
{
PER_HANDLE_DATA pPerHandleData=pSvr->ClientInfo.GetAt(arrSize);
if((pPerHandleData.IpAddr==PerHandleData->IpAddr) &&
(pPerHandleData.sClient==PerHandleData->sClient))
{
bFind=true;
pSvr->ClientInfo.RemoveAt(arrSize);
break;
}
arrSize++;
}
::LeaveCriticalSection(&pSvr->cInfoSection);
if(bFind)
{
//记录退出日志
CString LogStr;
in_addr in_A;
in_A.S_un.S_addr=PerHandleData->IpAddr;
LogStr.Format("Ip: %s,Socket : %d Disconneted",inet_ntoa(in_A),PerHandleData->sClient);
pSvr->WriteLogString(LogStr);
TRACE("\nSocket : %d Disconneted",PerHandleData->sClient);
//调用回调函数,通知上层该客户端已经断开
pSvr->m_pProcessRecvData(PerHandleData->IpAddr,
PerHandleData->sClient,
NULL,
0);
//关闭套接口
closesocket(PerHandleData->sClient);
GlobalFree(PerHandleData);
GlobalFree(PerIoData);
}
continue;
}
//为读操作完成,处理数据
if(PerIoData->OperType==RECV_POSTED)
{
//调用回调函数,处理数据
pSvr->m_pProcessRecvData(PerHandleData->IpAddr,
PerHandleData->sClient,
PerIoData->RecvBuf,
ByteTransferred);
//将源数据置空
memset(PerIoData->RecvBuf,0,BUFFER_SIZE);
ByteTransferred=0;
//重置IO操作数据
unsigned long Flag=0;
ZeroMemory(&(PerIoData->OverLapped),sizeof(OVERLAPPED));

PerIoData->RecvDataBuf.buf=PerIoData->RecvBuf;
PerIoData->RecvDataBuf.len=BUFFER_SIZE;
PerIoData->OperType=RECV_POSTED;
//提交另一个Recv请求
WSARecv(PerHandleData->sClient,
&(PerIoData->RecvDataBuf),
1,
&RecvByte,
&Flag,
&(PerIoData->OverLapped),
NULL);
}
//发送完成,置空缓冲区,释放缓冲区
if(PerIoData->OperType==SEND_POSTED)
{
memset(PerIoData,0,sizeof(PER_IO_OPERATION_DATA));
GlobalFree(PerIoData);
ByteTransferred=0;
}
}
return 0L;
}


上面的 "提交另一个Recv请求" WSARecv到底是是干什么用的?

事实上在IOCP里面GetQueuedCompletionStatus(CompletionPort,&ByteTransferred,(LPDWORD)&PerHandleData,(LPOVERLAPPED* )&PerIoData,INFINITE)本身已经可以捕获数据了,为什么还要WSARecv呢?
...全文
157 点赞 收藏 8
写回复
8 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
aiguozhou 2005-10-27
查考windows网络编程2 一书所说

一个重叠的I/O请求最终完成后,应用程序要负责获取获取重叠I/O操作的结果。一个重叠请求操作最终完成之后,在事件通知方法中,,
Winsock会更改与WSAOVERLAPPED结构关联的事件对象的事件传信状态。讲未传信改为已传信。由于已经有一个事件对象分配给WSAOVERLAPPED结构,所以只需简单的调用WSAWaitForMultipleEvents函数,便可判断出重叠I/O调用将在什么时候完成。

确定完成之后,接着需要调用WSAGetOverlappedResult函数,判断这个重叠调用到底是成功还是失败。
回复
aiguozhou 2005-10-27
楼主可以查看MSDN啊
lpBuffers
[in, out] Pointer to an array of WSABUF structures. Each WSABUF structure contains a pointer to a buffer and the length of the buffer.

他是一个指向WSABUF结构的数组,每个WSABUF结构包含一个指向长度为buffer的BUFFER

他应该是一个接受套接字内容的一个指针性的数组结构BUF吧 。不知道理解是否正确。
学习中~有错的地方请多多指点
回复
Pandona 2005-10-26
我也不明白,没人帮顶吗
回复
skykeen 2005-10-11
不好意思,看走眼了,刚对照MSDN看了下,dwBufferCount是buf数组的个数,而不是buf内的的字节数,ft!!

在重叠情况下,获取重叠数据常用WSAGetOverlappedResult(),我不明白这是为什么呀?WSARecv不是已经把重叠事件与buf关联在一起了吗?也就是一但有事件发生,WSAWaitForMultipleEvents就会返回,按照重叠io模式的意思,这时buf内应该有数据了才对呀,干嘛还要个WSAGetOverlappedResult,它不是多余的吗?
回复
skykeen 2005-10-11
GetQueuedCompletionStatus不是已经收到数据了吗?还要WSARecv干嘛?
而且请再看一下:
WSARecv(PerHandleData->sClient,&(PerIoData->RecvDataBuf),1,&RecvByte,&Flag,&(PerIoData->OverLapped),NULL);
第三个参数:也就是那个WSABUF的长度,居然为1,这有什么用?
回复
xingboy 2005-10-11
WSARecv可以当Recv用,但他自己有自己的特色,就用与异步传输。
Send发送完然后用Recv跟在后面接收这时程序就会停在Recv这里不往下运行。
用WSARecv接收时可以跟个事件句柄,在参数Overlapped里,当你调用WSARecv时程序会继续往下运行,有数据传输过来时系统会自动触发事件句柄。
回复
lifengice0706 2005-10-11
异步的,查msdn!
回复
skykeen 2005-10-11
int WSARecv
(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesRecvd,
LPDWORD lpFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
lpBuffers,lpOverlapped这两个参数分别是干什么用的?
回复
相关推荐
发帖
网络编程
创建于2007-09-28

1.8w+

社区成员

VC/MFC 网络编程
申请成为版主
帖子事件
创建了帖子
2005-10-11 12:47
社区公告
暂无公告