Sending and receiving UDP packets between two programs on the same computer

Viewed 61911

Is it possible to get two separate programs to communicate on the same computer (one-way only) over UDP through localhost/127... by sharing the same port #?

We're working on a student project in which we need to send UDP packets containing some telemetry between two computers. The program that generates these packets is proprietary, but I'm working on the receiver program myself with C# using System.Net.Sockets.UdpClient and System.Net.IPEndPoint.

This works fine during our group's meetings when we have multiple computers connected on which we can run the two programs separately. But it's not very useful when I'm home and trying to expand on the telemetry processing program as I only have one computer (I need a feed for testing the processing program). I can not install the program on any of the school's computers either.

When I try to run both programs on my computer at the same time (starting my program last) I get a SocketException saying that only a single use of each port is normally allowed. Which leads me to believe there must be some way to share the port (although it makes sense that only a single program can use port on a computer at any one time, I have no trouble running multiple internet browsers at the same time (and I suppose they use port 80 for http)).

REEDIT of the EDIT:

sipwiz was right, and thanks to Kalmi for the pointer to UdpClient.Client.Bind(). At the time, though, we are considering using another program that generates similar packets, and with which we are able to share port with on the same computer using my first (although naive) approach with the UDP client binding in the ctor. Sorry for having to unmark your answer, sysrqb.

8 Answers

You can bind to a port multiple times using the ReuseAddress socket option.

UdpClient udpClient = new UdpClient();
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

You'll need to set the same option on the UDP server socket as well.

I did not expect this to be possible, but.. well.. sipwiz was right.

It can be done very easily. (Please vote sipwiz's answer up!)

IPEndPoint localpt = new IPEndPoint(IPAddress.Any, 6000);

//Failed try
    try
    {
        var u = new UdpClient(5000);
        u.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

        UdpClient u2 = new UdpClient(5000);//KABOOM
        u2.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    }
    catch (Exception)
    {
        Console.WriteLine("ERROR! You must call Bind only after setting SocketOptionName.ReuseAddress. \n And you must not pass any parameter to UdpClient's constructor or it will call Bind.");
    }

//This is how you do it (kudos to sipwiz)
    UdpClient udpServer = new UdpClient(localpt); //This is what the proprietary(see question) sender would do (nothing special) 

    //!!! The following 3 lines is what the poster needs...(and the definition of localpt (of course))
    UdpClient udpServer2 = new UdpClient();
    udpServer2.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    udpServer2.Client.Bind(localpt);

You might be able to put multiple IP addresses on your network card, or loopback, and bind the server and client to different IP addresses?

Or else the Virtual machine approach will definitely work.

Only one program can bind to a port at a time. Multiple programs can connect to one port on another system's, but the local port your different web browsers have bound themselves to is randomly assigned.

Unless you want to do some ugly inter-process communication or packet sniffing, there's no way to have multiple programs bound to one port.

My advice: don't pass the port number into the UdpClient constructor. From the documentation, (somewhat sparse, I know...) it looks like if you do, the UdpClient will try to bind to that port (which, as sysrqb mentioned, is not allowed). (If you don't, I believe the UdpClient will listen on a random port for any replies. You could also pick a port you know to be unused.)

When you call Connect() you need to pass in the port number the server is listening on.

bind the two programs,ie, the sender and receiver to the same port on the localhost.dats the simple answer.

Related