I have following program in perl which is supposed to listen on IPv6 address, and by theory should serve to both IPv4 (through IPv4 mapped IPv6 address) and IPv6 clients on a dual stack box.
use Socket;
use Socket6;
@res = getaddrinfo('', 8086, AF_UNSPEC, SOCK_STREAM,0, AI_PASSIVE);
my @ipv6Result;
while(scalar(@res)>=5){
my @currentResult = @res;
($family, $socktype, $proto, $saddr, $canonname, @res) = @res;
if($family == AF_INET6){
@ipv6Result = @currentResult;
}
}
if(@ipv6Result){
($family, $socktype, $proto, $saddr, $canonname) = @ipv6Result;
}
socket(Socket_Handle, $family, $socktype,$proto) || next;
bind(Socket_Handle,$saddr ) || die "bind: $!";
listen(Socket_Handle, 1) || die "listen: $!";
$paddr = accept(Client,Socket_Handle) || die "accept: $!";
After running this the netstat gave following observation:
c:\Perl\bin>netstat -nao | findstr 8086
TCP [::]:8086 [::]:0 LISTENING 2892
It seems, it is listening on only IPv6 wildcard address (::) and not on IPv4 wildcard address (0.0.0.0). I was not able to connect this server process from an IPv4 client, but was able to connect through an IPv6 client.
I tried a similar server program in java as follows (on the same setup):
import java.net.ServerSocket;
public class CodeTCPServer {
public static void main(String[] args) throws Exception{
new ServerSocket(8086).accept();
}
}
The netstat output for this was as follows:
C:\Users\Administrator>netstat -nao | findstr 8086
TCP 0.0.0.0:8086 0.0.0.0:0 LISTENING 3820
TCP [::]:8086 [::]:0 LISTENING 3820
Seems to listen on both IPv6 and IPv4, and I am also able to connect it from IPv4 and IPv6 clients.
If I run the same perl program on a linux box it works fine, and I am able to connect to it through IPv4 and IPv6 clients.
I wonder, if something on windows is stopping the perl program from listening on both IPv4 and IPv6 (but then it should have stopped the java program as well for the same reason). If some problem with the program logic it shouldn't have worked on linux as well.
(I am using Socket6 for now, as I couldn't use perl's inbuilt support for IPv6 somehow on windows, I am in communication with the authors to get it worked on my setup)
UPDATE:
I just tried following:
setsockopt (Socket_Handle, IPPROTO_IPV6, IPV6_V6ONLY, 0 ) or print("\nFailed to set IPV6_V6ONLY $! ");
in anticipation that the socket option has default value 1 (for this platform), and I have to manually override it, but alas! I got following error:
Your vendor has not defined Socket macro IPV6_V6ONLY, used at c:\socket6\Socket6Server.pl line 66
Now I wonder what does 'vendor' mean, is it Socket6 module / perl vendor or OS vendor ?
UPDATE2
I think the answer is given in http://metacpan.org/pod/IO::Socket::IP (for the V6Only argument)
with following lines: If your platform does not support disabling this option but you still want to listen for both AF_INET and AF_INET6 connections you will have to create two listening sockets, one bound to each protocol.
And this worked for me! But then I need to check if the platform supports V6Only disabling (protocol aware code in my program :( ), when compared to Java, Java does it automatically for me (checking and creating 2 sockets).