Prev: Problem in porting from 32 bit to 64 bit application
Next: Set window position on multiple monitors
From: Gary C on 19 May 2010 03:48 Apologies in advance if this newsgroup is considered not relevent, if so please suggest one that is. I have a situation where i need to receive UDP multicasts on a computer that has multiple network cards. The problem i am experiencing is that the udp packets are arriving on the network card of interest (i have run a network analysis application to verify this) but something is blocking the data from arriving on the open socket. Following the advice from an older post i have run TDIMon.exe also and can confirm that the 'TDI_EVENT_RECEIVE_DATAGRAM' message is not reported when the messages are not received which as i understand it implies that the received data is being blocked somewhere in the protocol stack. If i disable the other network cards the messages get through. I have tried the same broadcast code against a program that uses a third party UDP comms component under the same network conditions and the multicast is received successfully so i strongly suspect i am doing something wrong in my winsock udp code. I have stripped the code out of a much larger application that is experiencing this problem into a console application and can confirm the same behaviour (code listing to follow). Any help would be greatly appreciated, the environment is Windows XP SP2, the code is compiled under BCB2007 but #pragmas aside it should compile under most windows c ++ compilers. In the version given below i am using 'INADDR_ANY' as the transmission host address, this is from a machine with a single network card, the same behaviour was achieved when using 'szHostAddress'. If i run the application with option 1 on the system with multiple active cards it will listen for multicast data on '234.5.6.7', if i then run the application on a networked system with option 2 the application sends the sample message 10 times before returning, the listener does not pick up the transmissions. If i disable the additional cards on the listener and re-run the listener application it receives the messages. I did also notice (although the test app below will not reproduce the scenario) that one the receive socket is open on the system with the network cards disabled, if i then re-enable them transmissions are received, if the socket is closed and a new one opened however the transmissions are no longer received. In all scenarios i have confirmed that the UDP packets are arriving on the listeners network. Once again all suggestions would be greatly appreciated. Many thanks Gary //--------------------------------------------------------------------------- //-UDP_TESTAPP //--------------------------------------------------------------------------- #include <iostream.h> #include <winsock2.h> #include <ws2tcpip.h> //--------------------------------------------------------------------------- bool InitialiseWinsock(); void CleanupWinsock(); int main_client(); int main_server(); //--------------------------------------------------------------------------- // definitions const char* szHostAddress = "10.10.10.7"; const char* szMultiAddress = "234.5.6.7"; const char* szMessage = "Sample multicast message!"; const int iMaxBuffer= 500; const int iPortNumber = 50326; //--------------------------------------------------------------------------- // globals SOCKET g_Socket = INVALID_SOCKET; #pragma hdrstop //--------------------------------------------------------------------------- #pragma argsused //--------------------------------------------------------------------------- int main(int argc, char* argv[]) { int choice = 0; while (choice != 3) { cout <<"Enter choice:"<< endl << "1)Run UDP multicast listener." << endl << "2)Run UDP multicast transmitter." << endl<< "3)quit" << endl; cin >> choice; switch(choice) { case 1: main_server(); break; case 2: main_client(); break; default: choice = 3; break; } }; return 0; } //--------------------------------------------------------------------------- int main_client() { if (!InitialiseWinsock()) { return -1; } // create our socket g_Socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (INVALID_SOCKET == g_Socket) { cerr << "Failed to create socket, WSAGetLastError returned " << WSAGetLastError() << endl; CleanupWinsock(); return -1; } // allow use of address already in use int iReuse = 1; if (0 != setsockopt(g_Socket, SOL_SOCKET, SO_REUSEADDR, (char*)&iReuse, sizeof(int))) { cerr << "Failed to set option 'SO_RESUEADDR' on socket, WSAGetLastError " "returned " << WSAGetLastError() << endl; CleanupWinsock(); return -1; } SOCKADDR_IN SockAddr; // initialise memset(&SockAddr, 0, sizeof(SOCKADDR_IN)); // populate SockAddr.sin_family = AF_INET; // SockAddr.sin_addr.s_addr = inet_addr(szHostAddress); SockAddr.sin_addr.s_addr = htonl(INADDR_ANY); SockAddr.sin_port = htons(iPortNumber); // bind to the socket if (0 != bind(g_Socket, (const sockaddr*)&SockAddr, sizeof(SOCKADDR_IN))) { cerr << "Failed to bind socket for transmission. WSAGetLastError " "returned " << WSAGetLastError() << endl; CleanupWinsock(); return -1; } IN_ADDR iAddr; iAddr.s_addr = inet_addr(szHostAddress); if (0 != setsockopt(g_Socket, IPPROTO_IP, IP_MULTICAST_IF, (char*)&iAddr, sizeof(IN_ADDR))) { cerr << "Failed to set option 'IP_MULTICAST_IF' on socket, WSAGetLastError " "returned " << WSAGetLastError() << endl; CleanupWinsock(); return -1; } // N.B. this sets a limit on router hops for the multicast after which the // message is discarded. On a direct connection to a DIU there are no routers // so this does not have to be set (its default value of 1 is sufficient) // int iTTL = 3; // set to whatever is required for network // if (0 != setsockopt(g_Socket, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&iTTL, // sizeof(int))) { // cerr << "Failed to set option 'IP_MULTICAST_TTL' on socket, WSAGetLastError " // "returned " << WSAGetLastError() << endl; // CleanupWinsock(); // return -1; // } // prepare the destination address SOCKADDR_IN DestAddr; // initialise memset(&DestAddr, 0, sizeof(SOCKADDR_IN)); // populate DestAddr.sin_family = AF_INET; DestAddr.sin_addr.s_addr = inet_addr(szMultiAddress); DestAddr.sin_port = htons(iPortNumber); int iLen = strlen(szMessage); int iCount = 0; int iMax = 10; const char* pDataBuf = szMessage; cout << "Sending '" << szMessage << "' " << iMax << " times." << endl; while (1) { if (iLen != sendto(g_Socket, pDataBuf, iLen, 0, (const sockaddr*)&DestAddr, sizeof(SOCKADDR_IN))) { cerr << "Failed to send expected " << iLen << " bytes. " "WSAGetLastError returned " << WSAGetLastError() << endl; break; } iCount += 1; if (iCount > 10) { break; } if (iCount > 1) { cout << ", " << iCount; } else { cout << iCount; } Sleep(100); }; // final cleanup CleanupWinsock(); return 0; } //--------------------------------------------------------------------------- int main_server() { if (!InitialiseWinsock()) { return -1; } // create our socket g_Socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (INVALID_SOCKET == g_Socket) { cerr << "Failed to create socket, WSAGetLastError returned " << WSAGetLastError() << endl; CleanupWinsock(); return -1; } SOCKADDR_IN SockAddr; // initialise memset(&SockAddr, 0, sizeof(SOCKADDR_IN)); // populate SockAddr.sin_family = AF_INET; SockAddr.sin_addr.s_addr = htonl(INADDR_ANY); SockAddr.sin_port = htons(iPortNumber); // bind to the socket if (0 != bind(g_Socket, (const sockaddr*)&SockAddr, sizeof(SOCKADDR_IN))) { cerr << "Failed to bind socket for reception. WSAGetLastError " "returned " << WSAGetLastError() << endl; CleanupWinsock(); return -1; } ip_mreq mreq; mreq.imr_multiaddr.s_addr = inet_addr(szMultiAddress); mreq.imr_interface.s_addr = htonl(INADDR_ANY); if (0 != setsockopt(g_Socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mreq, sizeof(ip_mreq))) { cerr << "Failed to set option 'IP_ADD_MEMBERSHIP' on socket, WSAGetLastError " "returned " << WSAGetLastError() << endl; CleanupWinsock(); return -1; } int iLen = strlen(szMessage); int iCount = 0; int iMax = 10; char buffer[iMaxBuffer]; int iSockAddrLen = sizeof(SOCKADDR_IN); cout << "Listening for '" << iMax << "' multicast messages on '" << szMultiAddress << "'..."<< endl; while (1) { iLen = recvfrom(g_Socket, buffer, iMaxBuffer, 0, (sockaddr*)&SockAddr, &iSockAddrLen); if (iLen > 0) { iCount += 1; cout << "Received message #" << iCount << " : " << (const char*)buffer << endl; } if (iCount > iMax) { break; } Sleep(100); }; // final cleanup CleanupWinsock(); return 0; } //--------------------------------------------------------------------------- bool InitialiseWinsock() { WORD wVersionRqd; WSADATA wsaData; // set the version wVersionRqd = MAKEWORD(2,2); if (0 != WSAStartup(wVersionRqd, &wsaData)) { cerr << "Call to WSAStartup failed, WSAGetLastError returned " << WSAGetLastError() << endl; return false; } return true; } //--------------------------------------------------------------------------- void CleanupWinsock() { if (INVALID_SOCKET != g_Socket) { if (0 != shutdown(g_Socket, SD_BOTH)) { cerr << "shutdown call failed for socket, WASGetLastError returned " << WSAGetLastError() << endl; } if (0 != closesocket(g_Socket)) { cerr << "closesocket call failed for socket, WASGetLastError " "returned " << WSAGetLastError() << endl; } g_Socket = INVALID_SOCKET; } if (0 != WSACleanup()) { cerr << "WSACleanup call failed, WSAGetLastError returned " << WSAGetLastError() << endl; } }
From: Gary C on 19 May 2010 07:34 Just in case anyone was looking at this i have resolved the problem i was having, sort of anyway. If i open my 'listen' socket on a specific interface address and, when i join the multicast group, set the interface address to the same specific address (with the source address being set to the multicast address as before) i can successfully pick up the multicast broadcasts. Previously i was always joining the multicast group with 'any' interface regardless of whether or not my socket was opened on a specific interface or a named one which i accept is why it was failing to pick up packets on a socket bound to a specific interface, i presume that this is down to a mismatch between the socket level and IPPROTO_IP settings. Am i correct in thinking that a '0.0.0.0' socket listening for multicast broadcasts on a '0.0.0.0' interface with more than one interface available may not receive the broadcasts because of the volume of network traffic, if this was the case i would have thought i would have seen the occasional broadcast get through. Named interfaces are fine for my current application but if there are any UDP experts out there who see the problems i encountered as obvious it would be great to hear an explanation. Many thanks Gary
|
Pages: 1 Prev: Problem in porting from 32 bit to 64 bit application Next: Set window position on multiple monitors |