c#知道我们使用哪个IP与另一个IP通信吗?

c#知道我们使用哪个IP与另一个IP通信吗?,c#,.net,network-programming,C#,.net,Network Programming,通过自制的发现工具,我发现了我感兴趣的服务列表 我有他们的IP,服务名称,端口,主机。。。但要使用它们,我必须向客户机库指定我们将使用的IP 由于我有几个网卡,我需要检测哪个接口用于与我知道的目标IP通信,然后将此IPAddress提供给我的库 但我如何才能检测到我应该使用哪个接口IP 我试图在互联网上进行一些搜索,但我认为我没有正确的关键字,因为我找不到任何相关的内容。我已经从我为之开发的网络库中为您找到了相关的方法: // ///确定与提供的远程端点联系的最合适的本地端点。 ///测试表明,

通过自制的发现工具,我发现了我感兴趣的服务列表

我有他们的IP,服务名称,端口,主机。。。但要使用它们,我必须向客户机库指定我们将使用的IP

由于我有几个网卡,我需要检测哪个接口用于与我知道的目标IP通信,然后将此
IPAddress
提供给我的库

但我如何才能检测到我应该使用哪个接口IP


我试图在互联网上进行一些搜索,但我认为我没有正确的关键字,因为我找不到任何相关的内容。

我已经从我为之开发的网络库中为您找到了相关的方法:

//
///确定与提供的远程端点联系的最合适的本地端点。
///测试表明,该方法平均需要1.6ms才能返回。
/// 
///遥远的终点
///选定的本地端点
公共静态IPEndPoint BestLocalEndPoint(IPEndPoint remoteIPEndPoint)
{    
Socket testSocket=新套接字(remoteIPEndPoint.AddressFamily,SocketType.Dgram,ProtocolType.Udp);
testSocket.Connect(remoteIPEndPoint);
返回(IPEndPoint)testSocket.LocalEndPoint;
}

一旦您有了正确的IP,您就可以遍历
NetworkInterface.GetAllNetworkInterfaces()
找到匹配的适配器。

以下操作通过查询路由表来实现。这与套接字的方法相同。连接决定使用哪个本地端点。差异:

  • 不能因为防火墙而失败
  • 由于不存在远程终结点,无法失败
  • 不保留本地端口
  • 更快

(源代码复制自)


请注意,虽然指定的是带有端口的
IpEndPoint
,但该端口并不相关。另外,返回的
IpEndPoint.Port
始终是
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;
    }
[DllImport(“ws2_32.dll”,SetLastError=true)]
私有静态外部套接字错误WSAIoctl([In]IntPtr socketHandle,uint ioControlCode,[In]字节[]inBuffer,intinbuffersize,[Out]字节[]extruffer,intextruffersize,Out int bytesttransfered,IntPtr重叠,IntPtr completionroutin);
///获取远程地址的本地IP地址
///远程地址
/// 
公共静态IPAddress GetLocalAddressForRemote(IPAddress remoteAddress)
{
if(remoteAddress==null)返回null;
长rm=远程地址。地址;
//临时插座仅用于其手柄
Socket s=新套接字(AddressFamily.InterNetwork、SocketType.Dgram、ProtocolType.Udp);
字节[]src=新字节[16];
src[0]=2;
src[4]=(字节)rm;
src[5]=(字节)(rm>>8);
src[6]=(字节)(rm>>16);
src[7]=(字节)(rm>>24);
int transferred=0;
如果(WSAIoctl(s.Handle,3355443220,src,16,src,16,输出传输,IntPtr.Zero,IntPtr.Zero)=SocketError.Success)
{
s、 处置();
rm=src[4];

rm |=((long)src[5])很好,如果有几个端点允许我ping远程IP,那么如何选择端点?选择最快的?决策由基本操作系统做出。操作系统通常会使用路由表,特别是路由器度量来做出此决策()。您可以通过自己访问路由表来强制执行手动决策,就像在另一个答案中一样,但这通常比它的价值更麻烦。可能重复
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);
    [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;
    }