• unity Socket 客户端向服务端发送消息并实现简单远程控制


    需求:想在开发的应用中加一个简单的后台控制,并向服务器发送该设备基本信息(公网ip,机器码,等);在服务器控制该设备是否可以正常打开该应用。

    已实现功能:每个每个应用(客户端)向服务端发送设备信息等数据。服务器端对数据处理后存储到服务器本地JSON里。客户端打开是要判断服务器是否禁止该设备使用。服务器端JSON文件可以查看该应用每个用户使用次数和打开时间等。(实现一个简单的远程控制)。

    待实现功能:判断用户单次使用时间并写入JSON

    客户端:发送设备信息到服务器。

    服务端:用来接收客户端数据,并且存储json到服务器。

    使用socket来写。

    客户端代码:

    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using System.Net;
    4. using System.Net.Sockets;//引入socket命名空间
    5. using System.Threading;
    6. using System.Text;
    7. using UnityEngine.SceneManagement;
    8. using System.IO;
    9. using System.Net.NetworkInformation;
    10. using System;
    11. using System.Collections;
    12. using UnityEngine.Networking;
    13. using System.Collections.Generic;
    14. using Newtonsoft.Json;
    15. #region json格式解析
    16. [Serializable]
    17. public class Info
    18. {
    19. public string DeviceCode;
    20. public string Ip;
    21. public string productName;
    22. public string DeviceInfo;
    23. public List<string> time;
    24. public int count;
    25. public string Switch;
    26. }
    27. #endregion
    28. public class Client : MonoBehaviour
    29. {
    30. public Text text;//在屏幕上显示出设备信息
    31. public string path;//Json文件在服务器上的路径
    32. void Start()
    33. {
    34. //连接服务器
    35. ConnectServer();
    36. #region 显示设备信息
    37. string info = "设备的详细信息" +
    38. "\n设备名称: " + SystemInfo.deviceName
    39. + "\nCPU类型:" + SystemInfo.processorType
    40. + "\n" + "设备唯一识别标识:" + SystemInfo.deviceUniqueIdentifier
    41. + "\n" + "显卡名称:" + SystemInfo.graphicsDeviceName
    42. + "\n显卡厂商:" + SystemInfo.graphicsDeviceVendor
    43. + "\n" + "操作系统:" + SystemInfo.operatingSystem
    44. + "\n" + "MAC地址:" + GetMacAddress()
    45. + "\n" + "公网IP:" + GetIp("http://104.16.22.1/cdn-cgi/trace");
    46. text.text = info;
    47. #endregion
    48. StartCoroutine(GetData());
    49. }
    50. ///
    51. /// 此协程用来判断服务器存的字典中是否禁止此设备运行本软件
    52. ///
    53. ///
    54. IEnumerator GetData()
    55. {
    56. UnityWebRequest www = UnityWebRequest.Get(path);
    57. yield return www.SendWebRequest();
    58. if (www.result != UnityWebRequest.Result.Success)
    59. {
    60. Debug.Log(www.error);
    61. }
    62. else
    63. {
    64. var ip = www.downloadHandler.text.ToString();
    65. Dictionary<string, Info> root = new Dictionary<string, Info>();
    66. root = JsonConvert.DeserializeObjectstring, Info>>(ip);//解析json
    67. if (root.ContainsKey(SystemInfo.deviceUniqueIdentifier))//字典中是否存在此设备
    68. {
    69. if (root[SystemInfo.deviceUniqueIdentifier].Switch == "关")//判断是否关闭应用
    70. {
    71. Application.Quit();
    72. }
    73. }
    74. }
    75. }
    76. ///
    77. /// 连接服务器
    78. ///
    79. static Socket socket_client;
    80. public static void ConnectServer()
    81. {
    82. try
    83. {
    84. IPAddress pAddress = IPAddress.Parse("服务器公网IP"); //如果是本地就写本地ipv4地址
    85. IPEndPoint pEndPoint = new IPEndPoint(pAddress, 服务器端口号);
    86. socket_client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    87. socket_client.Connect(pEndPoint);
    88. Debug.Log("连接成功");
    89. string info = "设备的详细信息:" +
    90. "设备名称: " + SystemInfo.deviceName
    91. + "——CPU类型:" + SystemInfo.processorType
    92. + "——" + "设备唯一识别标识:" + SystemInfo.deviceUniqueIdentifier
    93. + "——" + "显卡名称:" + SystemInfo.graphicsDeviceName
    94. + "——显卡厂商:" + SystemInfo.graphicsDeviceVendor
    95. + "——" + "操作系统:" + SystemInfo.operatingSystem
    96. + "——" + "MAC地址:" + GetMacAddress()
    97. + "——" + "公网IP:" + GetIp("http://104.16.22.1/cdn-cgi/trace");
    98. Send(SystemInfo.deviceUniqueIdentifier + "_" + GetIp("http://104.16.22.1/cdn-cgi/trace")+"_"+ Application.productName+Application.version + "_" + info);
    99. //创建线程,执行读取服务器消息
    100. Thread c_thread = new Thread(Received);
    101. c_thread.IsBackground = true;
    102. c_thread.Start();
    103. }
    104. catch (System.Exception)
    105. {
    106. Debug.Log("IP端口号错误或者服务器未开启");
    107. }
    108. }
    109. ///
    110. /// 读取服务器消息
    111. ///
    112. public static void Received()
    113. {
    114. while (true)
    115. {
    116. try
    117. {
    118. byte[] buffer = new byte[1024];
    119. int len = socket_client.Receive(buffer);
    120. if (len == 0) break;
    121. string str = Encoding.UTF8.GetString(buffer, 0, len);
    122. Debug.Log("客户端打印服务器返回消息:" + socket_client.RemoteEndPoint + ":" + str);
    123. }
    124. catch (System.Exception)
    125. {
    126. throw;
    127. }
    128. }
    129. }
    130. ///
    131. /// 发送消息
    132. ///
    133. ///
    134. public static void Send(string msg)
    135. {
    136. try
    137. {
    138. byte[] buffer = new byte[1024];
    139. buffer = Encoding.UTF8.GetBytes(msg);
    140. socket_client.Send(buffer);
    141. }
    142. catch (System.Exception)
    143. {
    144. Debug.Log("未连接");
    145. }
    146. }
    147. ///
    148. /// 关闭连接
    149. ///
    150. public static void close()
    151. {
    152. try
    153. {
    154. socket_client.Close();
    155. Debug.Log("关闭客户端连接");
    156. SceneManager.LoadScene("control");
    157. }
    158. catch (System.Exception)
    159. {
    160. Debug.Log("未连接");
    161. }
    162. }
    163. private void OnDestroy()
    164. {
    165. close();
    166. }
    167. ///
    168. /// 获取公网ip
    169. ///
    170. ///
    171. ///
    172. public static string GetIp(string ipurl)
    173. {
    174. UnityWebRequest request = UnityWebRequest.Get(ipurl);
    175. request.SendWebRequest();//读取数据
    176. while (true)
    177. {
    178. if (request.downloadHandler.isDone)//是否读取完数据
    179. {
    180. var ip = request.downloadHandler.text.ToString().Substring(request.downloadHandler.text.IndexOf("ip=") + 3, request.downloadHandler.text.IndexOf("ts=") - request.downloadHandler.text.IndexOf("ip=") - 4);
    181. return ip;
    182. }
    183. }
    184. }
    185. ///
    186. /// 获取设备MAC地址
    187. ///
    188. ///
    189. private static string GetMacAddress()
    190. {
    191. //MAC 地址字符串
    192. string _PhysicalAddress = "";
    193. //获取所有网络接口
    194. NetworkInterface[] _Nice = NetworkInterface.GetAllNetworkInterfaces();
    195. foreach (NetworkInterface _Adaper in _Nice)
    196. {
    197. //得到物理地址
    198. _PhysicalAddress = _Adaper.GetPhysicalAddress().ToString();
    199. if (_PhysicalAddress != "")
    200. {
    201. break;
    202. };
    203. }
    204. return _PhysicalAddress;
    205. }
    206. }

    服务端代码:

    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System.Net.Sockets;//需要引用socket命名空间
    5. using System.Net;
    6. using System.Linq;
    7. using System.Text;
    8. using System.Threading;
    9. using UnityEngine.UI;
    10. using System.IO;
    11. using System;
    12. using Newtonsoft.Json;
    13. #region json格式解析
    14. [Serializable]
    15. public class Info
    16. {
    17. public string DeviceCode;
    18. public string Ip;
    19. public string productName;
    20. public string DeviceInfo;
    21. public List<string> time;
    22. public int count;
    23. public string Switch;
    24. }
    25. #endregion
    26. public class Server : MonoBehaviour
    27. {
    28. public List<string> logs;
    29. public Text text;//显示log
    30. public string m_IP;//服务器ip(内网)
    31. public string m_Path;//服务器json文件路径
    32. void Start()
    33. {
    34. openServer();
    35. }
    36. ///
    37. /// 解析json文件
    38. ///
    39. ///
    40. Dictionary<string, Info> LoadJson()
    41. {
    42. Dictionary<string, Info> root = new Dictionary<string, Info>();
    43. if (File.Exists(m_Path))
    44. {
    45. root = JsonConvert.DeserializeObjectstring, Info>>(File.ReadAllText(m_Path));
    46. }
    47. return root;
    48. }
    49. ///
    50. /// 处理数据
    51. ///
    52. /// 客户端发来的数据
    53. public void DataDiapose(object obj)
    54. {
    55. Dictionary<string, Info> dic = LoadJson();
    56. List<string> times = new List<string>();
    57. Loom.QueueOnMainThread((param) =>
    58. {
    59. Info info = new Info();
    60. info.DeviceCode = obj.ToString().Split('_')[0];
    61. info.Ip = obj.ToString().Split('_')[1];
    62. info.productName = obj.ToString().Split('_')[2];
    63. info.DeviceInfo = obj.ToString().Split('_')[3];
    64. times.Add(DateTime.Now.ToString());
    65. info.time= times;
    66. info.count = 1;
    67. if (!dic.ContainsKey(info.DeviceCode))//如果json中没有该设备的信息,存入
    68. {
    69. dic.Add(info.DeviceCode, info);
    70. }
    71. else
    72. {
    73. //如果有就加入本次打开时间并增加使用次数
    74. dic[info.DeviceCode].time.Add(DateTime.Now.ToString());
    75. dic[info.DeviceCode].count += 1;
    76. }
    77. WriteJson(dic); //把新数据写入json
    78. }, null);
    79. }
    80. ///
    81. /// 写入json
    82. ///
    83. ///
    84. public void WriteJson(Dictionary<string, Info> info)
    85. {
    86. if (File.Exists(m_Path))
    87. {
    88. File.Delete(m_Path);
    89. }
    90. Debug.Log(m_Path);
    91. //找到当前路径
    92. FileInfo fileInfo = new FileInfo(m_Path);
    93. //判断有没有文件,有则打开,没有则创建后打开
    94. StreamWriter sw = fileInfo.CreateText();
    95. //ToJson接口将你的列表类传进去,转为string
    96. string json = JsonConvert.SerializeObject(info);
    97. //将转换好的字符串保存到文件
    98. sw.WriteLine(json);
    99. //释放资源
    100. sw.Close();
    101. sw.Dispose();
    102. }
    103. //在text上刷新显示log
    104. public void MyLog(object lg)
    105. {
    106. Loom.QueueOnMainThread((param) =>
    107. {
    108. if (logs.Count >= 10)
    109. {
    110. logs.RemoveAt(0);
    111. }
    112. logs.Add(lg.ToString());
    113. text.text = "";
    114. foreach (var item in logs)
    115. {
    116. text.text += item + "\n";
    117. }
    118. }, null);
    119. }
    120. ///
    121. /// 打开链接
    122. ///
    123. void openServer()
    124. {
    125. try
    126. {
    127. IPAddress pAddress = IPAddress.Parse(m_IP);
    128. IPEndPoint pEndPoint = new IPEndPoint(pAddress, 12345);
    129. Socket socket_server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    130. socket_server.Bind(pEndPoint);
    131. socket_server.Listen(5);//设置最大连接数
    132. Debug.Log("监听成功");
    133. Loom.RunAsync(
    134. () =>
    135. {
    136. ParameterizedThreadStart ParStart1 = new ParameterizedThreadStart(MyLog);
    137. Thread thread2 = new Thread(ParStart1);
    138. object o = " 监听成功 ";
    139. thread2.Start(o);
    140. }
    141. );
    142. //创建新线程执行监听,否则会阻塞UI,导致unity无响应
    143. Thread thread = new Thread(listen);
    144. thread.IsBackground = true;
    145. thread.Start(socket_server);
    146. }
    147. catch (System.Exception)
    148. {
    149. throw;
    150. }
    151. }
    152. ///
    153. /// 监听
    154. ///
    155. Socket socketSend;
    156. void listen(object o)
    157. {
    158. try
    159. {
    160. Socket socketWatch = o as Socket;
    161. while (true)
    162. {
    163. socketSend = socketWatch.Accept();
    164. string tempStr = socketSend.RemoteEndPoint.ToString() + ":" + "连接成功";
    165. Debug.Log(tempStr);
    166. Loom.RunAsync(
    167. () =>
    168. {
    169. ParameterizedThreadStart ParStart1 = new ParameterizedThreadStart(MyLog);
    170. Thread thread2 = new Thread(ParStart1);
    171. object oo = tempStr;
    172. thread2.Start(oo);
    173. }
    174. );
    175. Thread r_thread = new Thread(Received);
    176. r_thread.IsBackground = true;
    177. r_thread.Start(socketSend);
    178. }
    179. }
    180. catch (System.Exception)
    181. {
    182. throw;
    183. }
    184. }
    185.    ///
    186. /// 获取消息
    187. ///
    188. ///
    189. void Received(object o)
    190. {
    191. try
    192. {
    193. Socket socketSend = o as Socket;
    194. while (true)
    195. {
    196. byte[] buffer = new byte[1024];
    197. int len = socketSend.Receive(buffer);
    198. if (len == 0) break;
    199. string str = Encoding.UTF8.GetString(buffer, 0, len);
    200. string tempStr = "服务器打印客户端返回消息:" + socketSend.RemoteEndPoint + ":" + DateTime.Now+"登录";
    201. Debug.Log(tempStr);
    202. Loom.RunAsync(
    203. () =>
    204. {
    205. ParameterizedThreadStart ParStart = new ParameterizedThreadStart(DataDiapose);
    206. Thread thread2 = new Thread(ParStart);
    207. object o2 = str;
    208. thread2.Start(o2);
    209. }
    210. );
    211. Loom.RunAsync(
    212. () =>
    213. {
    214. ParameterizedThreadStart ParStart1 = new ParameterizedThreadStart(MyLog);
    215. Thread thread2 = new Thread(ParStart1);
    216. object oo = tempStr;
    217. thread2.Start(oo);
    218. }
    219. );
    220. //Send("我收到了");
    221. }
    222. }
    223. catch (System.Exception)
    224. {
    225. throw;
    226. }
    227. }
    228. ///
    229. /// 发送消息
    230. ///
    231. ///
    232. void Send(string msg)
    233. {
    234. byte[] buffer = Encoding.UTF8.GetBytes(msg);
    235. socketSend.Send(buffer);
    236. }
    237. }

     效果:

     

     

    工程:下载链接icon-default.png?t=M7J4https://download.csdn.net/download/Dore__/86438470

    直接打开两个项目或分别将以下两个unitypackage包导入项目

     

  • 相关阅读:
    flink源码分析之功能组件(四)-slot管理组件I
    混合背包问题
    19. 删除链表的倒数第 N 个结点
    Kubernetes资源编排系列之三: Kustomize篇
    Ant Design Vue - 去掉 <a-tabs> 标签页组件底部细条灰色线(清掉选项卡组件整体底部灰色黑色细线)
    海藻酸钠-peg-环糊精|alginate-peg-Cyclodextrin
    [Python进阶] 目录相关库:os、pathlib、shutil
    141.环形链表
    【Linux】—一文掌握Linux基本命令(上)
    ASP.NET添加MVC控制器报错
  • 原文地址:https://blog.csdn.net/Dore__/article/details/126492751