[RESOLVED] Receiving duplicate udp messages
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 5 of 5

Thread: [RESOLVED] Receiving duplicate udp messages

  1. #1
    Join Date
    Dec 2012
    Location
    England
    Posts
    2,265

    [RESOLVED] Receiving duplicate udp messages

    I have a program that sends broadcast udp messages which runs on a windows 7 computer. I have another program which receives these udp messages. When the receiving program is run on a Windows 7 computer all is well. It receives the broadcast message correctly.

    However when the same receive .exe program is run on a Windows XP computer it receives each message twice. The program below (from the code published from MSDN) demonstrates the problem. If it is run in transmit mode on one computer (XP or Win 7) and a Win7 computer runs it in receive mode then it shows once what was sent. If an XP computer runs it in receive mode then it shows twice what was sent.

    Does any guru have any ideas about this please?

    Code:
    #define WIN32_LEAN_AND_MEAN
    
    #include <winsock2.h>
    #include <Ws2tcpip.h>
    #include <stdio.h>
    
    // Link with ws2_32.lib
    #pragma comment(lib, "Ws2_32.lib")
    
    int udpRec()
    {
    int iResult = 0;
    
    WSADATA wsaData;
    
    SOCKET RecvSocket;
    sockaddr_in RecvAddr;
    
    unsigned short Port = 27015;
    
    char RecvBuf[1024];
    int BufLen = 1024;
    
    sockaddr_in SenderAddr;
    int SenderAddrSize = sizeof (SenderAddr);
    
    	//-----------------------------------------------
    	// Initialize Winsock
    	iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    	if (iResult != NO_ERROR) {
    		printf("WSAStartup failed with error %d\n", iResult);
    		return 1;
    	}
    
    	//-----------------------------------------------
    	// Create a receiver socket to receive datagrams
    	RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    	if (RecvSocket == INVALID_SOCKET) {
    		printf("socket failed with error %d\n", WSAGetLastError());
    		return 1;
    	}
    
    	//-----------------------------------------------
    	// Bind the socket to any address and the specified port.
    	RecvAddr.sin_family = AF_INET;
    	RecvAddr.sin_port = htons(Port);
    	RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    
    	iResult = bind(RecvSocket, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));
    	if (iResult != 0) {
    		printf("bind failed with error %d\n", WSAGetLastError());
    		return 1;
    	}
    
    	for (; ;) {
    
    		//-----------------------------------------------
    		// Call the recvfrom function to receive datagrams
    		// on the bound socket.
    		printf("Receiving datagrams...\n");
    		iResult = recvfrom(RecvSocket, RecvBuf, BufLen, 0, (SOCKADDR *) & SenderAddr, &SenderAddrSize);
    		if (iResult == SOCKET_ERROR) {
    			printf("recvfrom failed with error %d\n", WSAGetLastError());
    		} else {
    			RecvBuf[iResult] = 0;
    			printf("%s\n", RecvBuf);
    		}
    	}
     
    	//-----------------------------------------------
    	// Close the socket when finished receiving datagrams
    	printf("Finished receiving. Closing socket.\n");
    	iResult = closesocket(RecvSocket);
    	if (iResult == SOCKET_ERROR) {
    		printf("closesocket failed with error %d\n", WSAGetLastError());
    		return 1;
    	}
    
    	//-----------------------------------------------
    	// Clean up and exit.
    	printf("Exiting.\n");
    	WSACleanup();
    	return 0;
    }
    
    int udpSend()
    {
    int iResult;
    WSADATA wsaData;
    
    SOCKET SendSocket = INVALID_SOCKET;
    sockaddr_in RecvAddr;
    
    unsigned short Port = 27015;
    
    char SendBuf[1024];
    
    	strcpy(SendBuf, "qwertyuiopasdfghjklzxcvbnm");
    
    int BufLen = strlen(SendBuf);
    
    	//----------------------
    	// Initialize Winsock
    	iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    	if (iResult != NO_ERROR) {
    		printf("WSAStartup failed with error: %d\n", iResult);
    		return 1;
    	}
    
    	//---------------------------------------------
    	// Create a socket for sending data
    	SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    	if (SendSocket == INVALID_SOCKET) {
    		printf("socket failed with error: %ld\n", WSAGetLastError());
    		WSACleanup();
    		return 1;
    	}
    
    	BOOL bBroadcast = TRUE;
    	setsockopt(SendSocket, SOL_SOCKET, SO_BROADCAST, (char *)&bBroadcast, sizeof(BOOL));
    
    	//---------------------------------------------
    	// Set up the RecvAddr structure with the IP address of
    	// the receiver (in this example case "192.168.1.1")
    	// and the specified port number.
    	RecvAddr.sin_family = AF_INET;
    	RecvAddr.sin_port = htons(Port);
    	RecvAddr.sin_addr.s_addr = INADDR_BROADCAST;
    
    	//---------------------------------------------
    	// Send a datagram to the receiver
    	printf("Sending a datagram to the receiver...\n");
    	iResult = sendto(SendSocket, SendBuf, BufLen, 0, (SOCKADDR *) &RecvAddr, sizeof (RecvAddr));
    	if (iResult == SOCKET_ERROR) {
    		printf("sendto failed with error: %d\n", WSAGetLastError());
    		closesocket(SendSocket);
    		WSACleanup();
    		return 1;
    	}
    
    	//---------------------------------------------
    	// When the application is finished sending, close the socket.
    	printf("Finished sending. Closing socket.\n");
    	iResult = closesocket(SendSocket);
    	if (iResult == SOCKET_ERROR) {
    		printf("closesocket failed with error: %d\n", WSAGetLastError());
    		WSACleanup();
    		return 1;
    	}
    
    	//---------------------------------------------
    	// Clean up and quit.
    	printf("Exiting.\n");
    	WSACleanup();
    	return 0;
    }
    
    
    //use from the command line
    //no args is send mode
    //with args is receive mode
    int main(int argc, char *argv[])
    {
    	if (argc > 1)
    		udpRec();
    	else
    		udpSend();
    
    	return 0;
    }
    All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.

  2. #2
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    3,762

    Re: Receiving duplicate udp messages

    This is normal (to a degree), if there are multiple ways to reach the endpoint, you'll receive the message once for each distinctive route.
    UDP has no flow control, if you need to detect duplicates, you need to provide for that.

  3. #3
    Join Date
    Dec 2012
    Location
    England
    Posts
    2,265

    Re: Receiving duplicate udp messages

    Quote Originally Posted by OReubens View Post
    This is normal (to a degree), if there are multiple ways to reach the endpoint, you'll receive the message once for each distinctive route.
    UDP has no flow control, if you need to detect duplicates, you need to provide for that.
    Ah! Thanks. I've already put in code to detect duplicates in the main program as a 'tempory' fix which will now become permanent!
    All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.

  4. #4
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    3,762

    Re: Receiving duplicate udp messages

    Quote Originally Posted by 2kaud View Post
    Ah! Thanks. I've already put in code to detect duplicates in the main program as a 'tempory' fix which will now become permanent!
    Duplicates on UDP multicast isn't an indication of you doing anything wrong per se (it could be), it's part of how UDP works. There might be something wrong with the network configuration if you have multiple routes going to your endpoint. It could be intended, it could point to a configuration error somewhere.
    If packet duplication gets excessive, it may cause delays on the entire network because of collisions and congestion.

    This is why you have tcp which does have flow control and things like handling duplicates on it's own. but this comes at a cost, UDP is faster than TCP.
    And TCP isn't a magic buttlet either, because ultimately TCP runs on top of UDP also, so if you have excessive packet duplication slowing down your network, "changing" to TCP won't help, because under the hood, it'll still be UDP afterall. But depending on the type of application, it might be easier to use TCP which gives you the impression that things arrive in a synchronised/serial fashion.


    BTW. you also need to account for UDP packets arriving out of order, or a packet getting dropped.
    Depending on needs this means storing a later packet until it's predecessor(s) arrive (or request retransmission) or simply continuing with the gap in the data.

    For something like an online game or a stock ticker, a dropped or out of order packet isn't necessarily a problem. If you're receiving a large file and need it to be complete, it is.

  5. #5
    Join Date
    Dec 2012
    Location
    England
    Posts
    2,265

    Re: [RESOLVED] Receiving duplicate udp messages

    BTW. you also need to account for UDP packets arriving out of order, or a packet getting dropped.
    This doesn't matter to the application in question which is why we've using UDP broadcast. There is one sender with multiple receivers. There is one UDP packet sent about every 5 seconds. The only issue is duplicate packets which has been handled. Everything now 'appears' to be working.

    Thanks for the extra info.
    All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Azure Activities Information Page

Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center