Only one use of each socket address (proto/ip/port

2020-02-06 17:13发布

问题:

Good day all

Info:

Topic: Multicast

First off, I have found the solution but I do not understand why this is the solution.

**Scope : ** (removing any cluttering/unnecessary code)

new_socket()
{
    //SND_LOCAL_IP = 10.0.0.30 - local network adapter's IP
    //SND_MCAST_PORT = 80 port used to broadcast Multicast Packets 

    //_SND_LOCAL_EP = new IPEndPoint(SND_LOCAL_IP, SND_MCAST_PORT);  <problem>                                       
    _SND_LOCAL_EP = new IPEndPoint(SND_LOCAL_IP, 0);                 <fixed>    
}

init_socket()
{
    _SND_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
    _SND_Socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(_SND_MCAST_IP, _SND_LOCAL_IP));
    _SND_Socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.ReuseAddress, true);
    _SND_Socket.ExclusiveAddressUse = false;
    _SND_Socket.Bind(_SND_LOCAL_EP);      <<< ====== PROBLEM LINE=====
}

The problem:

My listener runs on a Thread seperately, on a form_load event, thus it initializes in the same way as my SND_Socket does, however changing the SND_Socket.Bind() port to 0 allows me to recieve these Multicast packets.

As by the def MSDN, adding the ExclusiveAddress should not alleviate this problem (since the recieve and send sockets are initialized in the same way).

true if the Socket allows only one socket to bind to a specific port; otherwise, false. The default is true for Windows Server 2003 and Windows XP Service Pack 2, and false for all other versions.

and further on, in Remarks this is confirmed:

If ExclusiveAddressUse is false, multiple sockets can use the Bind method to bind to a specific port; however only one of the sockets can perform operations on the network traffic sent to the port. If more than one socket attempts to use the Bind(EndPoint) method to bind to a particular port, then the one with the more specific IP address will handle the network traffic sent to that port.

If ExclusiveAddressUse is true, the first use of the Bind method to attempt to bind to a particular port, regardless of Internet Protocol (IP) address, will succeed; all subsequent uses of the Bind method to attempt to bind to that port will fail until the original bound socket is destroyed.

This property must be set before Bind is called; otherwise an InvalidOperationException will be thrown.

Why does the

Socket.ExclusiveAddress = false

not allow the SND_Socket to listen on this IP and port as "Listener_Socket", furthermore why does setting port to 0 in the RCV_Socket.Bind() solve this problem?

回答1:

Without a good Minimal, Complete, and Verifiable Example it's impossible to know for sure what problem you're even having specifically, never mind know for sure what the cause would be. Lacking that, some observations/comments related to the question as stated:

  1. The ExclusiveAddressUse property affects not the socket on which it's set, but any other socket bound after that socket. It prevents any other socket from using the same port number, i.e. which it would otherwise be able to do through the ReuseAddress socket option.
  2. The ReuseAddress socket option does affect the socket on which it's set. It's what allows a socket to bind to the same port that some other socket on the same adapter had already been bound.
  3. One would typically not use both of those options at the same time. Either you want the sockets to cooperate, where one allows the other to reuse the same port number, or you want to prohibit any other socket from using the same port number.
  4. Binding to port 0 can in some cases alleviate issues that might otherwise occur when misusing the address-exclusivity options. With the incomplete question, I cannot infer what specific problem you are having. But binding to port 0 causes the socket to select a unique port number, which will of course avoid any problems with port number conflicts.
  5. Other than that, the biggest issue I see in your code is that you are attempting to join the multicast group before you call Bind(). You should be doing it the other way around, i.e. bind the socket, and then join the multicast group.
  6. Most likely, you should not be using ReuseAddress at all. Your sockets should have unique port numbers. You may use ExclusiveAddressUse, as a preventative measure to ensure you get an exception if some code does try to bind a socket to a port that's already in use.

I recommend that you start by closely following the example found on MSDN on the documentation page for the MulticastOption Class. Once you have a working example using that code, then you can adjust the code to suit your specific needs.