Reusing a Port Number in a Udp

Reusing a port number in a UDP

You should be able to use the SO_REUSEADDR socket option to bind multiple sockets to the same address. But having said that, you don't want to do this because it's not specified which socket will receive incoming data on that port (you would have to check all sockets for incoming data)

The better option is just to use the same socket to send replies - this can safely be done from multiple threads without any additional synchronisation (as you are using UDP).

UDP socket still bound to previous port – how to reuse it?

Unlike with TCP an UDP socket is not lingering around in some temporary state once the socket is closed by the application. What you see means therefore that there is still a process owning a socket bound to this port. This suggest that the application was not fully shutdown but at least one thread of it is still running. Or it might be a forked child which inherited the socket.

While you can create an additional socket with SO_REUSEADDR (see other comments and answers for details) this will not make the already existing socket inactive. Data send to this port will end up at only one of the existing sockets and will not be propagated to all. This might lead to data loss.

Linux UDP Socket/Port Reuse

Do I need to do any locking between the two sockets or is that handled
in the OS? That is, can I send data concurrently to both sockets and
not get some weird collisions since both use the same port?

For UDP, locking isn't necessary. That said, you may still find it easier to simply create a separate socket for each thread, if only because safely co-ordinating the shutdown and destruction of a socket that is in use by multiple threads can be a bit tricky.

Do I need to worry about Thread 2 receiving data that is sent out by
either of the "sender" threads? How do I prevent this?

Yes, Thread 2 is likely to see the broadcast packets at least, and possibly the unicast packets as well (if they ever get sent to the computer that thread 2 is running on). The easiest way to avoid that would be to listen on a different port instead (e.g. send your broadcast packets to port X, but have the clients send their unicast reply packets back to port X+1; that way any packet you receive on port X+1 is almost certainly a unicast reply from a client)

Are there any options that I need to enable to make this work?

Just the SO_BROADCAST one, AFAIK. (if you wanted several sockets on the same machine to listen to the same port, you'd also need to do SO_REUSEADDR and [under MacOS/X] SO_REUSEPORT, but hopefully you don't need that)

Does it matter if the broadcast socket (socket_a) gets set up prior to the
unicast one (socket_b)?

No, the ordering should not matter.

Should I create a dedicated "receive" socket on port X? That is, would
it make sense to have a socket that is solely used to receive data?
This is the only socket that would have bind() called on it.

You could do that, but having the same socket send and receive will work as well. (Note that if you use blocking I/O you have to watch out for things like recv() not returning for a long time, which can prevent your thread from doing anything else like sending in the meantime -- which is why I almost always use non-blocking I/O and select() in my programs. That way it's possible to do everything I want using a single thread, which allows me to avoid all of the non-determinism and potential race conditions and deadlocks that come with multiple threads)

Are there any other issues I should be worried about given that all
three threads are using the same port? Unfortunately, this is a
constraint that I am working with. If the above scheme is impossible,
I may have to revisit my one port design.

Using a single port will work, just be prepared to receive your own broadcast packets back on it (i.e. don't go into a feedback loop when that happens).

Reuse UdpClient vs Disposing it

I should recommend again about using Sockets directly, it gives you a lot of flexibility. Check out the following example that uses one socket for UDP connections for both sending and receiving:

    private static readonly List<EndPoint> clients = new List<EndPoint>();
private static readonly SocketAsyncEventArgs receiveEventArgs = new SocketAsyncEventArgs();
private static Socket socket;

private static void Main(string[] args)
{
receiveEventArgs.Completed += OnReceive;
socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
socket.Bind(new IPEndPoint(IPAddress.Any, 6000));
Receive();

while (true)
{
Thread.Sleep(3000);
lock (clients)
{
foreach (var endPoint in clients)
socket.SendTo(Encoding.ASCII.GetBytes("PING"), endPoint);
}
}
}

private static void Receive()
{
receiveEventArgs.SetBuffer(new byte[256], 0, 256);
receiveEventArgs.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 6000);
socket.ReceiveFromAsync(receiveEventArgs);
}

private static void OnReceive(object sender, SocketAsyncEventArgs e)
{
if (e.BytesTransferred > 0)
{
// Is reply?
var isReply = true/false;
if (isReply)
{
// Do domething
}
else
lock (clients)
{
clients.Add(e.RemoteEndPoint);
}
}
else
{
lock (clients)
{
clients.Remove(e.RemoteEndPoint);
}
}
Receive();
}

How to open the two udp client socket with same local port

Contrary to all the commentary, all you have to do is set the socket option SO_REUSEPORT prior to the bind().



Related Topics



Leave a reply



Submit