URLInfo is a complete Internet application (with VB source code) which is using winsock functions and types (structures) directly, without any ocx (winsock.ocx). The goals of the program are:
And now we'll delve into the source code of the program. I'm using a single form (frmMain) which is containing all the declarations, functions and controls. There are declarations of the functions declared from "wsock32.dll" and constants and types structures used by these functions.
Private Const IP_STATUS_BASE As Long = 11000 Private Const IP_SUCCESS As Long = 0 Private Const IP_BUF_TOO_SMALL As Long = (11000 + 1) Private Const IP_DEST_NET_UNREACHABLE As Long = (11000 + 2) Private Const IP_DEST_HOST_UNREACHABLE As Long = (11000 + 3) Private Const IP_DEST_PROT_UNREACHABLE As Long = (11000 + 4) Private Const IP_DEST_PORT_UNREACHABLE As Long = (11000 + 5) Private Const IP_NO_RESOURCES As Long = (11000 + 6) Private Const IP_BAD_OPTION As Long = (11000 + 7) Private Const IP_HW_ERROR As Long = (11000 + 8) Private Const IP_PACKET_TOO_BIG As Long = (11000 + 9) Private Const IP_REQ_TIMED_OUT As Long = (11000 + 10) Private Const IP_BAD_REQ As Long = (11000 + 11) Private Const IP_BAD_ROUTE As Long = (11000 + 12) Private Const IP_TTL_EXPIRED_TRANSIT As Long = (11000 + 13) Private Const IP_TTL_EXPIRED_REASSEM As Long = (11000 + 14) Private Const IP_PARAM_PROBLEM As Long = (11000 + 15) Private Const IP_SOURCE_QUENCH As Long = (11000 + 16) Private Const IP_OPTION_TOO_BIG As Long = (11000 + 17) Private Const IP_BAD_DESTINATION As Long = (11000 + 18) Private Const IP_ADDR_DELETED As Long = (11000 + 19) Private Const IP_SPEC_MTU_CHANGE As Long = (11000 + 20) Private Const IP_MTU_CHANGE As Long = (11000 + 21) Private Const IP_UNLOAD As Long = (11000 + 22) Private Const IP_ADDR_ADDED As Long = (11000 + 23) Private Const IP_GENERAL_FAILURE As Long = (11000 + 50) Private Const MAX_IP_STATUS As Long = (11000 + 50) Private Const IP_PENDING As Long = (11000 + 255) Private Const PING_TIMEOUT As Long = 500 Private Const MIN_SOCKETS_REQD As Long = 1 Private Const SOCKET_ERROR As Long = -1 Private Const INADDR_NONE As Long = &HFFFFFFFF Private Const AF_Inet As Long = 2 Private Const SockStream As Long = 1 Private Const lWinsockVersion As Integer = 1 Private Type WSAData wVersion As Integer wHighVersion As Integer szDescription As String * 257 szSystemStatus As String * 129 iMaxSockets As Integer iMaxUdpDg As Long lpVendorInfo As Long End Type Private Type Hostent h_name As Long h_aliases As Long h_addrtype As Integer h_length As Integer h_addr_list As Long End Type Private Type SockAddr_In sin_family As Integer sin_port As Integer sin_addr As Long sin_zero As String * 8 End Type Private Type ICMP_OPTIONS Ttl As Byte Tos As Byte Flags As Byte OptionsSize As Byte OptionsData As Long End Type Private Type ICMP_ECHO_REPLY Address As Long status As Long RoundTripTime As Long DataSize As Long 'Reserved As Integer DataPointer As Long Options As ICMP_OPTIONS Data As String * 250 End Type Private Declare Function WSAStartup Lib "wsock32.dll" ( _ ByVal a As Long, b As WSAData) As Integer Private Declare Function WSACleanup Lib "wsock32.dll" () As Integer Private Declare Function inet_ntoa Lib "wsock32.dll" (ByVal inn As Long) As Long Private Declare Function inet_addr Lib "wsock32" (ByVal cp As String) As Long Private Declare Function gethostbyname Lib "wsock32.dll" (ByVal name As String) As Long Private Declare Function gethostbyaddr Lib "wsock32" _ (addr As Long, ByVal nLen As Long, ByVal ntype As Long) As Long Private Declare Function WSAGetLastError Lib "wsock32.dll" () As Integer Private Declare Function lstrlen Lib "kernel32" Alias "lstrlenA" (ByVal lpString As String) As Long Private Declare Function Socket Lib "wsock32.dll" Alias "socket" ( _ ByVal af As Long, ByVal typesock As Long, ByVal protocol As Long) As Integer Private Declare Function htons Lib "wsock32.dll" (ByVal a As Long) As Integer Private Declare Function connect Lib "wsock32.dll" ( _ ByVal sock As Long, sockstruct As SockAddr_In, ByVal structlen As Long) As Integer Private Declare Function Send Lib "wsock32.dll" Alias "send" ( _ ByVal sock As Long, ByVal msg As String, ByVal msglen As Long, _ ByVal flag As Long) As Integer Private Declare Function recv Lib "wsock32.dll" ( _ ByVal sock As Long, ByVal msg As String, ByVal msglen As Long, _ ByVal flag As Long) As Integer Private Declare Function closesocket Lib "wsock32.dll" (ByVal sock As Long) As Integer Private Declare Function IcmpCreateFile Lib "icmp.dll" () As Long Private Declare Function IcmpCloseHandle Lib "icmp.dll" _ (ByVal IcmpHandle As Long) As Long Private Declare Function IcmpSendEcho Lib "icmp.dll" _ (ByVal IcmpHandle As Long, _ ByVal DestinationAddress As Long, _ ByVal RequestData As String, _ ByVal RequestSize As Long, _ ByVal RequestOptions As Long, _ ReplyBuffer As ICMP_ECHO_REPLY, _ ByVal ReplySize As Long, _ ByVal Timeout As Long) As Long Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _ Destination As Any, Source As Any, ByVal Length As Long) Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" _ (ByVal hwnd As Long, ByVal lpOperation As String, _ ByVal lpFile As String, ByVal lpParameters As String, _ ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long Private Const SW_MAXIMIZE = 3The last 2 function doesn't pertain to winsock library but they are used into the program. Many parameters or type members are pointers (the addresses of a variable) and as we know VB haven't functions to handle pointers. All the job can be made using RtlMoveMemory function from Kernel32.dll, in a pretty unorthodox way. Also, there are some declarations from "icmp.dll" used for pinging the site. The constants which start "IP_" are need for results codes from ping function.
First, let's look what the URL format means and how to convert it. Unless you own your own web site with its own domain name, you may not realize that all Web addresses really are numeric: when a web site is created, it's normally listed with a special "registrar" who is authorized to run a Domain Name Server. This server contains a huge lookup table that associates a normal-sounding name with the web site's true numeric address.
For example, http://www.yahoo.com is really site number "209.238.38.127." If you click on http://209.238.38.127 (or enter in your browser's address line), you'll still go to yahoo.com exactly the same as if you'd clicked on http://www.yahoo.com . The more familiar URL format (www.yahoo.com) is really nothing more than an alias provided solely for human convenience, because it's much easier to remember than a string of numbers.
But it's the numbers that matter: When you enter or click on a URL like www.yahoo.com, your browser actually asks a Domain Name Server for the real numeric address of the site, and then uses the numeric address to find the page you want. (By the way: Now you know what your browser means when it gives you a "DNS Not Found" error: It couldn't find the correct Domain Name Server, or couldn't find the correct site entry within the server, and thus didn't know how to find the site you were looking for.)
With a bit of deep-geek manipulation, those numeric addresses can be converted into a variety of formats. For example, the four groups of three digits in a site's real numeric address are based on powers of 256; from left to right, each group of digits represents itself times 256 to the zero, first, second, and third, respectively .
I'll do the math for you, but you can see that Yahoo.Com's "216.32.74.55" address can be expanded into 216*16777216 + 32*65536 + 74*256+ 55, and that adds up to 3625994807. And in fact, http:// 3625994807/ also gets you to Yahoo.Com.
But there's still more: If you're looking for real obscurity the human-friendly decimal (base ten) digits also can be translated into their computer-friendly hexadecimal (base 16) equivalents; and the numbers and punctuation also can be represented as ASCII computer code. Thus, http://www.yahoo.com can be shown in all these ways, which function identically, and bring you to exactly the same place:
For these conversions there are some functions:
Private Function Convert1(s As String) As String On Error Resume Next If s = "" Then Exit Function Dim a() As String a = Split(s, ".") If UBound(a) <> 3 Then MsgBox "Address incorrect format (xxx.xxx.xxx.xxx)", , "Error" Else Convert1 = CDbl(a(3)) + CDbl(a(2)) * 256 + CDbl(a(1)) * 65536 + CDbl(a(0)) * 16777216 End If End Function Private Function Convert2(s As String) As String On Error Resume Next If s = "" Then Exit Function Dim d As Double, dd As Double, sTmp As String d = CDbl(s) dd = CInt(d / 16777216 - 0.99999) sTmp = CStr(dd) d = d - dd * 16777216 sTmp = sTmp & "." & CStr(d \ 65536) d = d Mod 65536 sTmp = sTmp & "." & CStr(d \ 256) sTmp = sTmp & "." & CStr(d Mod 256) Convert2 = sTmp End Function Private Function Encode(s As String) As String Dim sTmp As String Dim i As Long For i = 1 To Len(s) sTmp = sTmp & "%" & Right$("00" & Hex$(Asc(Mid$(s, i, 1))), 2) Next Encode = sTmp End FunctionAt the same time there is another operation: if we have one form of an address to get the others. So, we get IP address from a named address (GetIP function) or backward, to get named address from a IP address (GetURL function). These functions are based on the gethostbyname and gethostbyaddr functions of winsock library. The code is following:
Private Function GetIP(sAddr As String) On Error GoTo Done: Dim tWSAData As WSAData Dim Host As Hostent Dim NSInfo As Long Dim addr As Long, addr2 As Long Dim ErrCode As Long Dim strIP As String Dim cName() As Byte If WSAStartup(lWinsockVersion, tWSAData) Then Err.Raise vbObjectError + 1000, "Error calling WSAStartup " GoTo Done End If NSInfo = gethostbyname(sAddr) If NSInfo <> 0 Then CopyMemory Host, ByVal NSInfo, LenB(Host) If Host.h_addr_list <> 0 Then CopyMemory addr, ByVal Host.h_addr_list, 4 CopyMemory addr, ByVal addr, 4 addr2 = inet_ntoa(addr) ReDim cName(lstrlen(addr2) * 2) CopyMemory cName(0), ByVal addr2, lstrlen(addr2) * 2 strIP = StrConv(cName, vbUnicode) If InStr(strIP, Chr(0)) > 0 Then GetIP = Left(strIP, InStr(strIP, Chr(0)) - 1) Else GetIP = strIP End If End If End If Done: On Error Resume Next WSACleanup End Function Function GetURL(IPAddr As String) As String Dim tWSAData As WSAData Dim Host As Hostent Dim NSInfo As Long Dim addr As Long Dim ErrCode As Long Dim strName As String Dim cName() As Byte If WSAStartup(lWinsockVersion, tWSAData) Then Err.Raise vbObjectError + 1000, "Error calling WSAStartup " GoTo Done End If addr = inet_addr(IPAddr) NSInfo = gethostbyaddr(addr, 4, AF_Inet) If NSInfo <> 0 Then CopyMemory Host, ByVal NSInfo, LenB(Host) ReDim cName(lstrlen(Host.h_name) * 2) CopyMemory cName(0), ByVal Host.h_name, lstrlen(Host.h_name) * 2 strName = StrConv(cName, vbUnicode) If InStr(strName, Chr(0)) > 0 Then GetURL = Left(strName, InStr(strName, Chr(0)) - 1) Else GetURL = strName End If End If Done: On Error Resume Next WSACleanup End FunctionFirst of all, we need to start winsock library using WSAStartup function. Then call the gethostbyname or gethostbyaddr functions and interpret the results. But because the results are pointers (memory addresses of the variables or structures) we are using CopyMemory (RtlMoveMemory) function to convert these results. I can't explain here all the functions from winsock library, but there are good sources for this. Finally, we are unloading winsock library by using WSACleanup function.
I guess you already knows what ping is: a way to check if a computer is online or not (using TCP/IP). This operation is made by our program for current address, calling "Ping" function with an ICMP_ECHO_REPLY structure (type) as parameter. The result is interpreted by StatusCode function. Here you are "Ping" function (for address from txtAddrNo1 text-box):
Private Function Ping(Echo As ICMP_ECHO_REPLY) As Long On Error Resume Next Dim addr As Long Dim hPort As Long hPort = IcmpCreateFile() If hPort Then addr = inet_addr(txtAddrNo1) IcmpSendEcho hPort, addr, "test", _ 4, 0, Echo, Len(Echo), PING_TIMEOUT Ping = Echo.status IcmpCloseHandle hPort End If End FunctionFinally, we get informations regarding a site by querying a whois database. The informations are: registrar name and address, his email, phone and fax, his DNS servers address and other related informations. For achieving this we need a function to get web pages using HTTP protocol on the Internet. The code for getting a page over the Internet using winsock library is following:
Private Function GetHTTP(IPAddr As String, page As String) As String Dim tWSAData As WSAData Dim udtSocket As SockAddr_In Dim lSocket As Long, lSize As Long Dim sResult As String, sBuffer As String * 2048 Dim sCommand As String If WSAStartup(lWinsockVersion, tWSAData) Then Err.Raise vbObjectError + 1000, "Error calling WSAStartup " GoTo Done End If lSocket = Socket(AF_Inet, SockStream, 0) If lSocket > 0 Then With udtSocket .sin_family = AF_Inet .sin_addr = inet_addr(IPAddr) .sin_port = htons(80) .sin_zero = String$(8, 0) End With If connect(lSocket, udtSocket, CLng(Len(udtSocket))) Then Err.Raise vbObjectError + 10001, , "Connect failure" GoTo Done End If sCommand = "GET " & page & " HTTP/1.0" & vbCrLf & vbCrLf If Send(lSocket, sCommand, Len(sCommand), 0) <> Len(sCommand) Then Err.Raise vbObjectError + 10002, "Send failure" GoTo Done End If sBuffer = String$(2048, 0) Do While True lSize = recv(lSocket, sBuffer, Len(sBuffer), 0) If lSize < 1 Then Exit Do sResult = sResult & Left$(sBuffer, lSize) Loop GetHTTP = sResult End If Done: On Error Resume Next closesocket lSocket WSACleanup End FunctionThen, the result from web page is parsed and displayed into a text-box.
You can download all the project from here (40,6 kb).
© VB Work 2000, Last update