NetUtils.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. using STUN.Client;
  2. using STUN.StunResult;
  3. using System;
  4. using System.Diagnostics;
  5. using System.Linq;
  6. using System.Net;
  7. using System.Net.Sockets;
  8. using System.Threading.Tasks;
  9. namespace STUN.Utils
  10. {
  11. public static class NetUtils
  12. {
  13. public const string DefaultLocalEnd = @"0.0.0.0:0";
  14. public static IPEndPoint ParseEndpoint(string str)
  15. {
  16. var ipPort = str.Trim().Split(':');
  17. if (ipPort.Length < 2) return null;
  18. IPAddress ip = null;
  19. if (ipPort.Length == 2 && IPAddress.TryParse(ipPort[0], out ip))
  20. {
  21. if (!IPAddress.TryParse(ipPort[0], out ip))
  22. {
  23. return null;
  24. }
  25. }
  26. else if (ipPort.Length > 2)
  27. {
  28. var ipStr = string.Join(@":", ipPort, 0, ipPort.Length - 1);
  29. if (!ipStr.StartsWith(@"[") || !ipStr.EndsWith(@"]") || !IPAddress.TryParse(ipStr, out ip))
  30. {
  31. return null;
  32. }
  33. }
  34. if (ip != null && ushort.TryParse(ipPort.Last(), out var port))
  35. {
  36. return new IPEndPoint(ip, port);
  37. }
  38. return null;
  39. }
  40. public static (string, string, string) NatTypeTestCore(string local, string server, ushort port)
  41. {
  42. try
  43. {
  44. if (string.IsNullOrWhiteSpace(server))
  45. {
  46. Debug.WriteLine(@"[ERROR]: Please specify STUN server !");
  47. return (string.Empty, DefaultLocalEnd, string.Empty);
  48. }
  49. using var client = new StunClient3489(server, port, ParseEndpoint(local));
  50. var result = client.Query();
  51. return (
  52. result.NatType.ToString(),
  53. $@"{client.LocalEndPoint}",
  54. $@"{result.PublicEndPoint}"
  55. );
  56. }
  57. catch (Exception ex)
  58. {
  59. Debug.WriteLine($@"[ERROR]: {ex}");
  60. return (string.Empty, DefaultLocalEnd, string.Empty);
  61. }
  62. }
  63. public static async Task<StunResult5389> NatBehaviorDiscovery(string server, ushort port, IPEndPoint local)
  64. {
  65. using var client = new StunClient5389UDP(server, port, local);
  66. return await client.QueryAsync();
  67. }
  68. public static (byte[], IPEndPoint, IPAddress) UdpReceive(this UdpClient client, byte[] bytes, IPEndPoint remote, EndPoint receive)
  69. {
  70. var localEndPoint = (IPEndPoint)client.Client.LocalEndPoint;
  71. Debug.WriteLine($@"{localEndPoint} => {remote} {bytes.Length} 字节");
  72. client.Send(bytes, bytes.Length, remote);
  73. var res = new byte[ushort.MaxValue];
  74. var flag = SocketFlags.None;
  75. var length = client.Client.ReceiveMessageFrom(res, 0, res.Length, ref flag, ref receive, out var ipPacketInformation);
  76. var local = ipPacketInformation.Address;
  77. Debug.WriteLine($@"{(IPEndPoint)receive} => {local} {length} 字节");
  78. return (res.Take(length).ToArray(),
  79. (IPEndPoint)receive
  80. , local);
  81. }
  82. public static async Task<(byte[], IPEndPoint, IPAddress)> UdpReceiveAsync(this UdpClient client, byte[] bytes, IPEndPoint remote, EndPoint receive)
  83. {
  84. var localEndPoint = (IPEndPoint)client.Client.LocalEndPoint;
  85. Debug.WriteLine($@"{localEndPoint} => {remote} {bytes.Length} 字节");
  86. await client.SendAsync(bytes, bytes.Length, remote);
  87. var res = new byte[ushort.MaxValue];
  88. var flag = SocketFlags.None;
  89. var length = client.Client.ReceiveMessageFrom(res, 0, res.Length, ref flag, ref receive, out var ipPacketInformation);
  90. var local = ipPacketInformation.Address;
  91. Debug.WriteLine($@"{(IPEndPoint)receive} => {local} {length} 字节");
  92. return (res.Take(length).ToArray(),
  93. (IPEndPoint)receive
  94. , local);
  95. }
  96. }
  97. }