NetUtils.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  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. //TODO:IPv6
  17. var ipPort = str.Trim().Split(':');
  18. if (ipPort.Length == 2)
  19. {
  20. if (IPAddress.TryParse(ipPort[0], out var ip))
  21. {
  22. if (ushort.TryParse(ipPort[1], out var port))
  23. {
  24. return new IPEndPoint(ip, port);
  25. }
  26. }
  27. }
  28. return null;
  29. }
  30. public static (string, string, string) NatTypeTestCore(string local, string server, ushort port)
  31. {
  32. try
  33. {
  34. if (string.IsNullOrWhiteSpace(server))
  35. {
  36. Debug.WriteLine(@"[ERROR]: Please specify STUN server !");
  37. return (string.Empty, DefaultLocalEnd, string.Empty);
  38. }
  39. using var client = new StunClient3489(server, port, ParseEndpoint(local));
  40. var result = (ClassicStunResult)client.Query();
  41. return (
  42. result.NatType.ToString(),
  43. $@"{client.LocalEndPoint}",
  44. $@"{result.PublicEndPoint}"
  45. );
  46. }
  47. catch (Exception ex)
  48. {
  49. Debug.WriteLine($@"[ERROR]: {ex}");
  50. return (string.Empty, DefaultLocalEnd, string.Empty);
  51. }
  52. }
  53. public static (byte[], IPEndPoint, IPAddress) UdpReceive(this UdpClient client, byte[] bytes, IPEndPoint remote, EndPoint receive)
  54. {
  55. var localEndPoint = (IPEndPoint)client.Client.LocalEndPoint;
  56. Debug.WriteLine($@"{localEndPoint} => {remote} {bytes.Length} 字节");
  57. client.Send(bytes, bytes.Length, remote);
  58. var res = new byte[ushort.MaxValue];
  59. var flag = SocketFlags.None;
  60. var length = client.Client.ReceiveMessageFrom(res, 0, res.Length, ref flag, ref receive, out var ipPacketInformation);
  61. var local = ipPacketInformation.Address;
  62. Debug.WriteLine($@"{(IPEndPoint)receive} => {local} {length} 字节");
  63. return (res.Take(length).ToArray(),
  64. (IPEndPoint)receive
  65. , local);
  66. }
  67. public static async Task<(byte[], IPEndPoint, IPAddress)> UdpReceiveAsync(this UdpClient client, byte[] bytes, IPEndPoint remote, EndPoint receive)
  68. {
  69. var localEndPoint = (IPEndPoint)client.Client.LocalEndPoint;
  70. Debug.WriteLine($@"{localEndPoint} => {remote} {bytes.Length} 字节");
  71. await client.SendAsync(bytes, bytes.Length, remote);
  72. var res = new ArraySegment<byte>(new byte[ushort.MaxValue]);
  73. var result = await client.Client.ReceiveMessageFromAsync(res, SocketFlags.None, receive);
  74. var local = result.PacketInformation.Address;
  75. Debug.WriteLine($@"{(IPEndPoint)result.RemoteEndPoint} => {local} {result.ReceivedBytes} 字节");
  76. return (res.Take(result.ReceivedBytes).ToArray(),
  77. (IPEndPoint)result.RemoteEndPoint
  78. , local);
  79. }
  80. }
  81. }