我正在开发一个遗留的 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);