iocp 连续调用WSASend问题
我自己写了个iocp程序 但是在连续给同个客户端发包 造成第二个包没发出去
不知道如何处理
本人主要代码如下
DWORD WINAPI ServerThreadFunc(LPVOID lpParam)
{
CHuanshouDlg *lp = (CHuanshouDlg *)lpParam;
WSADATA wsaData;
HANDLE hCompPort;
DWORD ThreadID;
DWORD Ret;
if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)
{
AfxMessageBox("WSAStartup failed with error!");
return 0;
}
if ((hCompPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)) == NULL)
{
AfxMessageBox("CreateIoCompletionPort failed with error!");
return 0;
}
SYSTEM_INFO SystemInfo;
GetSystemInfo(&SystemInfo);
unsigned cpu = SystemInfo.dwNumberOfProcessors*2;
for(unsigned int i=0; i < cpu; i++)
{
HANDLE ThreadHandle;
lpthreadParam p = new _THREADPARAM;
p->cpid = hCompPort;
p->lp = lp;
//if ((ThreadHandle = CreateThread(NULL, 0, WorkThread, hCompPort, 0, &ThreadID)) == NULL)
if ((ThreadHandle = CreateThread(NULL, 0, WorkThread, p, 0, &ThreadID)) == NULL)
{
AfxMessageBox("CreateThread() failed with error");
return 0;
}
CloseHandle(ThreadHandle);
}
SOCKET ListenSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, NULL, WSA_FLAG_OVERLAPPED);
SOCKADDR_IN ServerAddr;
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
ServerAddr.sin_port = htons(8888);
bind(ListenSocket,(LPSOCKADDR)&ServerAddr,sizeof(ServerAddr));
listen(ListenSocket,100);
SOCKADDR_IN ClientAddr;
int addr_length=sizeof(ClientAddr);
while (TRUE)
{
LPSOCKET_INFORMATION SI = new SOCKET_INFORMATION();
if ((SI->Socket = WSAAccept(ListenSocket,(SOCKADDR*)&ClientAddr, &addr_length,NULL,0)) != INVALID_SOCKET)
{
//初始化一个新的用户信息
memset(&SI->Overlapped,0,sizeof(WSAOVERLAPPED));
memset(SI->buffer, 0, DATA_BUFSIZE);
SI->RecvDataBuf.buf = SI->buffer;
SI->RecvDataBuf.len = DATA_BUFSIZE;
SI->SendDataBuf.buf = SI->buffer;
SI->SendDataBuf.len = DATA_BUFSIZE;
SI->IoType = IORECV;
SI->ClientName = "null";
SI->firstlog = true;
InitializeCriticalSection(&SI->single_cs);
if (CreateIoCompletionPort((HANDLE)SI->Socket, hCompPort, (DWORD)SI, 0) == NULL)
{
AfxMessageBox("CreateIoCompletionPort failed with error ");
return 0;
}
//send a I/O request
if(WSARecv(SI->Socket, &SI->RecvDataBuf, 1, &Bytes, &Flags, &SI->Overlapped, NULL) == SOCKET_ERROR)
{
if(WSAGetLastError() != WSA_IO_PENDING)
{
AfxMessageBox("disconnect\n");
shutdown(SI->Socket,SD_SEND);
closesocket(SI->Socket);
delete SI;
continue;
}
}
}
}
return 0;
}
/// <summary>
/// I/O工作线程
/// </summary>
DWORD WINAPI WorkThread(LPVOID CompletionPortID)
{
//HANDLE hCompPort = (HANDLE)CompletionPortID;
lpthreadParam p = (lpthreadParam)CompletionPortID;
HANDLE hCompPort = (HANDLE)p->cpid;
CHuanshouDlg *lp = (CHuanshouDlg *)p->lp;
while (TRUE)
{
DWORD BytesTransferred = 0;
LPSOCKET_INFORMATION SI = NULL;
LPWSAOVERLAPPED Overlapped = NULL;
//Threads pool,waiting for awake
BOOL t = GetQueuedCompletionStatus(hCompPort, &BytesTransferred, (LPDWORD)&SI, &Overlapped, INFINITE);
if (t)
{
EnterCriticalSection(&SI->single_cs);
switch(SI->IoType)
{
case IORECV:
{
if (0 == BytesTransferred)
{
if(!SI->firstlog)
{
lp->QuitGame(SI->Socket,SI->ClientName);
}
continue;
}
CString message,msg2;
message = SI->RecvDataBuf.buf;
if(message == "")
{
memset(SI->buffer, 0, DATA_BUFSIZE);
SI->RecvDataBuf.len = DATA_BUFSIZE;
SI->RecvDataBuf.buf = SI->buffer;
SI->IoType = IORECV;
if (WSARecv(SI->Socket, &SI->RecvDataBuf, 1, &Bytes, &Flags, &SI->Overlapped, NULL) == SOCKET_ERROR)
{
if(WSAGetLastError() != WSA_IO_PENDING)
{
lp->QuitGame(SI->Socket,SI->ClientName);
delete SI;
continue;
}
}
continue;
}
int f = -1;
f = message.Find("<policy-file-request/>\0");
if(f >= 0)
{
CString xml = "<cross-domain-policy>";
xml = xml + "<site-control permitted-cross-domain-policies=\"all\"/>";
xml = xml + "<allow-access-from domain=\"*\" to-ports=\"8888\" />";
xml = xml + "</cross-domain-policy>\0";
sprintf(SI->SendDataBuf.buf,"%s",xml);
SI->SendDataBuf.len = strlen(xml) + 1;
SI->IoType = IOSEND;
//发送策略文件
if (WSASend(SI->Socket, &SI->SendDataBuf, 1, &Bytes, Flags, &SI->Overlapped, NULL) == SOCKET_ERROR)
{
if(WSAGetLastError() != WSA_IO_PENDING)
{
shutdown(SI->Socket,SD_SEND);
closesocket(SI->Socket);
delete SI;
continue;
}
}
}
else
{
CMarkup xml = CMarkup();
xml.SetDoc(message);
CString act;
CString item;
CString condition;
item = "msg";
condition = "act";
if(xml.FindChildElem(item))
{
xml.IntoElem();
act = xml.GetAttrib(condition);
}else{
AfxMessageBox("格式错误:" + SI->ClientName+"->" + message);
continue;
}
char* act2 = act.GetBuffer(act.GetLength());
switch(actMap[act2])
{
case login:
{
condition = "username";
CString username;
username = xml.GetAttrib(condition);
//踢掉同名用户
map<CString, LPSOCKET_INFORMATION>::iterator iter;
EnterCriticalSection(&clients_cs);
iter = clients.find(username.GetBuffer());
if(iter != clients.end())
{
LPSOCKET_INFORMATION oldlp = LPSOCKET_INFORMATION(iter->second);
if(SI->Socket != oldlp->Socket)
{
shutdown(LPSOCKET_INFORMATION(iter->second)->Socket,SD_SEND);
closesocket(LPSOCKET_INFORMATION(iter->second)->Socket);
}
clients.erase(iter);
}
SI->ClientName = username;
SI->firstlog = false;
SI->IoType = IOSEND;
clients[username] = SI;
LeaveCriticalSection(&clients_cs);
lp->loginGame(username);
//接到数据后向客户端发同意登录信息
CString _msg = "<root act='login' />\0";
SI->SendDataBuf.len = _msg.GetLength() + 1;
SI->SendDataBuf.buf = _msg.GetBuffer(_msg.GetLength());
SI->IoType = IOSEND;
if (WSASend(SI->Socket, &SI->SendDataBuf, 1, &Bytes, Flags, &SI->Overlapped, NULL) == SOCKET_ERROR)
{
if(WSAGetLastError() != WSA_IO_PENDING)
{
lp->QuitGame(SI->Socket,SI->ClientName);
delete SI;
continue;
}
}
break;
}
default:
{
break;
}
}
}
break;
}
case IOSEND:
{
CString num;
num.Format("%d",BytesTransferred);
lp->m_log += "IOSEND:"+ num +"\r\n";
lp->SendMessage(UPDATA_MESSAGE);
memset(SI->buffer, 0, DATA_BUFSIZE);
SI->RecvDataBuf.len = DATA_BUFSIZE;
SI->RecvDataBuf.buf = SI->buffer;
SI->IoType = IORECV;
if (WSARecv(SI->Socket, &SI->RecvDataBuf, 1, &Bytes, &Flags, &SI->Overlapped, NULL) == SOCKET_ERROR)
{
if(WSAGetLastError() != WSA_IO_PENDING)
{
lp->QuitGame(SI->Socket,SI->ClientName);
delete SI;
continue;
}
}
break;
}
default:
break;
}
LeaveCriticalSection(&SI->single_cs);
}
}
return FALSE;
}
bool CHuanshouDlg::SendMessageToOneByName(CString msg,CString username)
{
EnterCriticalSection(&clients_cs);
map<CString, LPSOCKET_INFORMATION>::iterator iter;
LPSOCKET_INFORMATION lp;
iter = clients.find(username.GetBuffer());
if(iter == clients.end())
{
LeaveCriticalSection(&clients_cs);
return false;
}
lp = (LPSOCKET_INFORMATION)iter->second;
lp->SendDataBuf.len = msg.GetLength() + 1;
lp->SendDataBuf.buf = msg.GetBuffer(msg.GetLength());
lp->IoType = IOSEND;
Flags = 0;
if (WSASend(lp->Socket, &lp->SendDataBuf, 1, &Bytes, Flags, &lp->Overlapped, NULL) == SOCKET_ERROR)
{
shutdown(lp->Socket,SD_SEND);
closesocket(lp->Socket);
clients.erase(iter);
LeaveCriticalSection(&clients_cs);
return false;
}
LeaveCriticalSection(&clients_cs);
return true;
}
/发送系统消息按钮
void CHuanshouDlg::OnBnClickedSend()
{
SendMessageToOneByName("test11\0","bear");
Sleep(100);
SendMessageToOneByName("test2\0","bear");
}
很奇怪,只要在发送的时候 Sleep(100);就成功
没有sleep 第二条客户端没有接到
没有出现沾包情况 客户端只接到第一个包的完整信息