2
votes

I'm trying to to figure out how to create a protocol agnostic socket listener in C# - it should grab IPv4 and IPv6 requests. Everything I can find on Google seems to be C. Attempting something similar to what I saw for C, I tried the following code:

/*Socket*/ m_sock = null;
/*IPAddress*/ m_addr = null;
/*int*/ m_port = port; /*port passed to function*/
/*int*/ m_listenqueue = listen_queue_size; /*also passed to function, number of pending requests to allow before busy*/
IPAddress[] addrs = Dns.GetHostEntry("localhost").AddressList;
if(family == null) m_addr = addrs[0];
else
{
    foreach(IPAddress ia in addrs)
    {
        if(ia.AddressFamily == family) /*desired address family also passed as an argument*/
        {
            m_addr = ia;
            break;
        }
    }
}
if(m_addr == null) throw new Exception(this.GetType().ToString() + ".@CONSTRUCTOR@: Listener Initailization Error, couldn't get a host entry for 'localhost' with an address family of " + family.ToString());

m_sock = new Socket(m_addr.AddressFamily, SocketType.Stream, ProtocolType.IP);
/*START "AGNOSTICATION LOGIC"... Tried here...*/
if(m_addr.AddressFamily == AddressFamily.InterNetworkV6) //allow IP4 compatibility
{
    m_sock.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.AcceptConnection, true);
    /*fails*/ m_sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AcceptConnection, true);
    /*fails*/ m_sock.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AcceptConnection, true);
}
/*END "AGNOSTICATION LOGIC" */
IPEndPoint _endpoint = new IPEndPoint(m_addr, m_port);
m_sock.Bind(_endpoint);
/*... tried here*/
m_sock.Listen(m_listenqueue);
/*... and tried here*/

I've tried the logic at the three places marked, and regardless of where I put it, the two listed lines will throw an invalid argument exception.

Can anyone recommend to me how I should make a socket that will listen to both IPv4/IPv6?

1
What about fixing the InvalidArgumentException?Robert Harvey
Bind and Listen methods should be enough, no need for SetSocketOption at all.Anton Kovalenko
This blog post might be of help?Sami Kuhmonen
@Anton Kovalenko - That's what I thought, but this produces a 'Connection Refused' error when others try to connect from IPv4 (if the listener was created using InterNetworkV6) or IPv6 (if the listener was created using InterNetwork).S James S Stapleton
Derived from Sami's comment - m_addr = IPAddress.IPv6Any and m_sock.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false); are both needed for the address and socket options.S James S Stapleton

1 Answers

5
votes

You can use sock.SetSockOption(SocketOptionLevel.IPv6, SocketOptionName.IPV6Only, 0); to set the socket to allow connections with other protocols than IPv6. It will work from Vista onwards.

SocketOptionName documentation