NetUtils.cs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. using System;
  2. using System.Buffers;
  3. using System.Diagnostics;
  4. using System.Linq;
  5. using System.Net;
  6. using System.Net.NetworkInformation;
  7. using System.Net.Sockets;
  8. using System.Runtime.InteropServices;
  9. using System.Threading;
  10. using System.Threading.Tasks;
  11. namespace STUN.Utils
  12. {
  13. public static class NetUtils
  14. {
  15. public static TcpState GetState(this TcpClient tcpClient)
  16. {
  17. var foo = IPGlobalProperties
  18. .GetIPGlobalProperties()
  19. .GetActiveTcpConnections()
  20. .SingleOrDefault(x => x.LocalEndPoint.Equals(tcpClient.Client.LocalEndPoint));
  21. return foo?.State ?? TcpState.Unknown;
  22. }
  23. //TODO .NET6.0
  24. public static Task<(IPAddress, int, IPEndPoint)> ReceiveMessageFromAsync(this Socket client, EndPoint receive, byte[] array, SocketFlags flag)
  25. {
  26. return Task.Run(() =>
  27. {
  28. var length = client.ReceiveMessageFrom(array, 0, array.Length, ref flag, ref receive, out var ipPacketInformation);
  29. var local = ipPacketInformation.Address;
  30. Debug.WriteLine($@"{(IPEndPoint)receive} => {local} {length} 字节");
  31. return (local, length, (IPEndPoint)receive);
  32. });
  33. }
  34. //TODO Remove in .NET6.0
  35. public static ValueTask<SocketReceiveMessageFromResult> ReceiveMessageFromAsync(this Socket client, Memory<byte> buffer, SocketFlags socketFlags, EndPoint remoteEndPoint, CancellationToken cancellationToken = default)
  36. {
  37. client.ReceiveTimeout = (int)TimeSpan.FromSeconds(3).TotalMilliseconds;
  38. return new ValueTask<SocketReceiveMessageFromResult>(Task.Run(() =>
  39. {
  40. if (!MemoryMarshal.TryGetArray((ReadOnlyMemory<byte>)buffer, out var segment))
  41. {
  42. ThrowNotSupportedException();
  43. }
  44. var length = client.ReceiveMessageFrom(segment.Array!, segment.Offset, segment.Count, ref socketFlags, ref remoteEndPoint, out var ipPacketInformation);
  45. return new SocketReceiveMessageFromResult
  46. {
  47. ReceivedBytes = length,
  48. SocketFlags = socketFlags,
  49. RemoteEndPoint = remoteEndPoint,
  50. PacketInformation = ipPacketInformation
  51. };
  52. }, cancellationToken));
  53. static void ThrowNotSupportedException()
  54. {
  55. throw new NotSupportedException();
  56. }
  57. }
  58. //TODO Remove in .NET6.0
  59. public static async ValueTask<int> SendToAsync(this Socket client, ReadOnlyMemory<byte> buffer, SocketFlags socketFlags, EndPoint remoteEP, CancellationToken cancellationToken)
  60. {
  61. byte[]? t = null;
  62. try
  63. {
  64. if (!MemoryMarshal.TryGetArray(buffer, out var segment))
  65. {
  66. t = ArrayPool<byte>.Shared.Rent(buffer.Length);
  67. buffer.CopyTo(t);
  68. segment = new ArraySegment<byte>(t, 0, buffer.Length);
  69. }
  70. return await client.SendToAsync(segment, socketFlags, remoteEP);
  71. }
  72. finally
  73. {
  74. if (t is not null)
  75. {
  76. ArrayPool<byte>.Shared.Return(t);
  77. }
  78. }
  79. }
  80. }
  81. }