Winsock recv() 无休止地收到 10053 WSAECONNABORTED 错误

Posted

技术标签:

【中文标题】Winsock recv() 无休止地收到 10053 WSAECONNABORTED 错误【英文标题】:Winsock recv() endlessly receives 10053 WSAECONNABORTED error 【发布时间】:2014-06-21 16:16:23 【问题描述】:

我希望我不会错过一个简单的解决方案,但我已经找了好几天了。

我的 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() 函数之前,我从recv() 结果中得到不间断的10053 WSAECONNABORTED 结果,我的服务器的send() 函数也会首先触发 10053 WSAECONNABORTED。这些显然在某种程度上是相关的,但我仍然感到困惑。

那么最有可能发生的情况是,当客户端关闭时,它没有时间及时将其断开连接消息发送到服务器,因此服务器仍然在send()命令中存储数据包数据客户端的套接字并填充它,直到它最终在send() 函数上遇到10053 错误。

我不确定在此之后幕后发生了什么。但是一旦send() 函数遇到WSAECONNABORTED 错误,recv() 就会得到无穷无尽的窗口消息,同时返回WSAECONNABORTED

现在我在这里完全猜测......但我必须假设send() 函数仍然有一个完整的数据缓冲区等待发送到已经关闭的客户端,并且网络只是不断地将数据发送到一个不存在的客户端,然后将错误发送回recv() 函数?那么我是否应该以某种方式删除send() 缓冲区中的数据,以便将其清除,然后服务器可以正常运行?

【问题讨论】:

39245 是怎么回事?你的键盘没有配备字母吗? 对不起,39245 只是正在使用的端口号,当收到一个数据包时,它就是它来自的端口。 我认为您收到WSAECONNABORTED时需要关闭套接字。 您是指关闭调用send() 的服务器套接字吗?如果是这样,连接到服务器的所有其他客户端会发生什么情况?如果我关闭服务器套接字然后再次打开它,是否会重置每个人与服务器的连接? 【参考方案1】:

根据Microsoft Support:在运行Microsoft Windows Server 2003 的计算机上,您运行使用Winsock 连接的网络程序。当程序调用recv Winsock函数时,你会收到这个错误码

http://support.microsoft.com/kb/925513

【讨论】:

我理解我收到错误的原因,我只是想让服务器不会无限循环通过我的DefWindowProc() 无限循环并出现 10053 错误。此错误也发生在许多不同的 Window 操作系统上,主要是当客户端和服务器仅在 Windows 7 上运行时。我试图理解为什么 DefWindowProc() 不断地一遍又一遍地处理相同的 Winsock 错误消息。【参考方案2】:

好的,我相信我现在明白了。在我看来,我假设创建套接字就像内存分配一样,如果您在客户端分配内存,则必须在客户端处理它,但网络套接字连接可以作为 2 路处理。我不明白如果我在客户端上创建了一个套接字连接,我可以使用closesocket() 在服务器上关闭它。我想我必须在客户端再次处理它,或者让套接字自己工作,直到它意识到连接已经消失,它会终止自己的操作。

所以我希望得到的答案就是在服务器端的客户端套接字上调用closesocket()

所以关于调用closesocket(),你的回答是正确的,我只是没有把它缠在我的头上,我可以在服务器端关闭客户端的套接字,因为它“技术上”根本不在客户端或服务器上,而且在这两个程序中都可能是死亡。

【讨论】:

以上是关于Winsock recv() 无休止地收到 10053 WSAECONNABORTED 错误的主要内容,如果未能解决你的问题,请参考以下文章

winsock c++中recv函数的奇怪行为

使用 Winsock 的 send()/recv() 时是不是需要确认响应?

Winsock recv() 不阻塞

Winsock“recv”不会在非正常连接终止时返回

winsock套接字的recv函数

在 C++ 中的 Winsock 中发送 HTTP GET 请求后,Recv() 函数挂起