Получить Ip-адрес сервера из обычной ссылки - VB

Узнай цену своей работы

Формулировка задачи:

Добрый день! Вроде задача вполне реализуемая (тем более что в моем случае ссылка уже содержит этот ip), но хочется сделать грамотно! Есть ссылка: http://yandex.ru/internet Хочется вычислить Ip Яндекса в чистом виде из этой ссылки. Как? Спасибо!)

Решение задачи: «Получить Ip-адрес сервера из обычной ссылки»

textual
Листинг программы
Option Explicit
 
Const WSADESCRIPTION_LEN As Long = 256&
Const WSASYS_STATUS_LEN As Long = 128&
 
Private Type wsaData
    wVersion As Integer
    wHighVersion As Integer
    szDescription(WSADESCRIPTION_LEN + 1) As Byte
    szSystemStatus(WSADESCRIPTION_LEN + 1) As Byte
    iMaxSockets As Integer
    iMaxUdpDg As Integer
    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 in_addr
    oct_1 As Byte
    oct_2 As Byte
    oct_3 As Byte
    oct_4 As Byte
End Type
 
Private Declare Function WSAStartup Lib "Ws2_32.dll" (ByVal wVersionRequested As Integer, lpWSAData As wsaData) As Long
Private Declare Function WSACleanup Lib "Ws2_32.dll" () As Long
Private Declare Function WSAGetLastError Lib "Ws2_32.dll" () As Long
 
Private Declare Function inet_addr Lib "Ws2_32.dll" (ByVal cp As Long) As in_addr  'Windows Vista +
Private Declare Function inet_ntoa Lib "Ws2_32.dll" (ByVal Addr As Long) As Long  'Windows Vista +
Private Declare Function gethostbyname Lib "Ws2_32.dll" (ByVal lpCharName As Long) As Long  'Windows Vista +
Private Declare Function gethostbyaddr Lib "Ws2_32.dll" (ByVal lpCharAddr As Long, ByVal llen As Long, ByVal ltype As Long) As Long  'Windows Vista +
'Private Declare Function RtlIpv4AddressToString Lib "Ntdll.dll" Alias "RtlIpv4AddressToStringA" (ptAddr As Long, ByVal S As Long) As Long  'Windows Vista +
 
Private Declare Function memcpy Lib "kernel32.dll" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal length As Long) As Long
Private Declare Function FormatMessage Lib "kernel32.dll" Alias "FormatMessageA" (ByVal dwFlags As Long, lpSource As Long, ByVal dwMessageId As Long, ByVal dwLanguageId As Long, ByVal lpBuffer As String, ByVal nSize As Long, Arguments As Any) As Long
Private Declare Function lstrlenA Lib "kernel32.dll" (ByVal lpString As Long) As Long
Private Declare Function lstrcpyA Lib "kernel32.dll" (ByVal lpString1 As Long, ByVal lpString2 As Long) As Long
Private Declare Function GetMem4 Lib "msvbvm60" (pSrc As Any, pDst As Any) As Long
 
Private Const AF_INET As Long = 2
 
 
Private Sub Form_Load()
    ResolveHost "i.ua"
    ResolveHost "-"
    ResolveHost "255.1.1.1"
    ResolveHost "91.198.36.14"
    ResolveHost "https://yandex.ua/maps"
    ResolveHost "8.8.4.4:8080"
    Unload Me
End Sub
 
Function ResolveHost(ByVal Host_name As String)
    Dim wVersionRequested As Integer
    Dim dwErr As Long
    Dim wsaData As wsaData
    Dim remoteHost As hostent
    Dim lpRemoteHost As Long
    Dim i_addr As in_addr
    Dim pHost_NameA As Long
    Dim sAddr As String
 
    Debug.Print "-----------------------------------"
 
    'Extracting the host name
    Host_name = ExtractHost(Host_name)
 
    wVersionRequested = 2& * 256 + 2    '(WinSock ver. 2.2.)
 
    dwErr = WSAStartup(wVersionRequested, wsaData)
    If (dwErr <> 0) Then
        MsgBox "WSAStartup failed with error: " & dwErr
        Exit Function
    End If
    
    'Confirm that the WinSock DLL supports 2.2.
    If ((wsaData.wVersion And 255&) <> 2) Or ((wsaData.wVersion \ 256&) <> 2) Then
        MsgBox "Could not find a usable version of Winsock.dll"
        GoTo Finally
    End If
 
    pHost_NameA = StrPtr(StrConv(Host_name, vbFromUnicode)) 'WSTR -> *char[]
 
    ' If the user input is an alpha name for the host, use gethostbyname()
    ' If not, get host by addr (assume IPv4)
    
    If Host_name Like "*[!0-9.]*" Then  'host address is a name
        Debug.Print "By Name. Calling gethostbyname with " & Host_name
 
        lpRemoteHost = gethostbyname(pHost_NameA)
        
        If 0 = lpRemoteHost Then
            dwErr = Err.LastDllError
            Debug.Print "Error #" & dwErr & ". " & WSA_MessageText(dwErr)
            'Debug.Print WSAGetLastError()  ' it seems WSAGetLastError doesn't work inside vbvm; err.LastDllError redirects its code instead.
            GoTo Finally
        End If
    Else
        Debug.Print "By Address. Calling gethostbyaddr with " & Host_name
        
        i_addr = inet_addr(pHost_NameA)  'ipv4 validation
        
        ' INADDR_NONE (-1)
        If i_addr.oct_1 = 255 And i_addr.oct_2 = 255 And i_addr.oct_3 = 255 And i_addr.oct_4 = 255 Then
            MsgBox "The IPv4 address entered must be a legal address"
            GoTo Finally
        End If
        
        lpRemoteHost = gethostbyaddr(VarPtr(i_addr), 4, AF_INET)    'ipv4 type  (possible values = ipv4, ipv6, NETBIOS)
        
        If 0 = lpRemoteHost Then
            dwErr = Err.LastDllError
            Debug.Print "Error #" & dwErr & ". " & WSA_MessageText(dwErr)
            GoTo Finally
        End If
    End If
    
    If 0 <> lpRemoteHost Then
        memcpy remoteHost, ByVal lpRemoteHost, LenB(remoteHost)     ' * -> struct
        
        Debug.Print "Official name: " & GetStringFromPtrA(remoteHost.h_name)
        
        Dim PtArr   As Long
        Dim ptAddr  As Long
        Dim PtChar  As Long
        Dim Addr    As Long
        
        PtArr = remoteHost.h_addr_list
        
        Do
            GetMem4 ByVal PtArr, ptAddr ' *addr for each element
            
            If ptAddr <> 0 Then
            
                GetMem4 ByVal ptAddr, Addr
            
                PtChar = inet_ntoa(Addr)  'addr -> *char[]
                If PtChar <> 0 Then
                    Debug.Print "Address: " & GetStringFromPtrA(PtChar)
                End If
                
'                sAddr = String$(8, vbNullChar)  'at least 16 chars
'                dwErr = RtlIpv4AddressToString(ByVal ptAddr, StrPtr(sAddr))
'                sAddr = StrConv(sAddr, vbUnicode)
'                Debug.Print "Address: " & sAddr
            End If
            PtArr = PtArr + 4
        Loop While ptAddr <> 0
    End If
    
Finally:
    WSACleanup
End Function
 
Function GetStringFromPtrA(Ptr As Long) As String
    Dim Size As Long
    Dim sText As String
    If Ptr <> 0 Then
        Size = lstrlenA(Ptr)
        If Size > 0 Then
            sText = String$(Size \ 2 + 1, vbNullChar)
            lstrcpyA StrPtr(sText), Ptr
            GetStringFromPtrA = Left$(StrConv(sText, vbUnicode), Size)
        End If
    End If
End Function
 
Private Function WSA_MessageText(lCode As Long) As String
    Const MAX_PATH As Long = 260&
    Const FORMAT_MESSAGE_FROM_SYSTEM    As Long = &H1000&
    Const FORMAT_MESSAGE_IGNORE_INSERTS As Long = &H200
    Const WSANO_DATA As Long = 11004
    Const WSAHOST_NOT_FOUND As Long = 11001
    
    Dim sRtrnCode   As String
    Dim lRet        As Long
    
    Select Case lCode
        Case WSAHOST_NOT_FOUND
            WSA_MessageText = "Host not found"
        Case WSANO_DATA
            WSA_MessageText = "No data record found"
        Case Else
            sRtrnCode = Space$(MAX_PATH)
            lRet = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM Or FORMAT_MESSAGE_IGNORE_INSERTS, ByVal 0&, lCode, ByVal 0&, sRtrnCode, MAX_PATH, ByVal 0&)
            If lRet > 0 Then
                WSA_MessageText = Left$(sRtrnCode, lRet)
                WSA_MessageText = Replace$(WSA_MessageText, vbCrLf, vbNullString)
            End If
    End Select
End Function
 
' Вытягивает из строки адрес хоста для HTTP-адреса
Public Function ExtractHost(sText As String) As String
    On Error GoTo ErrorHandler
    Dim S        As String
    Dim pos      As Long
    Dim pos2     As Long
    Dim oRegEx   As Object
    Dim oMatches As Object
    
    Set oRegEx = CreateObject("VBScript.RegExp")
    oRegEx.Pattern = """?(http:|www(2)?\.|https:)[^ \r\n""]*( |""|$|\r|\n)"
    Set oMatches = oRegEx.Execute(sText)
    If oMatches.Count = 0 Then
        ExtractHost = sText
        GoTo Finally
    End If
    S = UnQuote(oMatches.Item(0).Value)
    
    ' - 0x0D 0x0A
    If Right$(S, 1) = Chr$(10) Then S = Left$(S, Len(S) - 1)
    If Right$(S, 1) = Chr$(13) Then S = Left$(S, Len(S) - 1)
    
    ' - http://
    If StrComp(Left$(S, 5), "http:", 1) = 0 Then
        S = Mid$(S, 8)
    ' - https://
    ElseIf StrComp(Left$(S, 6), "https:", 1) = 0 Then
        S = Mid$(S, 9)
    End If
    
    ' - www.
    If StrComp(Left$(S, 4), "www.", 1) = 0 Then
        S = Mid$(S, 5)
    ' - www2.
    ElseIf StrComp(Left$(S, 5), "www2.", 1) = 0 Then
        S = Mid$(S, 6)
    End If
    
    ' / с конца
    pos = InStr(S, "/")
    pos2 = InStr(S, "")
    If pos = 0 And pos2 = 0 Then
        ExtractHost = S
    Else
        If pos <> 0 And pos2 <> 0 Then
            ExtractHost = Left$(S, IIf(pos < pos2, pos - 1, pos2 - 1))
        ElseIf pos <> 0 Then
            ExtractHost = Left$(S, pos - 1)
        Else
            ExtractHost = Left$(S, pos2 - 1)
        End If
    End If
 
Finally:
    ' remove :port
    oRegEx.Pattern = ".*:\d+$"
    Set oMatches = oRegEx.Execute(ExtractHost)
    If oMatches.Count <> 0 Then
        ExtractHost = Left$(ExtractHost, InStrRev(ExtractHost, ":") - 1)
    End If
    
    Exit Function
ErrorHandler:
    Debug.Print Now, Err, "Parser.ExtractHost"
End Function
 
Public Function UnQuote(str As String) As String   ' Убрать кавычки (слева и справа)
    On Error GoTo ErrorHandler
    Dim S As String: S = str
    Do While Left$(S, 1&) = """"
        S = Mid$(S, 2&)
    Loop
    Do While Right$(S, 1&) = """"
        S = Left$(S, Len(S) - 1&)
    Loop
    UnQuote = S
    Exit Function
ErrorHandler:
    Debug.Print Now, Err, "Parser.UnQuote", "String: ", str
End Function

Оцени полезность:

5   голосов , оценка 3.8 из 5
Похожие ответы