SocketHelper.cs 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. using Island.StandardLib.Exceptions;
  2. using Island.StandardLib.Storage;
  3. using System;
  4. using System.Net.Sockets;
  5. using System.Threading;
  6. namespace Island.StandardLib
  7. {
  8. public static class SocketHelper
  9. {
  10. public static bool EnableHashCheck { get; set; } = true;
  11. public static int DefaultMaxBitSize { get; set; } = 1024 * 1024 * 1024;
  12. public static int MaxRecvBuffSize { get; set; } = 1024;
  13. public static int SendBufferSizeEx { get; set; } = 0;
  14. public static int RecvBufferSizeEx { get; set; } = 0;
  15. static int Claim(int val, int min, int max)
  16. {
  17. if (val < min) return min;
  18. if (val > max) return max;
  19. return val;
  20. }
  21. public static void ReceiveEx(this Socket sock, byte[] buff_out, int size)
  22. {
  23. int recved = 0;
  24. while (recved < size)
  25. {
  26. int recv = sock.Receive(buff_out, recved, size - recved > MaxRecvBuffSize ? MaxRecvBuffSize : size - recved, SocketFlags.None);
  27. if (recv == 0)
  28. throw new SocketException();
  29. recved += recv;
  30. }
  31. }
  32. public static void SendEx(this Socket sock, byte[] buff_in)
  33. {
  34. int send = 0;
  35. while (send < buff_in.Length)
  36. {
  37. int sent = sock.Send(buff_in, send, buff_in.Length - send > MaxRecvBuffSize ? MaxRecvBuffSize : buff_in.Length - send, SocketFlags.None);
  38. if (sent == 0)
  39. throw new SocketException();
  40. send += sent;
  41. }
  42. }
  43. public static T ReceiveOnce<T>(this Socket socket, int maxBitSize, string playerName = null)
  44. where T : IStorable, new()
  45. {
  46. maxBitSize = maxBitSize == 0 ? DefaultMaxBitSize : maxBitSize;
  47. byte[] buf_len = new byte[4], buf_hash = new byte[16], buf_data;
  48. socket.ReceiveEx(buf_len, 4);
  49. int length = BitConverter.ToInt32(buf_len, 0);
  50. if (length > maxBitSize)
  51. throw new PlayerSocketFatalException((playerName ?? "") + "(" + length + ", " + maxBitSize + ")", PlayerSocketFatalExceptionType.RecvBufferTooLong);
  52. socket.ReceiveEx(buf_hash, 16);
  53. buf_data = new byte[length];
  54. socket.ReceiveEx(buf_data, length);
  55. if (EnableHashCheck)
  56. {
  57. if (!buf_data.Hash16().ByteEquals(buf_hash))
  58. throw new PlayerSocketFatalException(playerName ?? "", PlayerSocketFatalExceptionType.HashFailException);
  59. }
  60. return buf_data.ReadData<T>();
  61. }
  62. public static void SendOnce(this Socket socket, byte[] buf_data)
  63. {
  64. byte[] buf_len = BitConverter.GetBytes(buf_data.Length), buf_hash = buf_data.Hash16();
  65. socket.SendEx(buf_len);
  66. socket.SendEx(buf_hash);
  67. socket.SendEx(buf_data);
  68. }
  69. public static void SendOnce<T>(this Socket socket, T data)
  70. where T : IStorable, new()
  71. {
  72. byte[] buf_data = data.GetBytes(),
  73. buf_len = BitConverter.GetBytes(buf_data.Length),
  74. buf_hash = buf_data.Hash16();
  75. socket.SendEx(buf_len);
  76. socket.SendEx(buf_hash);
  77. socket.SendEx(buf_data);
  78. }
  79. }
  80. }