2013-02-26 84 views
2

使用自制的發現工具,我發現了我感興趣的服務列表。c#知道我們使用哪個IP與另一個IP進行通信?

我有他們的IP,服務名稱,端口,主機......但要使用它們,我必須向客戶端庫指定我們將使用的IP。

由於我有幾張網卡,我需要檢測使用哪個接口與我知道的目標IP進行通信,然後將此IPAddress傳遞給我的庫。

但我怎麼能檢測到我應該使用哪個接口IP?

我試圖通過互聯網進行一些搜索,但我認爲我沒有正確的關鍵字,因爲我沒有找到任何相關的。

+0

可能重複中。淨](http://stackoverflow.com/questions/15625023/ip-routing-table-lookup-in-net) – BatteryBackupUnit 2014-10-28 14:57:03

回答

5

我已經從網絡庫我開發,networkComms.net拉的相關方法爲你:

/// <summary> 
/// Determines the most appropriate local end point to contact the provided remote end point. 
/// Testing shows this method takes on average 1.6ms to return. 
/// </summary> 
/// <param name="remoteIPEndPoint">The remote end point</param> 
/// <returns>The selected local end point</returns> 
public static IPEndPoint BestLocalEndPoint(IPEndPoint remoteIPEndPoint) 
{  
    Socket testSocket = new Socket(remoteIPEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp); 
    testSocket.Connect(remoteIPEndPoint); 
    return (IPEndPoint)testSocket.LocalEndPoint; 
} 

一旦你有了正確的IP,然後你可以遍歷NetworkInterface.GetAllNetworkInterfaces()找到匹配的適配器。

+0

好極了,如果我們有幾個端點允許我ping我的遠程IP,這是如何選擇端點?選擇最快的? – J4N 2013-02-26 11:20:42

+0

決定是由基本操作系統決定的。操作系統通常會使用路由表做出這一決定,特別是路由器指標(http://en.wikipedia.org/wiki/Router_metrics)。您可以通過自己訪問路由表來強制進行手動決策,就像在其他答案中一樣,但這通常比其價值更麻煩。 – MarcF 2013-02-26 11:46:47

+0

不,這對我來說很完美 – J4N 2013-02-26 11:51:00

0

這是通過路由表完成的。路由表將告訴你IP應該通過哪一組網關(它們有優先級指標)。然後您可以通過獲取NIC上的地址將其解決到NIC。

您可以通過放入命令shell並鍵入route print來查看該示例。

您可能需要從IP Helper API中調用GetIpForwardTableGetIpForwardTable2函數來獲取路由表代碼。

我發現這個例子代碼:http://pastebin.com/mvLYvgbg

而且你可以在這裏閱讀更多的MSDN:http://msdn.microsoft.com/en-us/library/windows/desktop/aa365953(v=vs.85).aspx

希望幫助!

1

我認爲最好的但仍然非常簡單的方法是使用Socket.IoCtl來查詢路由表。你不必亂搞太多的本地/不安全的東西,你也不必實際做Socket.Connect(因爲防火牆,錯誤的協議,可能會失敗..)。

所以這裏有雲(從here複製源代碼):(!例如)

private static IPEndPoint QueryRoutingInterface(
      Socket socket, 
      IPEndPoint remoteEndPoint) 
{ 
    SocketAddress address = remoteEndPoint.Serialize(); 

    byte[] remoteAddrBytes = new byte[address.Size]; 
    for (int i = 0; i < address.Size; i++) { 
     remoteAddrBytes[i] = address[i]; 
    } 

    byte[] outBytes = new byte[remoteAddrBytes.Length]; 
    socket.IOControl(
       IOControlCode.RoutingInterfaceQuery, 
       remoteAddrBytes, 
       outBytes); 
    for (int i = 0; i < address.Size; i++) { 
     address[i] = outBytes[i]; 
    } 

    EndPoint ep = remoteEndPoint.Create(address); 
    return (IPEndPoint)ep; 
} 

所使用,如:

IPAddress remoteIp = IPAddress.Parse("192.168.1.55"); 
IpEndPoint remoteEndPoint = new IPEndPoint(remoteIp, 0); 
Socket socket = new Socket(
         AddressFamily.InterNetwork, 
         SocketType.Dgram, 
         ProtocolType.Udp); 
IPEndPoint localEndPoint = QueryRoutingInterface(socket, remoteEndPoint); 
Console.WriteLine("Local EndPoint is: {0}", localEndPoint); 

請注意,雖然一個是指定用一個IpEndPoint港口,港口是無關緊要的。此外,返回的IpEndPoint.Port始終爲0

0

我已經花了幾個小時找到簡短的回答了這個問題,並且由於BatteryBackupUnit,我取得了這個解決方案,並希望它有助於其他程序員:IP路由表查找的

[DllImport("ws2_32.dll", SetLastError = true)] 
    private static extern SocketError WSAIoctl([In] IntPtr socketHandle, uint ioControlCode, [In] byte[] inBuffer, int inBufferSize, [Out] byte[] outBuffer, int outBufferSize, out int bytesTransferred, IntPtr overlapped, IntPtr completionRoutine); 

    /// <summary>Get local IP-address for remote address</summary> 
    /// <param name="remoteAddress">Remote Address</param> 
    /// <returns></returns> 
    public static IPAddress GetLocalAddressForRemote(IPAddress remoteAddress) 
    { 
     if (remoteAddress == null) return null; 

     long rm = remoteAddress.Address; 
     //Temporary socket only for handle of it 
     Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 
     byte[] src = new byte[16]; 

     src[0] = 2; 
     src[4] = (byte)rm; 
     src[5] = (byte)(rm >> 8); 
     src[6] = (byte)(rm >> 16); 
     src[7] = (byte)(rm >> 24); 

     int transeferred = 0; 
     if (WSAIoctl(s.Handle, 3355443220, src, 16, src, 16, out transeferred, IntPtr.Zero, IntPtr.Zero) == SocketError.Success) 
     { 
      s.Dispose(); 
      rm = src[4]; 
      rm |= ((long)src[5]) << 8; 
      rm |= ((long)src[6]) << 16; 
      rm |= ((long)src[7]) << 24; 
      return new IPAddress(rm); 
     } 
     s.Dispose(); 
     return null; 
    } 
相關問題