首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用特定的网络接口(或特定的源IP地址)执行Ping操作?

如何使用特定的网络接口(或特定的源IP地址)执行Ping操作?
EN

Stack Overflow用户
提问于 2014-03-22 16:54:20
回答 2查看 9.2K关注 0票数 2

根据此链接:使用System.Net.NetworkInformation,有没有一种方法可以将ping绑定到特定的pingICMP不能绑定到网络接口(不像基于套接字的东西):

ICMP不是基于套接字的。ping将根据路由表发送到相应的端口。https://stackoverflow.com/editing-help

但我找不到任何适当的方法来获取有关"pinger“的信息。至少,我可以在shell命令中指定源IP地址,但不能在使用Ping类时指定。

我尝试以编程方式执行一些跟踪路由,以获取Ping路由中涉及的IP地址,但我没有获得Network Interface的IP地址(我猜这是因为我无法将TTL设置为0)。

你知道如何确定某个ping使用的是哪个网络接口吗?(或指定用于pinging的网络接口的一种方式)。

EN

回答 2

Stack Overflow用户

发布于 2014-10-30 00:05:23

代码语言:js
复制
i know this is a old question but i found a solution and want to share it.

我把它发布在CodeProject上,链接如下:http://www.codeproject.com/Questions/828234/Ping-over-specific-Interface-with-IcmpSendEchoEx?loginkey=false

编辑:

因此,解决方案是在Iphlpapi.dll中使用IcmpSendEcho2Ex函数。

此函数采用接口be地址来确定应在哪个接口上发送ping。

该链接包括p调用和一个reply类,该类包装了函数的输出。

来自codeproject的代码:

代码语言:javascript
运行
复制
public static PingReply Send(IPAddress srcAddress, IPAddress destAddress, int timeout = 5000, byte[] buffer = null, PingOptions po = null)
{
    if (destAddress == null || destAddress.AddressFamily != AddressFamily.InterNetwork || destAddress.Equals(IPAddress.Any))
        throw new ArgumentException();
 
    //Defining pinvoke args
    var source = srcAddress == null ? 0 : BitConverter.ToUInt32(srcAddress.GetAddressBytes(), 0);
    var destination = BitConverter.ToUInt32(destAddress.GetAddressBytes(), 0);
    var sendbuffer = buffer ?? new byte[] {};
    var options = new Interop.Option
    {
        Ttl = (po == null ? (byte) 255 : (byte) po.Ttl),
        Flags = (po == null ? (byte) 0 : po.DontFragment ? (byte) 0x02 : (byte) 0) //0x02
    };
    var fullReplyBufferSize = Interop.ReplyMarshalLength + sendbuffer.Length; //Size of Reply struct and the transmitted buffer length.

 

    var allocSpace = Marshal.AllocHGlobal(fullReplyBufferSize); // unmanaged allocation of reply size. TODO Maybe should be allocated on stack
    try
    {
        DateTime start = DateTime.Now;
        var nativeCode = Interop.IcmpSendEcho2Ex(
            Interop.IcmpHandle, //_In_      HANDLE IcmpHandle,
            default(IntPtr), //_In_opt_  HANDLE Event,
            default(IntPtr), //_In_opt_  PIO_APC_ROUTINE ApcRoutine,
            default(IntPtr), //_In_opt_  PVOID ApcContext
            source, //_In_      IPAddr SourceAddress,
            destination, //_In_      IPAddr DestinationAddress,
            sendbuffer, //_In_      LPVOID RequestData,
            (short) sendbuffer.Length, //_In_      WORD RequestSize,
            ref options, //_In_opt_  PIP_OPTION_INFORMATION RequestOptions,
            allocSpace, //_Out_     LPVOID ReplyBuffer,
            fullReplyBufferSize, //_In_      DWORD ReplySize,
            timeout //_In_      DWORD Timeout
            );
        TimeSpan duration = DateTime.Now - start;
        var reply = (Interop.Reply) Marshal.PtrToStructure(allocSpace, typeof (Interop.Reply)); // Parse the beginning of reply memory to reply struct

        byte[] replyBuffer = null;
        if (sendbuffer.Length != 0)
        {
            replyBuffer = new byte[sendbuffer.Length];
            Marshal.Copy(allocSpace + Interop.ReplyMarshalLength, replyBuffer, 0, sendbuffer.Length); //copy the rest of the reply memory to managed byte[]
        }
 
        if (nativeCode == 0) //Means that native method is faulted.
            return new PingReply(nativeCode, reply.Status, new IPAddress(reply.Address), duration);
        else
            return new PingReply(nativeCode, reply.Status, new IPAddress(reply.Address), reply.RoundTripTime, replyBuffer);
    }
    finally
    {
        Marshal.FreeHGlobal(allocSpace); //free allocated space
    }
}
 
/// Interoperability Helper
///     
/// 
private static class Interop
{
    private static IntPtr? icmpHandle;
    private static int? _replyStructLength;
 
    /// Returns the application legal icmp handle. Should be close by IcmpCloseHandle
    ///     
    /// 
    public static IntPtr IcmpHandle
    {
        get
        {
            if (icmpHandle == null)
            {
                icmpHandle = IcmpCreateFile();
                //TODO Close Icmp Handle appropiate
            }
 
            return icmpHandle.GetValueOrDefault();
        }
    }
    /// Returns the the marshaled size of the reply struct.
    public static int ReplyMarshalLength
    {
        get
        {
            if (_replyStructLength == null)
            {
                _replyStructLength = Marshal.SizeOf(typeof (Reply));
            }
            return _replyStructLength.GetValueOrDefault();
        }
    }
 

    [DllImport("Iphlpapi.dll", SetLastError = true)]
    private static extern IntPtr IcmpCreateFile();
    [DllImport("Iphlpapi.dll", SetLastError = true)]
    private static extern bool IcmpCloseHandle(IntPtr handle);
    [DllImport("Iphlpapi.dll", SetLastError = true)]
    public static extern uint IcmpSendEcho2Ex(IntPtr icmpHandle, IntPtr Event, IntPtr apcroutine, IntPtr apccontext, UInt32 sourceAddress, UInt32 destinationAddress, byte[] requestData, short requestSize, ref Option requestOptions, IntPtr replyBuffer, int replySize, int timeout);
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct Option
    {
        public byte Ttl;
        public readonly byte Tos;
        public byte Flags;
        public readonly byte OptionsSize;
        public readonly IntPtr OptionsData;
    }
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct Reply
    {
        public readonly UInt32 Address;
        public readonly int Status;
        public readonly int RoundTripTime;
        public readonly short DataSize;
        public readonly short Reserved;
        public readonly IntPtr DataPtr;
        public readonly Option Options;
    }
}

[Serializable]
public class PingReply
{
    private readonly byte[] _buffer = null;
    private readonly IPAddress _ipAddress = null;
    private readonly uint _nativeCode = 0;
    private readonly TimeSpan _roundTripTime = TimeSpan.Zero;
    private readonly IPStatus _status = IPStatus.Unknown;
    private Win32Exception _exception;
 

    internal PingReply(uint nativeCode, int replystatus, IPAddress ipAddress, TimeSpan duration)
    {
        _nativeCode = nativeCode;
        _ipAddress = ipAddress;
        if (Enum.IsDefined(typeof (IPStatus), replystatus))
            _status = (IPStatus) replystatus;
    }
    internal PingReply(uint nativeCode, int replystatus, IPAddress ipAddress, int roundTripTime, byte[] buffer)
    {
        _nativeCode = nativeCode;
        _ipAddress = ipAddress;
        _roundTripTime = TimeSpan.FromMilliseconds(roundTripTime);
        _buffer = buffer;
        if (Enum.IsDefined(typeof (IPStatus), replystatus))
            _status = (IPStatus) replystatus;
    }
 

    /// Native result from IcmpSendEcho2Ex.
    public uint NativeCode
    {
        get { return _nativeCode; }
    }
    public IPStatus Status
    {
        get { return _status; }
    }
    /// The source address of the reply.
    public IPAddress IpAddress
    {
        get { return _ipAddress; }
    }
    public byte[] Buffer
    {
        get { return _buffer; }
    }
    public TimeSpan RoundTripTime
    {
        get { return _roundTripTime; }
    }
    /// Resolves the Win32Exception from native code
    public Win32Exception Exception
    {
        get
        {
            if (Status != IPStatus.Success)
                return _exception ?? (_exception = new Win32Exception((int) NativeCode, Status.ToString()));
            else
                return null;
        }
    }
 
    public override string ToString()
    {
        if (Status == IPStatus.Success)
            return Status + " from " + IpAddress + " in " + RoundTripTime + " ms with " + Buffer.Length + " bytes";
        else if (Status != IPStatus.Unknown)
            return Status + " from " + IpAddress;
        else
            return Exception.Message + " from " + IpAddress;
    }
}
票数 4
EN

Stack Overflow用户

发布于 2021-02-26 12:41:10

Christian Sack提供的解决方案正是我所需要的。下面是我如何使用Christian提供的代码,通过使用NIC卡的名称来允许从给定源IP using目标IP。

我创建了一个名为IpSupport的新静态类,并向其中添加了以下两个助手方法。然后,我添加了克里斯蒂安的所有代码从他的帖子。完整的类将在稍后显示。

代码语言:javascript
运行
复制
public static bool PingIpFromNic(string ipToPing, string nicName)
    {
        var sourceIpStr = GetIpOfNicFromName(nicName);

        if (sourceIpStr == "")
        {
            MessageBox.Show($"Unable to find an ip for the nic name of {nicName}");
            return false;
        }

        var p = Send(
            srcAddress: IPAddress.Parse(sourceIpStr),
            destAddress: IPAddress.Parse(ipToPing));

        return p.Status == IPStatus.Success;
    }

    public static string GetIpOfNicFromName(string nicName)
    {
        string ip = "";

        var adapters = NetworkInterface.GetAllNetworkInterfaces();

        foreach (var adapter in adapters)
        {
            if (!string.Equals(adapter.Name, nicName, StringComparison.CurrentCultureIgnoreCase)) continue;

            foreach (var uni in adapter.GetIPProperties().UnicastAddresses)
            {
                // Return the first one found
                return uni.Address.ToString();
            }
        }

        return ip;
    }

下面是完整的类。

代码语言:javascript
运行
复制
namespace Helpers.ChristianSack
{
public static class IpSupport
{
    /// 
    /// Pass in the IP you want to ping as a string along with the name of the NIC on your machine that
    /// you want to send the ping from.
    /// 
    /// The destination IP as a string ex. '10.10.10.1'
    /// The name of the NIC ex. 'LECO Hardware'.  Non-case sensitive.
    /// 
    public static bool PingIpFromNic(string ipToPing, string nicName)
    {
        var sourceIpStr = GetIpOfNicFromName(nicName);

        if (sourceIpStr == "")
        {
            MessageBox.Show($"Unable to find an ip for the nic name of {nicName}");
            return false;
        }

        var p = Send(
            srcAddress: IPAddress.Parse(sourceIpStr),
            destAddress: IPAddress.Parse(ipToPing));

        return p.Status == IPStatus.Success;
    }

    /// 
    /// Pass in the name of a NIC on your machine and this method will return the IPV4 address of it.
    /// 
    /// The name of the NIC you want the IP of ex. 'TE Hardware'
    /// 
    public static string GetIpOfNicFromName(string nicName)
    {
        var adapters = NetworkInterface.GetAllNetworkInterfaces();

        foreach (var adapter in adapters)
        {
            // Ignoring case in NIC name
            if (!string.Equals(adapter.Name, nicName, StringComparison.CurrentCultureIgnoreCase)) continue;

            foreach (var uni in adapter.GetIPProperties().UnicastAddresses)
            {
                // Return the first one found
                return uni.Address.ToString();
            }
        }

        return "";
    }

    public static PingReply Send(IPAddress srcAddress, IPAddress destAddress,
        int timeout = 5000,
        byte[] buffer = null, PingOptions po = null)
    {
        if (destAddress == null || destAddress.AddressFamily != AddressFamily.InterNetwork ||
            destAddress.Equals(IPAddress.Any))
            throw new ArgumentException();

        //Defining pinvoke args
        var source = srcAddress == null ? 0 : BitConverter.ToUInt32(srcAddress.GetAddressBytes(), 0);

        var destination = BitConverter.ToUInt32(destAddress.GetAddressBytes(), 0);

        var sendBuffer = buffer ?? new byte[] { };

        var options = new Interop.Option
        {
            Ttl = (po == null ? (byte)255 : (byte)po.Ttl),
            Flags = (po == null ? (byte)0 : po.DontFragment ? (byte)0x02 : (byte)0) //0x02
        };

        var fullReplyBufferSize =
            Interop.ReplyMarshalLength +
            sendBuffer.Length; //Size of Reply struct and the transmitted buffer length.

        var allocSpace =
            Marshal.AllocHGlobal(
                fullReplyBufferSize); // unmanaged allocation of reply size. TODO Maybe should be allocated on stack
        try
        {
            var start = DateTime.Now;
            var nativeCode = Interop.IcmpSendEcho2Ex(
                Interop.IcmpHandle,             //_In_      HANDLE IcmpHandle,
                Event: default(IntPtr),         //_In_opt_  HANDLE Event,
                apcRoutine: default(IntPtr),    //_In_opt_  PIO_APC_ROUTINE ApcRoutine,
                apcContext: default(IntPtr),    //_In_opt_  PVOID ApcContext
                source,                         //_In_      IPAddr SourceAddress,
                destination,                    //_In_      IPAddr DestinationAddress,
                sendBuffer,                     //_In_      LPVOID RequestData,
                (short)sendBuffer.Length,       //_In_      WORD RequestSize,
                ref options,                    //_In_opt_  PIP_OPTION_INFORMATION RequestOptions,
                replyBuffer: allocSpace,        //_Out_     LPVOID ReplyBuffer,
                fullReplyBufferSize,            //_In_      DWORD ReplySize,
                timeout                         //_In_      DWORD Timeout
            );

            var duration = DateTime.Now - start;

            var reply = (Interop.Reply)Marshal.PtrToStructure(allocSpace,
                typeof(Interop.Reply)); // Parse the beginning of reply memory to reply struct

            byte[] replyBuffer = null;
            if (sendBuffer.Length != 0)
            {
                replyBuffer = new byte[sendBuffer.Length];
                Marshal.Copy(allocSpace + Interop.ReplyMarshalLength, replyBuffer, 0,
                    sendBuffer.Length); //copy the rest of the reply memory to managed byte[]
            }

            if (nativeCode == 0) //Means that native method is faulted.
                return new PingReply(nativeCode, reply.Status,
                    new IPAddress(reply.Address), duration);
            else
                return new PingReply(nativeCode, reply.Status,
                    new IPAddress(reply.Address), reply.RoundTripTime,
                    replyBuffer);
        }
        finally
        {
            Marshal.FreeHGlobal(allocSpace); //free allocated space
        }
    }

    
    /// Interoperability Helper
    ///     
    /// 
    public static class Interop
    {
        private static IntPtr? _icmpHandle;
        private static int? _replyStructLength;

        /// Returns the application legal icmp handle. Should be close by IcmpCloseHandle
        ///     
        /// 
        public static IntPtr IcmpHandle
        {
            get
            {
                if (_icmpHandle == null)
                {
                    _icmpHandle = IcmpCreateFile();
                    //TODO Close Icmp Handle appropriate
                }

                return _icmpHandle.GetValueOrDefault();
            }
        }

        /// Returns the the marshaled size of the reply struct.
        public static int ReplyMarshalLength
        {
            get
            {
                if (_replyStructLength == null)
                {
                    _replyStructLength = Marshal.SizeOf(typeof(Reply));
                }
                return _replyStructLength.GetValueOrDefault();
            }
        }


        [DllImport("Iphlpapi.dll", SetLastError = true)]
        private static extern IntPtr IcmpCreateFile();
        [DllImport("Iphlpapi.dll", SetLastError = true)]
        private static extern bool IcmpCloseHandle(IntPtr handle);
        [DllImport("Iphlpapi.dll", SetLastError = true)]
        public static extern uint IcmpSendEcho2Ex(IntPtr icmpHandle, IntPtr Event, IntPtr apcRoutine, IntPtr apcContext, uint sourceAddress, UInt32 destinationAddress, byte[] requestData, short requestSize, ref Option requestOptions, IntPtr replyBuffer, int replySize, int timeout);
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct Option
        {
            public byte Ttl;
            public readonly byte Tos;
            public byte Flags;
            public readonly byte OptionsSize;
            public readonly IntPtr OptionsData;
        }
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct Reply
        {
            public readonly UInt32 Address;
            public readonly int Status;
            public readonly int RoundTripTime;
            public readonly short DataSize;
            public readonly short Reserved;
            public readonly IntPtr DataPtr;
            public readonly Option Options;
        }
    }

    [Serializable]
    public class PingReply
    {
        private Win32Exception _exception;

        internal PingReply(uint nativeCode, int replyStatus, IPAddress ipAddress, TimeSpan duration)
        {
            NativeCode = nativeCode;
            IpAddress = ipAddress;
            if (Enum.IsDefined(typeof(IPStatus), replyStatus))
                Status = (IPStatus)replyStatus;
        }
        internal PingReply(uint nativeCode, int replyStatus, IPAddress ipAddress, int roundTripTime, byte[] buffer)
        {
            NativeCode = nativeCode;
            IpAddress = ipAddress;
            RoundTripTime = TimeSpan.FromMilliseconds(roundTripTime);
            Buffer = buffer;
            if (Enum.IsDefined(typeof(IPStatus), replyStatus))
                Status = (IPStatus)replyStatus;
        }

        /// Native result from IcmpSendEcho2Ex.
        public uint NativeCode { get; }

        public IPStatus Status { get; } = IPStatus.Unknown;

        /// The source address of the reply.
        public IPAddress IpAddress { get; }

        public byte[] Buffer { get; }

        public TimeSpan RoundTripTime { get; } = TimeSpan.Zero;

        public Win32Exception Exception
        {
            get
            {
                if (Status != IPStatus.Success)
                    return _exception ?? (_exception = new Win32Exception((int)NativeCode, Status.ToString()));
                else
                    return null;
            }
        }

        public override string ToString()
        {
            if (Status == IPStatus.Success)
                return Status + " from " + IpAddress + " in " + RoundTripTime + " ms with " + Buffer.Length + " bytes";
            else if (Status != IPStatus.Unknown)
                return Status + " from " + IpAddress;
            else
                return Exception.Message + " from " + IpAddress;
        }
    }
}
}

以下是获取计算机上所有NIC卡名称及其IP地址的方法

代码语言:javascript
运行
复制
var adapters = NetworkInterface.GetAllNetworkInterfaces();

        foreach(var adapter in adapters)
        {
            cmbNicNames.Items.Add(adapter.Name);

            foreach (var uni in adapter.GetIPProperties().UnicastAddresses)
            {
                Debug.WriteLine($" IPv4 : {uni.Address}");
                cmbSourceIP.Items.Add(uni.Address);
            }
        }

下面是对Christian代码的调用。

代码语言:js
复制
var bSuccess = Helpers.ChristianSack.IpSupport.PingIpFromNic("10.10.10.1", "TE Hardware");
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22575485

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档