Ошибка Win-Socket UDP без подключения к recvfrom ()

Я работаю над устаревшим приложением VC6, которое использует winsocket для прослушивания UDP-порта для входящих пакетов. Однако я получаю следующие ошибки. Если я использую WSAGetLastError() я получил 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);

1

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …