使用自制的發現工具,我發現了我感興趣的服務列表。c#知道我們使用哪個IP與另一個IP進行通信?
我有他們的IP,服務名稱,端口,主機......但要使用它們,我必須向客戶端庫指定我們將使用的IP。
由於我有幾張網卡,我需要檢測使用哪個接口與我知道的目標IP進行通信,然後將此IPAddress
傳遞給我的庫。
但我怎麼能檢測到我應該使用哪個接口IP?
我試圖通過互聯網進行一些搜索,但我認爲我沒有正確的關鍵字,因爲我沒有找到任何相關的。
使用自制的發現工具,我發現了我感興趣的服務列表。c#知道我們使用哪個IP與另一個IP進行通信?
我有他們的IP,服務名稱,端口,主機......但要使用它們,我必須向客戶端庫指定我們將使用的IP。
由於我有幾張網卡,我需要檢測使用哪個接口與我知道的目標IP進行通信,然後將此IPAddress
傳遞給我的庫。
但我怎麼能檢測到我應該使用哪個接口IP?
我試圖通過互聯網進行一些搜索,但我認爲我沒有正確的關鍵字,因爲我沒有找到任何相關的。
我已經從網絡庫我開發,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()
找到匹配的適配器。
這是通過路由表完成的。路由表將告訴你IP應該通過哪一組網關(它們有優先級指標)。然後您可以通過獲取NIC上的地址將其解決到NIC。
您可以通過放入命令shell並鍵入route print
來查看該示例。
您可能需要從IP Helper API中調用GetIpForwardTable
和GetIpForwardTable2
函數來獲取路由表代碼。
我發現這個例子代碼:http://pastebin.com/mvLYvgbg
而且你可以在這裏閱讀更多的MSDN:http://msdn.microsoft.com/en-us/library/windows/desktop/aa365953(v=vs.85).aspx
希望幫助!
我認爲最好的但仍然非常簡單的方法是使用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
。
我已經花了幾個小時找到簡短的回答了這個問題,並且由於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;
}
可能重複中。淨](http://stackoverflow.com/questions/15625023/ip-routing-table-lookup-in-net) – BatteryBackupUnit 2014-10-28 14:57:03