views:

5181

answers:

6

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.

+2  A: 

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.

sysrqb
+13  A: 

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

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

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

sipwiz
The ReuseAddress property is used to enable a server application to listen for connections using the specified address and port number even if they were in use recently. This is used to enable the server to close the listening socket and immediately reopen it without getting an error.
Kalmi
And he wants to bind to the same port twice... So ReuseAddress is not relevant.
Kalmi
Thats incorrect. ReuseAddress means exactly what it says with no conditions about whether the socket is a server or a client. If you want to reuse a port on one socket for SENDING and on one for RECEIVING you can.
sipwiz
"Vote too old to be changed, unless post is edited"... doh... PLease edit the question so that I can vote you up.
Kalmi
sipwiz' original proposal works if you just add the statementudpClient.Client.Bind(localpt);
Cecil Has a Name
Wonderful. I'd tried setting ExclusiveAddressUse to false w/out luck and almost gave up. Once again SO to the rescue.
WaldenL
+1  A: 

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.

Douglas Leeder
The multiple IP address way is a lot more light-weight (and would work well without any performance penalty).
Kalmi
A: 

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.

Mike
"The program that generates these packets is proprietary" and the problem is that it is binding to the same port it is sending to.
Kalmi
+4  A: 

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

It can be done very easily. (Please vode 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);
Kalmi
I'll look into it. Currently we have switched to another program which apparantly allows us to send and receive on the same computer "out of the box", while we can also control that program more easily.So thanks to sipwiz!
Cecil Has a Name
A: 

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