Определить имя удаленного хоста vb6 winsock - эквивалент GetHostByAddr - PullRequest
1 голос
/ 18 ноября 2011

Задача

Я пытаюсь найти наиболее надежный способ определения имени рабочей станции компьютера, подключенного через соединение winsock, в vb6.

Особенности

На сервере размещена служба Windows, написанная на vb6. Другие компьютеры в той же сети подключаются к этой службе, и службе необходимо определить имя компьютера компьютеров, которые к ней подключены.

Возможный код

У элемента управления winsock vb6 есть свойство .RemoteHostIP, которое я могу использовать для получения IP-адреса.

Я нашел этот код winapi, чтобы использовать этот IP-адрес для получения имени удаленного компьютера:

  Private mbInitialized As Boolean
  Const WSADescription_Len = 256
  Const WSASYS_Status_Len = 128
  Const AF_INET = 4&


  Private Type HOSTENT
      hName As Long
      hAliases As Long
      hAddrType As Integer
      hLength As Integer
      hAddrList As Long
  End Type


  Private Type WSADATA
      wversion As Integer
      wHighVersion As Integer
      szDescription(0 To WSADescription_Len) As Byte
      szSystemStatus(0 To WSASYS_Status_Len) As Byte
      iMaxSockets As Integer
      iMaxUdpDg As Integer
      lpszVendorInfo As Long
  End Type

  Private Declare Function WSAStartup Lib "wsock32" (ByVal VersionReq As Long, WSADataReturn As WSADATA) As Long
  Private Declare Function WSACleanup Lib "wsock32" () As Long
  Private Declare Function WSAGetLastError Lib "wsock32" () As Long
  Private Declare Function gethostbyaddr Lib "wsock32" (addr As Long, addrLen As Long, addrType As Long) As Long
  Private Declare Function gethostbyname Lib "wsock32" (ByVal hostname As String) As Long
  Private Declare Sub RtlMoveMemory Lib "kernel32" (hpvDest As Any, ByVal hpvSource As Long, ByVal cbCopy As Long)

  Private Sub Class_Initialize()
      Dim wsa As WSADATA
      mbInitialized = (WSAStartup(257, wsa) = 0)
  End Sub
  Private Sub Class_Terminate()
      If mbInitialized Then
       WSACleanup
      End If
  End Sub

  'checks if string is valid IP address

  Private Function CheckIP(IPToCheck As String) As Boolean
      Dim TempValues
      Dim iLoop As Long
      Dim TempByte As Byte
      On Error GoTo CheckIPError

      TempValues = Split(IPToCheck, ".")
      If UBound(TempValues) < 3 Then
          Exit Function
      End If
      For iLoop = LBound(TempValues) To UBound(TempValues)
          TempByte = TempValues(iLoop)
      Next iLoop

      CheckIP = True

CheckIPError:

  End Function

  'converts IP address from string to sin_addr

  Private Function MakeIP(strIP As String) As Long

      Dim vTemp
      Dim lngTemp As Long
      Dim iLoop As Long
      On Error GoTo MakeIPError

      vTemp = Split(strIP, ".")
      For iLoop = 0 To (UBound(vTemp) - 1)
          lngTemp = lngTemp + (vTemp(iLoop) * (256 ^ iLoop))
      Next iLoop
      If vTemp(UBound(vTemp)) < 128 Then
       lngTemp = lngTemp + (vTemp(UBound(vTemp)) * (256 ^ 3))

      Else

          lngTemp = lngTemp + ((vTemp(UBound(vTemp)) - 256) * (256 ^ 3))
      End If

      MakeIP = lngTemp

MakeIPError:
   End Function

  'resolves IP address to host name

  Private Function AddrToName(strAddr As String) As String

      Dim heEntry As HOSTENT
      Dim strHost As String * 255
      Dim strTemp As String
      Dim lngRet As Long
      Dim lngIP As Long

      On Error GoTo AddrToNameError

      If CheckIP(strAddr) Then
          lngIP = MakeIP(strAddr)
          lngRet = gethostbyaddr(lngIP, 4, AF_INET)
          If lngRet = 0 Then
              Exit Function
          End If

          RtlMoveMemory heEntry, lngRet, Len(heEntry)
          RtlMoveMemory ByVal strHost, heEntry.hName, 255
          strTemp = TrimNull(strHost)
          AddrToName = strTemp

      End If

AddrToNameError:

  End Function

  'resolves host name to IP address

  Private Function NameToAddr(ByVal strHost As String)

      Dim ip_list() As Byte
      Dim heEntry As HOSTENT
      Dim strIPAddr As String
      Dim lp_HostEnt As Long

      Dim lp_HostIP As Long
      Dim iLoop As Integer
      On Error GoTo NameToAddrError

      lp_HostEnt = gethostbyname(strHost)
      If lp_HostEnt = 0 Then
          Exit Function
      End If

      RtlMoveMemory heEntry, lp_HostEnt, LenB(heEntry)
      RtlMoveMemory lp_HostIP, heEntry.hAddrList, 4
      ReDim ip_list(1 To heEntry.hLength)

      RtlMoveMemory ip_list(1), lp_HostIP, heEntry.hLength
      For iLoop = 1 To heEntry.hLength
          strIPAddr = strIPAddr & ip_list(iLoop) & "."
      Next

      strIPAddr = Mid(strIPAddr, 1, Len(strIPAddr) - 1)
      NameToAddr = strIPAddr

NameToAddrError:

  End Function

  Public Function AddressToName(strIP As String) As String

      If mbInitialized Then AddressToName = AddrToName(strIP)

  End Function

  Public Function NameToAddress(strName As String) As String

      If mbInitialized Then NameToAddress = NameToAddr(strName)

  End Function

  Private Function TrimNull(sTrim As String) As String

      Dim iFind As Long

      iFind = InStr(1, sTrim, Chr(0))
      If iFind > 0 Then
          TrimNull = Left(sTrim, iFind - 1)
      Else
          TrimNull = sTrim
      End If
  End Function

Что можно назвать так:

Dim obj As clsIPResolve
Set obj = New clsIPResolve

msgbox obj.AddressToName(frmMain.sckClient(i).RemoteHostIP)
Set obj = Nothing

Вопросы:

  1. Кто-нибудь знает, является ли это лучшим способом сделать это в vb6? Я заставил его работать в моей тестовой среде, но я немного нервничаю, чтобы полагаться на него в «реальном мире».

  2. Как это работает точно? Очевидно, что он выполняет какой-то обратный DNS с использованием IP-адреса удаленных машин. Где он получает эту информацию? Роутер? Где-то еще?

Заранее спасибо за любую помощь!

1 Ответ

0 голосов
/ 18 ноября 2011

1) Этот код выполняет простой поиск DNS, поэтому по определению это будет имя сети. Если на машине нет обратного DNS-имени, вы не получите никакого значимого имени и вам следует использовать IP-адрес.
Обратите внимание, что обратное DNS-имя НЕ совпадает с именем рабочей станции, которое машина имеет для себя. Чтобы получить это, вам либо нужно быть частью домена (я не могу предоставить какой-либо код, но WNet API должен получать эту информацию, искать имя NetBios), либо передавать его в сокетное соединение как часть протокола. / начальное рукопожатие.

2) Выполняется обратный поиск DNS, поэтому запросит ваш локальный сервер имен, чтобы попытаться получить детали. Затем он выполнит повторный поиск и найдет сервер авторизации, который может дать ответ на основании того, как он настроен, или имени машины в домене.
Если оба компьютера находятся в одном домене (Windows), он также попытается выполнить поиск NetBios по адресу.

...