You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

118 lines
4.5 KiB

4 years ago
4 years ago
4 years ago
  1. using Apewer.Internals;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. using System.Text;
  7. namespace Apewer.Network
  8. {
  9. /// <summary>UDP 客户端。</summary>
  10. public static class UdpClient
  11. {
  12. /// <summary>向所有服务端广播数据。</summary>
  13. /// <param name="bytes">数据。</param>
  14. /// <param name="port">服务端端口。</param>
  15. public static bool Broadcast(byte[] bytes, int port)
  16. {
  17. if (bytes == null) return false;
  18. if (bytes.LongLength == 0) return false;
  19. if (port < 0) port = 0;
  20. if (port > 65535) port = 65535;
  21. try
  22. {
  23. var uc = new System.Net.Sockets.UdpClient();
  24. var ep = new IPEndPoint(IPAddress.Parse("255.255.255.255"), port);
  25. uc.EnableBroadcast = true;
  26. uc.Send(bytes, bytes.Length, ep);
  27. uc.Close();
  28. return true;
  29. }
  30. catch { return false; }
  31. }
  32. /// <summary>向指定服务端发送数据。</summary>
  33. /// <param name="ip">服务端 IP 地址。</param>
  34. /// <param name="port">服务端端口。</param>
  35. /// <param name="bytes">数据。</param>
  36. /// <param name="await">阻塞当前线程,等待服务端返回数据,指定 FALSE 将立刻返回 NULL 值。</param>
  37. /// <returns>服务器返回的数据。当通过 await 参数指定 FALSE 时,立刻返回 NULL 值。</returns>
  38. public static byte[] Send(string ip, int port, byte[] bytes, bool await = false)
  39. {
  40. if (bytes == null) return null;
  41. if (bytes.LongLength == 0) return null;
  42. if (port < 0) port = 0;
  43. if (port > 65535) port = 65535;
  44. try
  45. {
  46. var uc = new System.Net.Sockets.UdpClient();
  47. var ep = new IPEndPoint(IPAddress.Parse(ip), port);
  48. uc.EnableBroadcast = false;
  49. uc.Send(bytes, bytes.Length, ep);
  50. var received = null as byte[];
  51. if (await)
  52. {
  53. var rep = null as IPEndPoint;
  54. received = await ? uc.Receive(ref rep) : null;
  55. }
  56. uc.Close();
  57. return received;
  58. }
  59. catch { return null; }
  60. }
  61. /// <summary>向指定服务端发送数据。</summary>
  62. /// <param name="ip">服务端 IP 地址。</param>
  63. /// <param name="port">服务端端口。</param>
  64. /// <param name="bytes">数据。</param>
  65. /// <param name="await">阻塞当前线程,等待服务端返回数据,指定 FALSE 将立刻返回 NULL 值。</param>
  66. /// <returns>服务器返回的数据。当通过 await 参数指定 FALSE 时,立刻返回 NULL 值。</returns>
  67. public static byte[] Send(byte[] bytes, int port, string ip = "127.0.0.1", bool await = false)
  68. {
  69. return Send(ip, port, bytes, false);
  70. }
  71. /// <summary>向指定服务端发送数据。</summary>
  72. /// <param name="ip">服务端 IP 地址。</param>
  73. /// <param name="port">服务端端口。</param>
  74. /// <param name="bytes">数据。</param>
  75. /// <param name="await">阻塞当前线程,等待服务端返回数据,指定 FALSE 将立刻返回 NULL 值。</param>
  76. /// <returns>服务器返回的数据。当通过 await 参数指定 FALSE 时,立刻返回 NULL 值。</returns>
  77. public static byte[] Send(int port, byte[] bytes, string ip = "127.0.0.1", bool await = false)
  78. {
  79. return Send(ip, port, bytes, false);
  80. }
  81. /// <summary>唤醒局域网中拥有指定 MAC 地址的设备。</summary>
  82. /// <param name="mac">被唤醒设备的 MAC 地址,必须是长度为 6 的字节数组。</param>
  83. public static void WakeOnLan(byte[] mac)
  84. {
  85. if (mac.Length != 6) return;
  86. var uc = new System.Net.Sockets.UdpClient();
  87. uc.Connect(IPAddress.Broadcast, 65535);
  88. var pack = new List<byte>();
  89. // 前 6 字节为 0xFF。
  90. for (int i = 0; i < 6; i++) pack.Add(255);
  91. // 目标 MAC 地址重复 16 次。
  92. for (int i = 0; i < 16; i++)
  93. {
  94. for (int j = 0; j < 6; j++) pack.Add(mac[j]);
  95. }
  96. // 发送 102 字节数据。
  97. uc.Send(pack.ToArray(), pack.Count);
  98. uc.Close();
  99. }
  100. }
  101. }