单个网卡+有多个模拟LAN网络连接时如何正确获取网卡的LAN IP?
因为想使用WinSockAPI来做TCP连接,于是找到了老马封装的一个自定义控件的WSAPI模块包,在只有一个本地连接的机器上运行一切正常,但是到了有多个LAN网络连接的机器上就无法准确定位真实网卡的IP(只有一块网卡,但是安装虚拟机后会生成几个虚拟LAN连接,见下图),导致绑定LAN IP 失败,就无法进行后续操作了.
里面有一个叫做: BindInternal 的过程需要用到真实网卡的IP,也就是上图中的"本地连接"的IP,但是那个包里面的: GetLocalIP 函数只能获取一个IP地址,而且不能保证是不是真实网卡的IP,于是找了个获取所有LAN连接的IP的函数来,但是还是无法区分到底那个IP才是我们需要的网卡的IP?请教各位是否有什么办法确定那个IP是网卡的?或者如何只获取真实网卡的IP?
我自己找的获取所有IP的函数如下:
我弱智的改了一下,将最后一个IP列表的IP输出,但是真实网卡的IP不可能每次都在最后一个....寒....
Private Function GetLocIP() As StringDim hostname As String Dim hostent_addr As Long Dim host As HOSTENT Dim hostip_addr As Long Dim temp_ip_address() As Byte Dim i As Integer Dim ip_address As String hostname = GetLocalHostName hostent_addr = gethostbyname(hostname) If hostent_addr = 0 Then GetLocIP = vbNullString Dim lngErrorCode As Long lngErrorCode = Err.LastDllError Err.Raise lngErrorCode, "CSocketMaster.GetLocalIP", GetErrorDescription(lngErrorCode) Exit Function End If RtlMoveMemory host, hostent_addr, LenB(host) RtlMoveMemory hostip_addr, host.hAddrList, 4 ' MsgBox hostname 'get all of the IP address if machine is multi-homed Do ReDim temp_ip_address(1 To host.hLength) RtlMoveMemory temp_ip_address(1), hostip_addr, host.hLength ip_address = "" For i = 1 To host.hLength ip_address = ip_address & temp_ip_address(i) & "." Next ip_address = Mid$(ip_address, 1, Len(ip_address) - 1) ' MsgBox ip_address host.hAddrList = host.hAddrList + LenB(host.hAddrList) RtlMoveMemory hostip_addr, host.hAddrList, 4 Loop While (hostip_addr <> 0) GetLocIP = ip_addressEnd Function
Private Function GetLocalIP() As StringDim lngResult As LongDim lngPtrToIP As LongDim strLocalHost As StringDim arrIpAddress(1 To 4) As ByteDim Count As IntegerDim udtHostent As HOSTENTDim strIpAddress As String strLocalHost = GetLocalHostName lngResult = api_gethostbyname(strLocalHost) If lngResult = 0 Then GetLocalIP = vbNullString Dim lngErrorCode As Long lngErrorCode = Err.LastDllError Err.Raise lngErrorCode, "CSocketMaster.GetLocalIP", GetErrorDescription(lngErrorCode) Else api_CopyMemory udtHostent, ByVal lngResult, LenB(udtHostent) api_CopyMemory lngPtrToIP, ByVal udtHostent.hAddrList, 4 api_CopyMemory arrIpAddress(1), ByVal lngPtrToIP, 4 For Count = 1 To 4 strIpAddress = strIpAddress & arrIpAddress(Count) & "." Next strIpAddress = Left$(strIpAddress, Len(strIpAddress) - 1) GetLocalIP = strIpAddress End IfEnd Function
Option ExplicitPublic Const MAX_ADAPTER_NAME_LENGTH = 260Public Const MAX_ADAPTER_ADDRESS_LENGTH = 8Public Const MAX_ADAPTER_DESCRIPTION_LENGTH = 132Public Const IP_ADAPTER_INFO_LENGTH = 640Type IP_ADDR_STRING Next As Long IpAddress As String * 16 IpMask As String * 16 Context As LongEnd TypeType IP_ADAPTER_INFO Next As Long ComboIndex As Long AdapterName As String * MAX_ADAPTER_NAME_LENGTH Description As String * MAX_ADAPTER_DESCRIPTION_LENGTH AddressLength As Long Address(MAX_ADAPTER_ADDRESS_LENGTH - 1) As Byte Index As Long Type As Long DhcpEnabled As Long CurrentIpAddress As Long IpAddressList As IP_ADDR_STRING GatewayList As IP_ADDR_STRING DhcpServer As IP_ADDR_STRING HaveWins As Byte PrimaryWinsServer As IP_ADDR_STRING SecondaryWinsServer As IP_ADDR_STRING LeaseObtained As Long LeaseExpires As LongEnd TypePublic Declare Function GetAdaptersInfo Lib "iphlpapi.dll" (IpAdapterInfo As Any, pOutBufLen As Long) As LongPrivate Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)Public Function LanIP() As String Dim AdapterInfoSize As Long Dim AdapterInfo As IP_ADAPTER_INFO Dim AdapterInfoBuffer() As Byte Dim ptr1 As Long AdapterInfoSize = 0 Call GetAdaptersInfo(ByVal 0&, AdapterInfoSize) ReDim AdapterInfoBuffer(AdapterInfoSize - 1) If 0 = GetAdaptersInfo(AdapterInfoBuffer(0), AdapterInfoSize) Then ptr1 = VarPtr(AdapterInfoBuffer(0)) Do While (ptr1 <> 0) CopyMemory AdapterInfo, ByVal ptr1, IP_ADAPTER_INFO_LENGTH If InStr(AdapterInfo.GatewayList.IpAddress, Chr(0)) > 6 Then LanIP = Left(AdapterInfo.IpAddressList.IpAddress, InStr(AdapterInfo.IpAddressList.IpAddress, Chr(0)) - 1) End If ptr1 = AdapterInfo.Next Loop End IfEnd Function
[解决办法]
同上,用GetAdaptersInfo:
给个参考代码:
Option ExplicitPublic Const MAX_ADAPTER_NAME_LENGTH = 260Public Const MAX_ADAPTER_ADDRESS_LENGTH = 8Public Const MAX_ADAPTER_DESCRIPTION_LENGTH = 132Public Const IP_ADAPTER_INFO_LENGTH = 640Type IP_ADDR_STRING Next As Long IpAddress As String * 16 IpMask As String * 16 Context As LongEnd TypeType IP_ADAPTER_INFO Next As Long ComboIndex As Long AdapterName As String * MAX_ADAPTER_NAME_LENGTH Description As String * MAX_ADAPTER_DESCRIPTION_LENGTH AddressLength As Long Address(MAX_ADAPTER_ADDRESS_LENGTH - 1) As Byte Index As Long Type As Long DhcpEnabled As Long CurrentIpAddress As Long IpAddressList As IP_ADDR_STRING GatewayList As IP_ADDR_STRING DhcpServer As IP_ADDR_STRING HaveWins As Byte PrimaryWinsServer As IP_ADDR_STRING SecondaryWinsServer As IP_ADDR_STRING LeaseObtained As Long LeaseExpires As LongEnd TypePublic Declare Function GetAdaptersInfo Lib "iphlpapi.dll" (IpAdapterInfo As Any, pOutBufLen As Long) As LongPrivate Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)Public Function LanIP() As String Dim AdapterInfoSize As Long Dim AdapterInfo As IP_ADAPTER_INFO Dim AdapterInfoBuffer() As Byte Dim ptr1 As Long AdapterInfoSize = 0 Call GetAdaptersInfo(ByVal 0&, AdapterInfoSize) ReDim AdapterInfoBuffer(AdapterInfoSize - 1) If 0 = GetAdaptersInfo(AdapterInfoBuffer(0), AdapterInfoSize) Then ptr1 = VarPtr(AdapterInfoBuffer(0)) Do While (ptr1 <> 0) CopyMemory AdapterInfo, ByVal ptr1, IP_ADAPTER_INFO_LENGTH If InStr(AdapterInfo.GatewayList.IpAddress, Chr(0)) > 6 Then LanIP = Left(AdapterInfo.IpAddressList.IpAddress, InStr(AdapterInfo.IpAddressList.IpAddress, Chr(0)) - 1) End If ptr1 = AdapterInfo.Next Loop End IfEnd Function
[解决办法]
恩,同上,判断IP_ADAPTER_INFO结构的Type属性是否为MIB_IF_TYPE_ETHERNET