我希望我不会错过一个简单的解决方案,但我一直在寻找好几天。
我的MMO客户端/服务器Winsock MFC架构在大多数情况下都运行良好。
在客户端关闭连接的极少数情况下,服务器将收到10053 WSAECONNABORTED
错误消息。即使是合法的客户关闭。以下是处理传入消息的服务器代码,为未优化的代码道歉:
//-----------------------------------------------------------------------------
LRESULT CDXDisplay::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) //handle the messages
{
case 39245: //Network port number
{
switch (lParam) //If so, which one is it?
{
case FD_ACCEPT:
VGlobal::sSocket.AcceptSocket();
break;
case FD_CONNECT:
break;
case FD_READ:
VGlobal::sSocket.receiveSocket = wParam;
VGlobal::sSocket.ReceivePacket();
break;
case FD_WRITE:
break;
case FD_CLOSE:
VGlobal::sSocket.CloseClientConnection( wParam );
break;
}
}
break;
default:
if(message == WM_EXITSIZEMOVE || (message == WM_SIZE && (wParam == SIZE_MAXIMIZED /*|| wParam == SIZE_RESTORED*/)))
{
OnSizeScreen();
MainVant->SetDisplayMode(0);
}
return CDialog::DefWindowProc(message, wParam, lParam);
//return CWnd::DefWindowProc(message, wParam, lParam);
}
return CDialog::DefWindowProc(message, wParam, lParam);
}
程序将收到数据包,触发FD_READ,然后调用ReceivePacket()
//-----------------------------------------------------------------------------
int SocketServer::ReceivePacket( char * tBuffer, int tReceived )
{
ClientInfo::_packetInfo tPacket;
if( tBuffer == NULL )
{
char buffer[4096];
memset(buffer, 0, sizeof(buffer));
int received = recv( receiveSocket, buffer, sizeof(buffer) - 1, 0 );
//received = -1 and the WSAGetLastError() ID is 10053
if( received == -1 )
{
int tError = WSAGetLastError();
return 0;
}
if( received == 0 )
return 0;
//Handle packet data
_recvData tRData;
tRData.length = received;
//tRData.recvBuffer = buffer;
tRData.recvSocket = receiveSocket;
CString convStr;
LPTSTR aStr = tRData.recvBuffer.GetBufferSetLength(received);
memcpy( (void*)aStr, buffer, received );
recvDataList.push_back( tRData );
}
return 1;
}
我只是忽略数据包,等待下一个窗口消息。但是,当我这样做时,DefWindowProc()
会不断地一遍又一遍地收到10053
错误。
我会假设在MSDN上阅读recv()
函数示例以及我在网上找到的其他示例,我需要做的就是"忽略"消息并继续前进,但事实并非如此。然后我假设我的客户端ping超时代码将处理客户端预错误的任何剩余数据,然后在完成后删除客户端信息。
如果我需要一个简单的解决方案来处理这个错误,我非常抱歉,但我似乎无法找到它。
更新1:
在进行进一步测试时,似乎在收到进入DefWindowProc()
的不间断套接字消息之前,然后进入recv()
函数,我从10053 WSAECONNABORTED
获得recv()
结果{ {1}}结果,我的服务器的send()
功能也首先触发10053 WSAECONNABORTED
。这些显然在某种程度上有关,但我仍然感到困惑,如何。
所以最有可能发生的事情是,当客户端关闭时,它没有时间及时将其断开连接消息发送到服务器,因此服务器仍然将数据包数据存储在{{1}中}}命令用于客户端套接字并填写它,直到它最终达到send()
函数上的10053
错误。
在此之后,我不确定幕后会发生什么。但是,send()
函数遇到send()
错误后,WSAECONNABORTED
会收到无尽的窗口消息,并返回recv()
。
现在我在这里做了完整的猜测...但我必须假设WSAECONNABORTED
函数仍然有一个完整的数据缓冲区等待发送到已经关闭的客户端,并且网络只是不断发送数据到不存在的客户端,然后在send()
函数中发回错误?所以我应该以某种方式删除recv()
缓冲区中的数据以便清除它,然后服务器可以正常继续吗?
答案 0 :(得分:0)
根据Microsoft Support:在运行Microsoft Windows Server 2003的计算机上,运行使用Winsock连接的网络程序。当程序调用recv Winsock函数时,您会收到此错误代码
答案 1 :(得分:0)
好的,我相信我现在明白了。在我看来,我假设创建一个套接字就像内存分配,如果你在客户端分配内存,你必须在客户端处理它,但网络套接字连接可以作为双向街道处理。我不明白,如果我在客户端上创建套接字连接,我可以使用closesocket()
在服务器上关闭它。我以为我必须再次在客户端上处理它,或者让套接字自行解决,直到它意识到连接已经消失,它将终止自己的行为。
所以我希望答案就是在服务器端的客户端套接字上调用closesocket()
。
所以你的答案是关于调用closesocket()
的正确答案,我只是没有将它包裹在我的头上,我可以关闭服务器端的客户端套接字,因为它“技术上”不在客户端或服务器上所有这些都可以在两个程序中死亡。