使用自制的发现工具,我发现了一系列我感兴趣的服务。
我有他们的IP,服务名称,端口,主机......但是要使用它们,我要向客户端库指定我们将使用的IP。
由于我有几张网卡,我需要检测哪个接口用于与我知道的目标IP进行通信,然后将此IPAddress
提供给我的库。
但是我怎么能检测到我应该使用哪个接口IP?
我试图通过互联网进行一些搜索,但我认为我没有合适的关键字,因为我找不到任何相关内容。
答案 0 :(得分:6)
我已经为我开发的网络库提取了相关的方法,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()
以找到匹配的适配器。
答案 1 :(得分:1)
以下通过查询路由表来工作。这与Socket.Connect
确定要使用的本地端点的方式相同。差异:
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);
(从here复制的源代码)
请注意,虽然有人指定带有端口的IpEndPoint
,但该端口无关紧要。此外,返回的IpEndPoint.Port
始终为0
。
答案 2 :(得分:0)
我花了几个小时才找到这个问题的简短答案,多亏了BatteryBackupUnit,我已经提出了这个解决方案并希望它能帮助其他程序员:
[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;
}