IOCP 重复WSASend发送数据的问题
好像发送数据以后还会跳到GetQueuedCompletionStatus
并且WSARecv缓存数据还是以前的
高手赐教
#include "Iocp.h"
#include "action.h"Iocp Iocp::Instance;Iocp & Iocp::getInstance()
{
return Instance;
}Iocp::Iocp(void)
{
}Iocp::~Iocp(void)
{
}
bool Iocp::init(int port)
{
__INIT_NET_ENVIR__ if(server.CreateSocket()==false){
cout<<"套接字创建失败"<<endl;
return false;
}
if(server.bind()==false){
cout<<"端口绑定失败"<<endl;
return false;
}
if(server.listen()==false){
cout<<"套接字监听失败"<<endl;
return false;
} return true;
}
bool Iocp::startup(){ // 接收的字节数
DWORD recvSize;
// 接收标识
DWORD flags = 0;
CInfo* pClient;
iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
Thread th;
th.create(workthread,(void*)this);

while (true)
{
// 创建客户端信息对象
pClient = new CInfo();
// 接入连接
*pClient = ::WSAAccept(server.socket,(sockaddr*)server.getAddr(),server.getAddrlen(),NULL,0);
// 关联新接入来的socket和与创建好的完成端口,并传递一个套接字信息结构
CreateIoCompletionPort((HANDLE)pClient->client,iocp,(ULONG_PTR)pClient,0);
// 创建重叠I/O信息结构
memset(&pClient->overlapped,0,sizeof(pClient->overlapped));
pClient->wsaBuf.len = NET_MAX_RECV_SIZE;
pClient->wsaBuf.buf = pClient->szBuffer;
pClient->type=true;
// 接收数据
WSARecv(pClient->client,&pClient->wsaBuf,1,&recvSize,&flags,&pClient->overlapped,NULL);
cout<<"用户:"<<server.getip()<<"连接"<<endl;
}
return false;
cout<<"工作线程结束"<<endl;
}
void Iocp::write(CInfo * info)
{
// 接收的字节数
DWORD recvSize = 0;
info->wsaBuf.len = strlen(info->czBuffer);
info->wsaBuf.buf = info->czBuffer;
memset(&(info->szBuffer),0,sizeof(info->szBuffer));
::WSASend(info->client,&info->wsaBuf,1,&recvSize,0,&info->overlapped,NULL);
}
workThread(workthread)
{
Iocp* iocp = (Iocp*)param;
// 接收标识
DWORD flags = 0;
// 数据缓冲区
LPOVERLAPPED ptrOverlapped;
// 接收的字节数
DWORD recvSize = 0;
BOOL bResult;
// 客户端
CInfo* pClient;/*=new CInfo();*/
while (true){ // 等待I/O完成
bResult=GetQueuedCompletionStatus(iocp->iocp,&recvSize,(PULONG_PTR)&pClient,&ptrOverlapped,INFINITE);
if (bResult == FALSE && ptrOverlapped == NULL)
{
printf("WorkerThread - GetQueuedCompletionStatus()错误.\n");
}else if (bResult == FALSE && ptrOverlapped != NULL)
{
cout<<"用户非正常退出"<<endl;
}
else if (recvSize == 0)
{    
closesocket(pClient->client);
cout<<"用户已经退出"<<endl;
}




short s=NULL;

memmove(&s,pClient->szBuffer,sizeof(s));

if(s==10010){

cout<<"成功"<<endl;
funcMap[100](pClient);
continue;
}

printf("recv data from client: %s\n", pClient->szBuffer);
WSARecv(pClient->client,&pClient->wsaBuf,1,&recvSize,&flags,&pClient->overlapped,NULL);

}
ExitThread(0);
return 0;
}
funcMap[100](pClient); 其实是调用了void login(CInfo *cinfo){
char uses[32];
char pwds[32];
char db[2];
short ss=10011;

memcpy(uses,cinfo->szBuffer+2,32);
memcpy(pwds,cinfo->szBuffer+34,32);
memcpy(db,&ss,sizeof(ss)); //memset(db+2,1,2);
memcpy(cinfo->czBuffer,db,2);
//cinfo->czBuffer[3]='\0';
SIOCP.write(cinfo);
}

解决方案 »

  1.   

    你没有完全理解GetQueuedCompletionStatus的意思。
    GetQueuedCompletionStatus是从IOCP获取一个完成信息,而非:
    printf("recv data from client: %s\n", pClient->szBuffer);另外你这位同志写代码很危险啊,很多东西都不检测。
      

  2.   

    如同楼上所说对完成端口理解不够,完成端口是异步机制,WSASend以后函数立即返回,但是并不表示send这个动作已经完成,当一个操作完成以后,GetQueuedCompletionStatus会得到一个通知,如果想知道是哪个操作完成了一般是通过PULONG_PTR lpCompletionKey这个参数来判断的,建议楼主还是仔细看看msdn对iocp的介绍!
      

  3.   

    OVERLAPPED 重复的了所以就这样子了