1

我正在开发一个遗留的 VC6 应用程序,它使用 winsocket 来监听传入数据包的 UDP 端口。但是我收到以下错误。如果我使用WSAGetLastError()I get WSAECONNRESET,如果我阅读了描述,这似乎没有意义,因为它说远程主机强行关闭了套接字,但我想使用 UDP 无连接庄园,所以无关紧要其他机器正在做......我们应该听听。如果我检查errno并使用,sterror()我会收到以下消息。"No such file or directory". (我认为它的枚举是 EIO,根据http://pubs.opengroup.org/onlinepubs/009695399/functions/recvfrom.html

我在缩小问题范围方面取得了一些成功,如果我sendto()拨打电话,在与 相同的端口上回调recvfrom(),代码似乎可以正常工作。因此,与此相关sendto()的东西处于糟糕的状态。

我正在寻找有关此套接字为何变坏以及如何预防或恢复的建议。

编辑

这是另一个奇怪的部分,如果再次为该套接字进行设置(在 recvfrom() 失败之后)......这一切似乎都有效,甚至额外的调用sendto()似乎也不会触发 recvfrom() 失败,这反过来会再次调用设置..

代码

 static VOID SetupSocketAddress( SOCKADDR_U &saRx, int nRTDPort )
    {
        memset(&saRx.saIPX, 0, sizeof(SOCKADDR_IPX));
        saRx.saIPX.sa_family = AF_IPX;                          // IPX type address
        memset(saRx.saIPX.sa_netnum,0x00,4);                    // we may have to get this number
        memset(saRx.saIPX.sa_nodenum,0xff,6);                   // broadcast address
        saRx.saIPX.sa_socket=(unsigned short)nRTDPort;      // socket number
    }

void CRealTimeData::SetupSocket( CRealTimeData * lpRTD, BOOL &bDone, SOCKADDR_U &saRx, int nRTDPort, SOCKADDR_U &saFrom, int &cbAddr, 
    DWORD &dwLocalAddress, int &nMaxIpIpxBuf, char * &pbyIpIpxRxBuf, int nFlags, BOOL bDo)
{
    char    szErrorCode[32];
    int     nReturn = 0;

    if (lpRTD->m_eSourceType == V7_RTD_IPX)
    {
        // open IPX socket
        // packet type = 4
        lpRTD->m_Socket=socket(AF_IPX, SOCK_DGRAM, NSPROTO_IPX+4);
        if (lpRTD->m_Socket == INVALID_SOCKET)
        {
            nReturn = AddSocketErrorToEventViewer( lpRTD);
            bDone = TRUE;
        }

        // Socket must be bound prior to calling recvfrom()
        // setup address
        SetupSocketAddress(saRx, nRTDPort);


#ifdef  _DEBUG_IPX
        // test changing host number to network number
        // we can't actually change though, because other programs use it this way
        u_short nNetPort=0;
        int nRet=WSAHtons(lpRTD->m_Socket, (unsigned short)nRTDPort, &nNetPort);
        TRACE(_T("RTDIpxThread: Host Port=%04x  Net Port=%04x RTD Input=%d \n"),nRTDPort, nNetPort, lpRTD->GetInputNumber());
#endif
        // setup address for Sending Data on RTD
        SetupSocketAddress( lpRTD->m_saRTD, nRTDPort );

        // copy address - Why are we copying the address just over right later (in recvfrom() )? -NG
        memcpy(&saFrom.saIPX, &lpRTD->m_saRTD.saIPX, sizeof(SOCKADDR_IPX));

        cbAddr = sizeof(SOCKADDR_IPX);
    }
    else
    {
        // open IP socket
        lpRTD->m_Socket=socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);        // ??? should this use IPPROTO_UDP???
        if (lpRTD->m_Socket == INVALID_SOCKET)
        {
            nReturn = AddSocketErrorToEventViewer( lpRTD);
            bDone = TRUE;
        }

        // Socket must be bound prior to calling recvfrom()
        // setup address
        memset(&saRx.saIP, 0, sizeof(SOCKADDR_IN));
        saRx.saIP.sin_family = AF_INET;                                         // IP type address
        saRx.saIP.sin_port=htons((u_short)nRTDPort);                            // PORT number
        saRx.saIP.sin_addr.s_addr=htonl(INADDR_ANY);                            // ADDRESS number

        // setup for Sending Data on RTD port
        memset(&lpRTD->m_saRTD.saIP, 0, sizeof(SOCKADDR_IN));
        lpRTD->m_saRTD.saIP.sin_family = AF_INET;                       // IP type address
        lpRTD->m_saRTD.saIP.sin_port=htons((u_short)nRTDPort);          // PORT number
        lpRTD->m_saRTD.saIP.sin_addr.s_addr=htonl(INADDR_BROADCAST);    // ADDRESS number

        // copy address - Why are we copying the address just over right later (in recvfrom() )? -NG
        memcpy(&saFrom.saIP, &lpRTD->m_saRTD.saIP, sizeof(SOCKADDR_IN));

        cbAddr = sizeof(SOCKADDR_IN);

        char    szHostName[MAX_PATH+1];
        if (gethostname(szHostName, MAX_PATH)==0)
        {
            hostent *phe=gethostbyname(szHostName);

            dwLocalAddress = *(DWORD*)&phe->h_addr_list[0];
        }
    }   // end IP socket

    if (!bDone)
    {
        // enable broadcasting
        BOOL bOptVal=TRUE;
        nReturn=setsockopt(lpRTD->m_Socket, SOL_SOCKET, SO_BROADCAST, (char *)&bOptVal, sizeof(BOOL));
        if (nReturn == SOCKET_ERROR)
        {
            nReturn=WSAGetLastError();
        }

        // enable reuse of address
        bOptVal=TRUE;
        nReturn=setsockopt(lpRTD->m_Socket, SOL_SOCKET, SO_REUSEADDR, (char *)&bOptVal, sizeof(BOOL));
        if (nReturn == SOCKET_ERROR)
        {
            nReturn=WSAGetLastError();
        }

        // get the socket's max message size
        int nOptSize=sizeof(UINT);
        UINT nMaxMsgSize=600;
        nReturn=getsockopt(lpRTD->m_Socket, SOL_SOCKET, SO_MAX_MSG_SIZE, (char *)&nMaxMsgSize, &nOptSize);
        if (nReturn == SOCKET_ERROR)
        {
            nReturn=WSAGetLastError();
            nMaxMsgSize=600;                // default max size
        }

        nMaxIpIpxBuf=nMaxMsgSize;                           // always create buffer that is as big as the sockets max message size
        pbyIpIpxRxBuf = new char[nMaxIpIpxBuf];     // allocate buffer for receiving data from socket

        if (!pbyIpIpxRxBuf)
            bDone = TRUE;
        else
            memset(pbyIpIpxRxBuf,0,nMaxIpIpxBuf*sizeof(char));

        // bind to address
        nReturn=bind(lpRTD->m_Socket, &saRx.sa, cbAddr);
        if (nReturn == SOCKET_ERROR)
        {
            nReturn = AddSocketErrorToEventViewer(lpRTD);
            bDone = TRUE;
        }

        // send data to indicate startup
        if (lpRTD->m_eProtocol == V7_RTD_ENHANCED)
        {
            int nLen=lpRTD->BuildErrorMsg(V7_ERTD_SERVICE_STARTUP, szErrorCode, sizeof(szErrorCode));
            nReturn=sendto(lpRTD->m_Socket,szErrorCode,nLen, nFlags, &lpRTD->m_saRTD.sa, cbAddr);
            if (nReturn == SOCKET_ERROR)
            {
                nReturn=WSAGetLastError();
            }
        }

    }   // end if not done
}

主要的()

    nFromLen = cbAddr;
    nReturn=recvfrom(lpRTD->m_Socket, pbyIpIpxRxBuf, nMaxIpIpxBuf, nFlags, &saFrom.sa, &nFromLen);
    if(nReturn == SOCKET_ERROR)
    {
        SetupSocket(lpRTD, bDone, saRx, nRTDPort, saFrom, cbAddr, dwLocalAddress, nMaxIpIpxBuf, pbyIpIpxRxBuf,nFlags, FALSE);
        nReturn=recvfrom(lpRTD->m_Socket, pbyIpIpxRxBuf, nMaxIpIpxBuf, nFlags, &saFrom.sa, &nFromLen);
    }

// if i take this out no error....
    nReturn=sendto(lpRTD->m_Socket, szErrorCode, nLen, nFlags, &saFrom.sa, cbAddr);
4

0 回答 0