using Apewer.Internals.Interop; using Apewer.Network; using System; using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Runtime.InteropServices; using System.Text; namespace Apewer { /// public class NetworkUtility { #region UDP /// 唤醒局域网中拥有指定 MAC 地址的设备。 /// 被唤醒设备的 MAC 地址,必须是长度为 6 的字节数组。 public static void WakeOnLan(byte[] mac) { if (mac.Length != 6) return; var uc = new System.Net.Sockets.UdpClient(); uc.Connect(IPAddress.Broadcast, 65535); var pack = new List(); // 前 6 字节为 0xFF。 for (int i = 0; i < 6; i++) pack.Add(255); // 目标 MAC 地址重复 16 次。 for (int i = 0; i < 16; i++) { for (int j = 0; j < 6; j++) pack.Add(mac[j]); } // 发送 102 字节数据。 uc.Send(pack.ToArray(), pack.Count); uc.Close(); } /// 从 NTP 服务器获取 UTC 时间。 /// /// Worldwide: pool.ntp.org
/// Asia: asia.pool.ntp.org
/// Europe: europe.pool.ntp.org
/// North: America north-america.pool.ntp.org
/// Oceania: oceania.pool.ntp.org
/// South America: south-america.pool.ntp.org
/// Windows: time.windows.com
/// Windows: time.nist.gov
/// China: us.ntp.org.cn
/// China: edu.ntp.org.cn
///
public static DateTime GetUtcFromNtp(string server = "pool.ntp.org", int port = 123, int timeout = 1000) { try { var addresses = Dns.GetHostEntry(server).AddressList; if (addresses.Length > 0) { var endpoint = new IPEndPoint(addresses[0], port); return GetUtcFromNtp(endpoint, timeout); } } catch { } return ClockUtility.Zero; } /// 从 NTP 服务器获取 UTC 时间。 public static DateTime GetUtcFromNtp(IPEndPoint endpoint, int timeout = 1000) { try { var request = new byte[48]; request[0] = 0x1B; var response = new byte[48]; response[0] = 0x1B; var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); socket.Connect(endpoint); socket.ReceiveTimeout = timeout; socket.Send(request); socket.Receive(response); socket.Close(); const byte replytime = 40; ulong secondspart = BitConverter.ToUInt32(response, replytime); ulong secondsfraction = BitConverter.ToUInt32(response, replytime + 4); secondspart = SwapEndian(secondspart); secondsfraction = SwapEndian(secondsfraction); ulong milliseconds = (secondspart * 1000) + ((secondsfraction * 1000) / 0x100000000UL); var utc = (new DateTime(1900, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).AddMilliseconds(milliseconds); return utc; } catch { } return ClockUtility.Zero; } private static uint SwapEndian(ulong x) { var a = ((x & 0x000000ff) << 24); var b = ((x & 0x0000ff00) << 8); var c = ((x & 0x00ff0000) >> 8); var d = ((x & 0xff000000) >> 24); return (uint)(a + b + c + d); } #endregion #region ARP /// 发送 ARP 请求,获取目标 IP 地址对应设备的 MAC 地址,MAC 格式为 01-23-45-67-89-AB。 /// 目标 IP 地址。 /// 注:
仅 Windows 可用。
/// MAC 地址。 public static string SendARP(string ip) { if (!string.IsNullOrEmpty(ip)) { try { var ipa = IPAddress.Parse(ip); uint dip = BitConverter.ToUInt32(ipa.GetAddressBytes(), 0); ulong mac = 0; uint len = 6; uint err = IpHlpApi.SendARP(dip, 0, ref mac, ref len); byte[] bytes = BitConverter.GetBytes(mac); return BitConverter.ToString(bytes, 0, 6); } catch { } } return ""; } #endregion #region Puny Code /// public static string ToPunyCode(string chinese) { if (string.IsNullOrEmpty(chinese)) return ""; try { return new IdnMapping().GetAscii(chinese); } catch { return chinese; } } /// public static string FromPunyCode(string punycode) { if (string.IsNullOrEmpty(punycode)) return ""; try { return new IdnMapping().GetUnicode(punycode); } catch { return punycode; } } #endregion #region IP /// 获取本地计算机的计算机名。 public static string LocalHost { get { var hn = Dns.GetHostName(); return string.IsNullOrEmpty(hn) ? "" : hn; } } /// 本地计算机的 IP 地址。 public static List LocalIP { get { var list = new List(); var he = Dns.GetHostEntry(Dns.GetHostName()); foreach (var ip in he.AddressList) { list.Add(ip.ToString()); } return list; } } /// 判断 IPv4 地址格式是否正确。 public static bool IsIP(string ipv4) { try { if (string.IsNullOrEmpty(ipv4)) return false; var split = ipv4.Split('.'); if (split.Length != 4) return false; for (int i = 0; i < 4; i++) { var n = Convert.ToInt32(split[i]); if (n < 0 || n > 255) return false; if (n.ToString() != split[i]) return false; } return true; } catch { } return false; } /// 对目标地址进行解析。 public static string Resolve(string host) { try { if (IsIP(host)) { var ip = IPAddress.Parse(host); var he = Dns.GetHostEntry(ip); return he.HostName; } else { var ip = ""; var dn = host.ToLower(); var he = Dns.GetHostEntry(dn); var ts = ""; var on = he.Aliases; he = Dns.GetHostEntry(dn); for (int i = 0; i < on.Length; i++) ts = ts + on[i].ToString() + ","; ts = ""; var al = he.AddressList; for (int i = 0; i < al.Length; i++) ts = ts + al[i].ToString() + ","; ip = ts; if (ip.Length > 0) { if (ip.Substring(ip.Length - 1, 1) == ",") ip = ip.Substring(0, ip.Length - 1); } return ip; } } catch { } return ""; } /// 对目标地址进行解析。 private static IPHostEntry InternalResolve(string hostName) { if (hostName.Length <= 255 && (hostName.Length != 255 || hostName[254] == '.')) { var intPtr = WS2_32.gethostbyname(hostName); if (intPtr != IntPtr.Zero) return NativeToHostEntry(intPtr); } return null; } private static IntPtr IntPtrAdd(IntPtr a, int b) { return (IntPtr)((long)a + b); } private static IPHostEntry NativeToHostEntry(IntPtr nativePointer) { hostent hostent = (hostent)Marshal.PtrToStructure(nativePointer, typeof(hostent)); IPHostEntry iPHostEntry = new IPHostEntry(); if (hostent.h_name != IntPtr.Zero) { iPHostEntry.HostName = Marshal.PtrToStringAnsi(hostent.h_name); } ArrayList arrayList = new ArrayList(); IntPtr intPtr = hostent.h_addr_list; nativePointer = Marshal.ReadIntPtr(intPtr); while (nativePointer != IntPtr.Zero) { int newAddress = Marshal.ReadInt32(nativePointer); arrayList.Add(new IPAddress(newAddress)); intPtr = IntPtrAdd(intPtr, IntPtr.Size); nativePointer = Marshal.ReadIntPtr(intPtr); } iPHostEntry.AddressList = new IPAddress[arrayList.Count]; arrayList.CopyTo(iPHostEntry.AddressList, 0); arrayList.Clear(); intPtr = hostent.h_aliases; nativePointer = Marshal.ReadIntPtr(intPtr); while (nativePointer != IntPtr.Zero) { string value = Marshal.PtrToStringAnsi(nativePointer); arrayList.Add(value); intPtr = IntPtrAdd(intPtr, IntPtr.Size); nativePointer = Marshal.ReadIntPtr(intPtr); } iPHostEntry.Aliases = new string[arrayList.Count]; arrayList.CopyTo(iPHostEntry.Aliases, 0); return iPHostEntry; } /// 将由字符串表示的 IPv4 地址转换为 32 位整数。 public static int GetNumber(IPAddress ipv4) { try { var ba = ipv4.GetAddressBytes(); return BitConverter.ToInt32(ba, 0); } catch { return 0; } } /// 转换 IP 地址格式。 public static string GetPlainAddress(IPAddress address) { try { return address.ToString(); } catch { return ""; } } /// 转换 IP 地址格式。 public static string GetPlainAddress(IPEndPoint endpoint) { try { return GetPlainAddress(endpoint.Address); } catch { return ""; } } /// 转换 IP 地址格式。 public static IPAddress GetIPAddress(string address) { try { return IPAddress.Parse(address); } catch { return new IPAddress(0); } } /// 转换 IP 地址格式。 public static IPEndPoint GetIPEndPoint(string address, int port) { try { return new IPEndPoint(IPAddress.Parse(address), NumberUtility.RestrictValue(port, 0, ushort.MaxValue)); } catch { return new IPEndPoint(0, 0); } } /// 转换 IP 地址格式。 public static IPEndPoint GetIPEndPoint(IPAddress address, int port) { try { return new IPEndPoint(address, NumberUtility.RestrictValue(port, 0, ushort.MaxValue)); } catch { return new IPEndPoint(0, 0); } } /// 转换 IP 地址格式。 public static IPEndPoint GetIPEndPoint(EndPoint endpoint) { try { return (IPEndPoint)endpoint; } catch { return new IPEndPoint(0, 0); } } /// 判断私有 IP 地址。 public static bool FromLAN(string ipv4) { if (ipv4.IsEmpty()) return false; // localhost if (ipv4 == "::1") return true; if (ipv4 == "127.0.0.1") return true; // IPv4 var a = ipv4.Split('.'); if (a.Length != 4) return false; switch (a[0]) { case "10": return true; case "172": var a1 = TextUtility.GetInt32(a[1]); if (a1 >= 16 && a1 <= 31) return true; break; case "192": if (a[1] == "168") return true; break; } return false; } #endregion #region HTTP /// GET public static HttpClient HttpGet(string url, int timeout = 30000) { return HttpClient.SimpleGet(url, timeout); } /// POST public static HttpClient HttpPost(string url, byte[] data, int timeout = 30000, string type = "application/octet-stream") { return HttpClient.SimplePost(url, data, timeout, type); } /// POST text/plain public static HttpClient HttpPost(string url, string text, int timeout = 30000, string type = "text/plain") { return HttpClient.SimpleText(url, text, timeout, type); } /// POST application/x-www-form-urlencoded public static HttpClient HttpPost(string url, IDictionary form, int timeout = 30000) { return HttpClient.SimpleForm(url, form, timeout); } /// POST application/x-www-form-urlencoded public static HttpClient HttpPost(string url, TextSet form, int timeout = 30000) { return HttpClient.SimpleForm(url, form, timeout); } #endregion #region Port private static List ListActivePort(IPEndPoint[] endpoints) { var list = new List(endpoints.Length); foreach (var endpoint in endpoints) { var port = endpoint.Port; if (list.Contains(port)) continue; list.Add(port); } list.Sort(); list.Capacity = list.Count; return list; } /// 列出活动的 TCP 端口。 public static List ListActiveTcpPort() { return ListActivePort(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners()); } /// 列出活动的 UDP 端口。 public static List ListActiveUdpPort() { return ListActivePort(IPGlobalProperties.GetIPGlobalProperties().GetActiveUdpListeners()); } #endregion } }