18,356
社区成员
发帖
与我相关
我的任务
分享
bool CSocketServer::DoAccept(lpREQUEST_CONTEXT lpAcceptContext)
{
SOCKADDR_IN * pClientAddr = NULL;
SOCKADDR_IN * pLocalAddr = NULL;
int nSockAddrLen = sizeof(SOCKADDR_IN);
m_lpfnGetAcceptExSockAddrs //acceptex 之友 用来获取 客户端发送回来的第一组数据、本地地址信息,客户端地址信息
(
lpAcceptContext->wsaBuffer.buf,
lpAcceptContext->wsaBuffer.len -( (nSockAddrLen + 16) * 2) ,
nSockAddrLen + 16 ,
nSockAddrLen + 16 ,
(LPSOCKADDR*)&pLocalAddr ,
&nSockAddrLen ,
(LPSOCKADDR*)&pClientAddr ,
&nSockAddrLen
);
string ip = inet_ntoa(pClientAddr->sin_addr);
int port = ntohs(pClientAddr->sin_port);
SOCKET sock = GetAcceptContextSocket(lpAcceptContext); //获取之前投递Accept请求时插入的socket
APP_TYPE type = GetClientType(lpAcceptContext->wsaBuffer.buf);
if( APP_NULL == type
|| !IsLoginCmd(lpAcceptContext->wsaBuffer.buf)) //如果验证失败
{
m_ploger->formatMsg("验证失败,断开连接:%s:%d.",ip.c_str(),port);
RELEASE_SOCKET(sock);
}
else
{
lpSOCKET_CONTEXT pSocketContext = GetClientSockContext(type , ip.c_str());
if(!pSocketContext)
{
m_ploger->formatMsg("不存在该客户端,端类型:%s 地址:%s.",GetAppTypeName(type).c_str(),ip.c_str());
RELEASE_SOCKET(sock);
}
else
{
pSocketContext->sock = sock;
pSocketContext->ip = ip;
pSocketContext->port = port;
pSocketContext->type = type;
setsockopt(sock,
SOL_SOCKET,
SO_UPDATE_ACCEPT_CONTEXT,
(char*)&m_plisenContext->sock,
sizeof(m_plisenContext->sock)
);
CreateIoCompletionPort((HANDLE)sock,m_hIOCompletionPort,(DWORD)pSocketContext,0);
SetClientOnline(pSocketContext);
m_ploger->formatMsg("客户端 类型:%s 地址:%s:%d 登陆成功.",GetAppTypeName(type).c_str(),
ip.c_str(),port);
lpREQUEST_CONTEXT pRecvContext = pSocketContext->GetNewContext(REQUEST_RECV);
if(!PostRecv(pSocketContext,pRecvContext)) //如果客户端投递recv请求失败,断开连接,并设置客户端离线
SetClientUnline(pSocketContext);
}
}
return PostAccept(lpAcceptContext);
}
bool CSocketServer::PostRecv(lpSOCKET_CONTEXT pSockContext,lpREQUEST_CONTEXT lpRecvContext)
{
lpRecvContext->ZeroBuffer();
OVERLAPPED * pOverlapped = &lpRecvContext->overlapped;
WSABUF * pWsaBuffer = &lpRecvContext->wsaBuffer;
DWORD dwFlags = 0;
DWORD dwBytes = 0;
int nBytesRecv = WSARecv(
pSockContext->sock,
pWsaBuffer,
1,
&dwBytes,
&dwFlags,
pOverlapped,
NULL
);
// 如果返回值错误,并且错误的代码并非是Pending的话,那就说明这个重叠请求失败了
if ((SOCKET_ERROR == nBytesRecv) && (WSA_IO_PENDING != WSAGetLastError()))
{
m_ploger->formatMsg("客户端投递Recv请求失败 类型:%s 地址:%s,Socket错误代码:%d",
GetAppTypeName(pSockContext->type).c_str(),pSockContext->ip.c_str(),WSAGetLastError());
SetClientUnline(pSockContext);
return false;
}
return true;
}