Just a quick implementation using the API WSAConnectByName. I'm doing some IPv6 stuff, needed to test connectivity to IPv6 sites but also wanted something to do IPv4 at the same time so leveraging the dual winsock stack capabilitites present in Windows Vista and up the WSAConnectByName came in handy to do this. Its the MSDN sample (http://msdn.microsoft.com/en-us/library ... s.85).aspx) converted for PureBasic (which does not at this time do IPv6).
The _ thing for an API function, you can use that too in some of the API calls with socket_, setsockopt_, closesocket_, WSAStartup_, and WSACleanup_, if you prefer

Winsock version 2.2 is started up first, then the procedure is called with the site named address (in the form 'www.somesite.com') and the port service name (e.g. http which is the name for port 80) or the actual port number (in a string). Then a dual use socket for both Ipv4 and Ipv6 is created and WSAConnectByName is used to make a fast connection to the named site to check for IPv4 or IPv6 connectivity (depending on the site). If connection is sucessful it returns #True, then the socket is closed and the procedure returns.
Code: Select all
#IPV6_V6ONLY = 27 ;Treat wildcard bind as AF_INET6-only
#SO_UPDATE_CONNECT_CONTEXT = $7010
#IPPROTO_ICMPV6 = 58
#IPPROTO_TCP = 6
#AF_INET6 = 23
#IPPROTO_IPV6 = 41
#IPV6_V6ONLY = 27
Prototype Psocket(af, type, protocol)
Prototype Psetsockopt(s, level, optname, optval, optlen)
Prototype Pclosesocket(s)
Prototype PWSAStartup(wVersionRequested, lpWSAData)
Prototype PWSACleanup()
Prototype PWSAGetLastError()
Prototype PWSAConnectByName(s, nodename, servicename, LocalAddressLength, LocalAddress, RemoteAddressLength, RemoteAddress, timeout, Reserved)
Global socket.Psocket
Global setsockopt.Psetsockopt
Global closesocket.Pclosesocket
Global WSAStartup.PWSAStartup
Global WSACleanup.PWSACleanup
Global WSAGetLastError.PWSAGetLastError
Global WSAConnectByName.PWSAConnectByName
Lib_Winsock = OpenLibrary(#PB_Any,"ws2_32.dll")
If IsLibrary(Lib_Winsock)<> 0
init_Winsock = #True
WSAStartup.PWSAStartup=GetFunction(Lib_Winsock,"WSAStartup")
WSACleanup.PWSACleanup=GetFunction(Lib_Winsock,"WSACleanup")
WSAGetLastError.PWSAGetLastError=GetFunction(Lib_Winsock,"WSAGetLastError")
socket.Psocket=GetFunction(Lib_Winsock,"socket")
setsockopt.Psetsockopt=GetFunction(Lib_Winsock,"setsockopt")
closesocket.Pclosesocket=GetFunction(Lib_Winsock,"closesocket")
CompilerIf #PB_Compiler_Unicode ; if compiled in unicode use this
WSAConnectByName.PWSAConnectByName=GetFunction(Lib_Winsock,"WSAConnectByNameW")
CompilerElse ; if not compiled in unicode use this
WSAConnectByName.PWSAConnectByName=GetFunction(Lib_Winsock,"WSAConnectByNameA")
CompilerEndIf
EndIf
; Structure SOCKADDR_STORAGE ;->Structure SOCKADDR_STORAGE
; ss_family.l
; __ss_pad1.c[6]
; __ss_align.q
; __ss_pad2.c[112]
; EndStructure
Macro MAKEWORD(a, b)
(a & $FF)|((b & $FF)<<8)
EndMacro
Procedure OpenAndConnect(Node_Name$)
ConnSocket = #INVALID_SOCKET
ipv6only = 0 ; 0 = IPv4 and IPv6 ------ 1 = IPv6 only
iResult.i
iResultopt.i
iResultoptII.i
bSuccess.b
;LocalAddr.SOCKADDR_STORAGE ; uncomment if needed for getting addresses
;RemoteAddr.SOCKADDR_STORAGE
;dwLocalAddr.i = SizeOf(LocalAddr)
;dwRemoteAddr.i = SizeOf(RemoteAddr)
NodeName$ = Node_Name$
PortName$ = "http"
timeout = 10000
ConnSocket = socket(#AF_INET6, #SOCK_STREAM, 0)
If ConnSocket = #INVALID_SOCKET
ProcedureReturn #INVALID_SOCKET
EndIf
iResultopt = setsockopt(ConnSocket, #IPPROTO_IPV6, #IPV6_V6ONLY, @ipv6only, SizeOf(ipv6only) )
If iResultopt = #SOCKET_ERROR
bSuccess = #False
Else
; note - read the MSDN, if the remote and local address are #Null the dont need the structure or dwLocalAddr and dwRemoteAddr variables as they are ignored in this case
; uncomment to use and put the LocalAddr and RemoteAddr back in the function
bSuccess = WSAConnectByName(ConnSocket, @NodeName$, @PortName$, @dwLocalAddr, #Null, @dwRemoteAddr, #Null, #Null, #Null)
If bSuccess = #False
bSuccess = #False
Else
bSuccess = #True
EndIf
EndIf
iResultoptII = setsockopt(ConnSocket, #SOL_SOCKET, #SO_UPDATE_CONNECT_CONTEXT, #Null, 0)
If iResultoptII = #SOCKET_ERROR
bSuccess = #False
Else
bSuccess = #True
EndIf
closesocket(ConnSocket)
ProcedureReturn bSuccess
EndProcedure
;url_d$ = "www.ipv6forum.com"
wVersionRequested.w = MAKEWORD(2,2)
WSAStart.i = WSAStartup(wVersionRequested,@wsaData.WSADATA) ; starts up winsock v 2.2 in wVersionRequested
PortName$ = "http"
NodeName$ = "www.google.com"
Debug OpenAndConnect(NodeName$)
; NodeName$ = "www.yahoo.com"
; Debug OpenAndConnect(NodeName$)
NodeName$ = "ipv6.google.com"
Debug OpenAndConnect(NodeName$)
NodeName$ = "www.ipv6ready.org"
Debug OpenAndConnect(NodeName$)
NodeName$ = "test-ipv6.com"
Debug OpenAndConnect(NodeName$)
NodeName$ = "2607:f8b0:4002:c05::67" ; ipv6 address for ipv6.google.com
Debug OpenAndConnect(NodeName$)
WSACleanup()
If Lib_Winsock : CloseLibrary(Lib_Winsock) : EndIf