如何使用特定的网络接口(或特定的源IP地址)? 此链接的符号:使用System.net.networkInformation,是否有一种将ping绑定到特定接口的方法? ICMP不能绑定到网络接口(与基于插座的东西不同): ICM ...

问题描述 投票:0回答:2

ICMP不是基于插座的。 ping将根据路由表发送到适当的端口。 但我看不到获得有关“ pinger”信息的任何正确方法。至少,在shell命令中,我可以指定源IP地址,但当我使用ping类时没有。 我试图以编程方式执行一些示踪操作,以获取ping路由中涉及哪些IP地址,但我没有获得网络接口的IP地址(我想这是我无法将TTL设置为0的事实)。

任何想法如何弄清楚哪种网络接口用于某个ping? (或一种指定用于ping的网络接口的方法)。

i know this is a old question but i found a solution and want to share it.

I在CodeProject上发布了这是链接:

Http://www.codeproject.com/questions/828234/ping-over-pecific-interface-with-icmpsendechoex?loginkey = falseky

已编辑:

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

c# network-programming ping icmp
2个回答
5
投票
链接包括p调用和包装功能输出的答复类。

从CodeProject:代码 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 } }   /// <summary>Interoperability Helper /// <see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/bb309069(v=vs.85).aspx" /> /// </summary> private static class Interop { private static IntPtr? icmpHandle; private static int? _replyStructLength;   /// <summary>Returns the application legal icmp handle. Should be close by IcmpCloseHandle /// <see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa366045(v=vs.85).aspx" /> /// </summary> public static IntPtr IcmpHandle { get { if (icmpHandle == null) { icmpHandle = IcmpCreateFile(); //TODO Close Icmp Handle appropiate }   return icmpHandle.GetValueOrDefault(); } } /// <summary>Returns the the marshaled size of the reply struct.</summary> 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; }   /// <summary>Native result from <code>IcmpSendEcho2Ex</code>.</summary> public uint NativeCode { get { return _nativeCode; } } public IPStatus Status { get { return _status; } } /// <summary>The source address of the reply.</summary> public IPAddress IpAddress { get { return _ipAddress; } } public byte[] Buffer { get { return _buffer; } } public TimeSpan RoundTripTime { get { return _roundTripTime; } } /// <summary>Resolves the <code>Win32Exception</code> from native code</summary> 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; } }

Christian Sack提供的解决方案正是我所需要的。 这是我使用基督徒提供的代码来允许使用NIC卡的名称从给定源IP中启用目标IP的方式。

I创建了一个名为Ipsupport的新静态类,并在其中添加了以下两个助手方法。 然后,我从他的帖子中添加了所有Christian的代码。 完整的课程将在稍后显示。

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; }

there是完整的班级。

namespace Helpers.ChristianSack { public static class IpSupport { /// <summary> /// 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. /// </summary> /// <param name="ipToPing">The destination IP as a string ex. '10.10.10.1'</param> /// <param name="nicName">The name of the NIC ex. 'LECO Hardware'. Non-case sensitive.</param> /// <returns></returns> 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; } /// <summary> /// Pass in the name of a NIC on your machine and this method will return the IPV4 address of it. /// </summary> /// <param name="nicName">The name of the NIC you want the IP of ex. 'TE Hardware'</param> /// <returns></returns> 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 } } /// <summary>Interoperability Helper /// <see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/bb309069(v=vs.85).aspx" /> /// </summary> public static class Interop { private static IntPtr? _icmpHandle; private static int? _replyStructLength; /// <summary>Returns the application legal icmp handle. Should be close by IcmpCloseHandle /// <see cref="http://msdn.microsoft.com/en-us/library/windows/desktop/aa366045(v=vs.85).aspx" /> /// </summary> public static IntPtr IcmpHandle { get { if (_icmpHandle == null) { _icmpHandle = IcmpCreateFile(); //TODO Close Icmp Handle appropriate } return _icmpHandle.GetValueOrDefault(); } } /// <summary>Returns the the marshaled size of the reply struct.</summary> 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; } /// <summary>Native result from <code>IcmpSendEcho2Ex</code>.</summary> public uint NativeCode { get; } public IPStatus Status { get; } = IPStatus.Unknown; /// <summary>The source address of the reply.</summary> 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; } } } }

where是一种将机器上NIC卡的所有名称以及其IP地址以及其IP地址的一种方式

3
投票

在这里是对基督教代码的呼吁。

var bSuccess = Helpers.ChristianSack.IpSupport.PingIpFromNic("10.10.10.1", "TE Hardware");


最新问题
© www.soinside.com 2019 - 2025. All rights reserved.