SocketManager.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Concurrent;
  4. using System.Collections.Generic;
  5. using System.Net.Sockets;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. using System.Net;
  9. using System;
  10. using System.Text;
  11. using System.IO;
  12. using pb = Google.Protobuf;
  13. ///// <summary>
  14. ///// 聊天部分使用的
  15. ///// </summary>
  16. //[Obsolete("-g",true)]
  17. //public class SocketManager
  18. //{
  19. // private static SocketManager _instance;
  20. // public static SocketManager Instance
  21. // {
  22. // get
  23. // {
  24. // if (_instance == null)
  25. // {
  26. // _instance = new SocketManager();
  27. // }
  28. // return _instance;
  29. // }
  30. // }
  31. // private string _currIP;
  32. // private int _currPort;
  33. // private bool _isConnected = false;
  34. // public bool IsConnceted { get { return _isConnected; } }
  35. // private Socket clientSocket = null;
  36. // private Thread receiveThread = null;
  37. // private DataBuffer _databuffer = new DataBuffer();
  38. // byte[] _tmpReceiveBuff = new byte[4096];
  39. // private sSocketData _socketData = new sSocketData();
  40. // /// <summary>
  41. // /// 断开
  42. // /// </summary>
  43. // private void _close()
  44. // {
  45. // if (!_isConnected)
  46. // return;
  47. // _isConnected = false;
  48. // if (receiveThread != null)
  49. // {
  50. // receiveThread.Abort();
  51. // receiveThread = null;
  52. // }
  53. // if (clientSocket != null && clientSocket.Connected)
  54. // {
  55. // clientSocket.Close();
  56. // clientSocket = null;
  57. // }
  58. // }
  59. // private void _ReConnect()
  60. // {
  61. // }
  62. // /// <summary>
  63. // /// 连接
  64. // /// </summary>
  65. // private void _onConnet()
  66. // {
  67. // try
  68. // {
  69. // clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建套接字
  70. // IPAddress ipAddress = IPAddress.Parse(_currIP); //解析IP地址
  71. // IPEndPoint ipEndpoint = new IPEndPoint(ipAddress, _currPort);
  72. // IAsyncResult result = clientSocket.BeginConnect(ipEndpoint, new AsyncCallback(_onConnect_Sucess), clientSocket);//异步连接
  73. // bool success = result.AsyncWaitHandle.WaitOne(5000, true);
  74. // if (!success) //超时
  75. // {
  76. // _onConnect_Outtime();
  77. // }
  78. // clientSocket.SetKeepAlive(1000);
  79. // }
  80. // catch (System.Exception _e)
  81. // {
  82. // _onConnect_Fail();
  83. // }
  84. // }
  85. // private void _onConnect_Sucess(IAsyncResult iar)
  86. // {
  87. // try
  88. // {
  89. // Socket client = (Socket)iar.AsyncState;
  90. // client.EndConnect(iar);
  91. // receiveThread = new Thread(new ThreadStart(_onReceiveSocket));
  92. // receiveThread.IsBackground = true;
  93. // receiveThread.Start();
  94. // _isConnected = true;
  95. // LogHelper.Log("连接成功");
  96. // }
  97. // catch (Exception _e)
  98. // {
  99. // Close();
  100. // }
  101. // }
  102. // private void _onConnect_Outtime()
  103. // {
  104. // _close();
  105. // }
  106. // private void _onConnect_Fail()
  107. // {
  108. // _close();
  109. // }
  110. // /// <summary>
  111. // /// 发送消息结果回掉,可判断当前网络状态
  112. // /// </summary>
  113. // /// <param name="asyncSend"></param>
  114. // private void _onSendMsg(IAsyncResult asyncSend)
  115. // {
  116. // try
  117. // {
  118. // Socket client = (Socket)asyncSend.AsyncState;
  119. // client.EndSend(asyncSend);
  120. // }
  121. // catch (Exception e)
  122. // {
  123. // LogHelper.Log("send msg exception:" + e.StackTrace);
  124. // }
  125. // }
  126. // /// <summary>
  127. // /// 接受网络数据
  128. // /// </summary>
  129. // private void _onReceiveSocket()
  130. // {
  131. // while (true)
  132. // {
  133. // if (!clientSocket.Connected)
  134. // {
  135. // _isConnected = false;
  136. // _ReConnect();
  137. // break;
  138. // }
  139. // try
  140. // {
  141. // int receiveLength = clientSocket.Receive(_tmpReceiveBuff);
  142. // if (receiveLength > 0)
  143. // {
  144. // _databuffer.AddBuffer(_tmpReceiveBuff, receiveLength);//将收到的数据添加到缓存器中
  145. // while (_databuffer.GetData(out _socketData))//取出一条完整数据
  146. // {
  147. // MessageCenter.Instance._netMessageDataQueue.Enqueue(_socketData);
  148. // }
  149. // }
  150. // }
  151. // catch (Exception e)
  152. // {
  153. // clientSocket.Disconnect(true);
  154. // clientSocket.Shutdown(SocketShutdown.Both);
  155. // clientSocket.Close();
  156. // break;
  157. // }
  158. // }
  159. // }
  160. // /// <summary>
  161. // /// ProtoBuf序列化
  162. // /// </summary>
  163. // /// <param name="data"></param>
  164. // /// <returns></returns>
  165. // public static byte[] ProtoBuf_Serializer(pb::IMessage data)
  166. // {
  167. // using (var ms = new MemoryStream())
  168. // using (var os = new pb::CodedOutputStream(ms))
  169. // {
  170. // data.WriteTo(os);
  171. // os.Flush();
  172. // ms.Seek(0, SeekOrigin.Begin);
  173. // return ms.ToArray();
  174. // }
  175. // }
  176. // /// <summary>
  177. // /// ProtoBuf反序列化
  178. // /// </summary>
  179. // /// <typeparam name="T"></typeparam>
  180. // /// <param name="_data"></param>
  181. // /// <returns></returns>
  182. // public static T ProtoBuf_Deserialize<T>(byte[] _data) where T : pb::IMessage<T>, new()
  183. // {
  184. // var _parser = new pb::MessageParser<T>(() => new T());
  185. // return _parser.ParseFrom(_data);
  186. // }
  187. // /// <summary>
  188. // /// 连接服务器
  189. // /// </summary>
  190. // /// <param name="_currIP"></param>
  191. // /// <param name="_currPort"></param>
  192. // public void Connect(string _currIP, int _currPort)
  193. // {
  194. // if (!IsConnceted)
  195. // {
  196. // this._currIP = _currIP;
  197. // this._currPort = _currPort;
  198. // _onConnet();
  199. // }
  200. // else if (clientSocket == null || !clientSocket.Connected)
  201. // {
  202. // _ReConnect();
  203. // }
  204. // }
  205. // /// <summary>
  206. // /// 发送消息基本方法
  207. // /// </summary>
  208. // /// <param name="_protocalType"></param>
  209. // /// <param name="_data"></param>
  210. // private void SendMsgBase(eProtocalCommand _protocalType, byte[] _data)
  211. // {
  212. // if (clientSocket == null || !clientSocket.Connected)
  213. // {
  214. // _ReConnect();
  215. // return;
  216. // }
  217. // //byte[] _msgdata = DataToBytes(_protocalType, _data);
  218. // var sd = sSocketData.FromBytes(_protocalType, _data);
  219. // try
  220. // {
  221. // clientSocket.BeginSend(sd.ToBytes(), 0, sd.PackLen, SocketFlags.None, new AsyncCallback(_onSendMsg), clientSocket);
  222. // }
  223. // catch (System.Exception e)
  224. // {
  225. // LogHelper.Log(e.Message);
  226. // clientSocket.Disconnect(true);
  227. // clientSocket.Shutdown(SocketShutdown.Both);
  228. // clientSocket.Close();
  229. // }
  230. // }
  231. // /// <summary>
  232. // /// 以二进制方式发送
  233. // /// </summary>
  234. // /// <param name="_protocalType"></param>
  235. // /// <param name="_byteStreamBuff"></param>
  236. // public void SendMsg(eProtocalCommand _protocalType, ByteStreamBuff _byteStreamBuff)
  237. // {
  238. // SendMsgBase(_protocalType, _byteStreamBuff.ToArray());
  239. // }
  240. // /// <summary>
  241. // /// 以ProtoBuf方式发送
  242. // /// </summary>
  243. // /// <param name="_protocalType"></param>
  244. // /// <param name="data"></param>
  245. // public void SendMsg(eProtocalCommand _protocalType, pb::IMessage data)
  246. // {
  247. // SendMsgBase(_protocalType, ProtoBuf_Serializer(data));
  248. // }
  249. // public void Close()
  250. // {
  251. // _close();
  252. // }
  253. //}
  254. /// <summary>
  255. /// boss战部分使用的
  256. /// </summary>
  257. public class TasPBSocketManager
  258. {
  259. private string _currIP;
  260. private int _currPort;
  261. private bool _isConnected = false;
  262. public bool IsConnceted { get { return _isConnected; } }
  263. private Socket clientSocket = null;
  264. private Thread receiveThread = null;
  265. private Task _receiveTask = null;
  266. private DataBuffer _databuffer = new DataBuffer();
  267. byte[] _tmpReceiveBuff = new byte[4096];
  268. private sSocketData _socketData = new sSocketData();
  269. public Action OnConnected;
  270. public Action OnDisconnected;
  271. /// <summary>
  272. /// 断开
  273. /// </summary>
  274. public void Close()
  275. {
  276. if (!_isConnected)
  277. return;
  278. _isConnected = false;
  279. if (receiveThread != null)
  280. {
  281. receiveThread.Abort();
  282. receiveThread = null;
  283. }
  284. if (clientSocket != null && clientSocket.Connected)
  285. {
  286. //clientSocket.Disconnect(true);
  287. clientSocket.Shutdown(SocketShutdown.Both);
  288. clientSocket.Close();
  289. clientSocket = null;
  290. }
  291. }
  292. private void _ReConnect()
  293. {
  294. }
  295. /// <summary>
  296. /// 连接服务器
  297. /// </summary>
  298. /// <param name="_currIP"></param>
  299. /// <param name="_currPort"></param>
  300. public void Connect(string _currIP, int _currPort)
  301. {
  302. if (!IsConnceted)
  303. {
  304. this._currIP = _currIP;
  305. this._currPort = _currPort;
  306. _onConnet();
  307. }
  308. else if (clientSocket == null || !clientSocket.Connected)
  309. {
  310. _ReConnect();
  311. }
  312. }
  313. /// <summary>
  314. /// 连接
  315. /// </summary>
  316. private async void _onConnet()
  317. {
  318. try
  319. {
  320. clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建套接字
  321. IPAddress ipAddress = IPAddress.Parse(_currIP); //解析IP地址
  322. IPEndPoint ipEndpoint = new IPEndPoint(ipAddress, _currPort);
  323. await clientSocket.ConnectAsync(ipEndpoint).WaitAsync(TimeSpan.FromSeconds(5));
  324. clientSocket.SetKeepAlive(60 * 1000);
  325. receiveThread = new Thread(new ThreadStart(_onReceiveSocket));
  326. receiveThread.IsBackground = true;
  327. receiveThread.Start();
  328. _isConnected = true;
  329. LogHelper.Log("连接成功");
  330. OnConnected?.Invoke();
  331. }
  332. catch (TimeoutException e)
  333. {
  334. LogHelper.LogError("连接超时");
  335. Close();
  336. }
  337. catch (Exception _e)
  338. {
  339. LogHelper.LogError("连接失败" + _e.Message);
  340. Close();
  341. }
  342. }
  343. /// <summary>
  344. /// 接受网络数据
  345. /// </summary>
  346. private async void _onReceiveSocket()
  347. {
  348. while (true)
  349. {
  350. if (!clientSocket.Connected)
  351. {
  352. _isConnected = false;
  353. _ReConnect();
  354. break;
  355. }
  356. try
  357. {
  358. var receiveLength = await clientSocket.ReceiveAsync(new ArraySegment<byte>(_tmpReceiveBuff), SocketFlags.None); // 将接收到的信息存入到内存缓冲区,并返回其字节数组的长度
  359. if (receiveLength > 0)
  360. {
  361. _databuffer.AddBuffer(_tmpReceiveBuff, receiveLength);//将收到的数据添加到缓存器中
  362. while (_databuffer.GetData(out _socketData))//取出一条完整数据
  363. {
  364. MessageCenter.Instance._netMessageDataQueue.Enqueue(_socketData);
  365. }
  366. }
  367. else
  368. { // 收到0字节数据视为对端连接已断开
  369. OnDisconnected?.Invoke();
  370. LogHelper.Log("发现对端断开连接.");
  371. Close();
  372. }
  373. }
  374. catch (Exception e)
  375. {
  376. Close();
  377. break;
  378. }
  379. }
  380. }
  381. /// <summary>
  382. /// ProtoBuf反序列化
  383. /// </summary>
  384. /// <typeparam name="T"></typeparam>
  385. /// <param name="_data"></param>
  386. /// <returns></returns>
  387. public static T ProtoBuf_Deserialize<T>(byte[] _data) where T : pb::IMessage<T>, new()
  388. {
  389. var _parser = new pb::MessageParser<T>(() => new T());
  390. return _parser.ParseFrom(_data);
  391. }
  392. /// <summary>
  393. /// 发送消息基本方法
  394. /// </summary>
  395. private async void SendMsgBase()
  396. {
  397. if (this.IsConnceted)
  398. {
  399. if (clientSocket == null || !clientSocket.Connected)
  400. {
  401. _ReConnect();
  402. return;
  403. }
  404. while (_msgQueue.TryDequeue(out var kv))
  405. {
  406. LogHelper.Log($"send msg in queue {kv.Key}");
  407. var msg = sSocketData.FromIMsg(kv.Key, kv.Value);
  408. try
  409. {
  410. await clientSocket.SendAsync(new ArraySegment<byte>(msg.ToBytes()), SocketFlags.None);
  411. }
  412. catch (Exception e)
  413. {
  414. LogHelper.Log(e.Message);
  415. Close();
  416. }
  417. }
  418. }
  419. }
  420. public void Update()
  421. {
  422. SendMsgBase();
  423. }
  424. /// <summary>
  425. /// 以ProtoBuf方式发送
  426. /// </summary>
  427. /// <param name="_protocalType"></param>
  428. /// <param name="data"></param>
  429. public void SendMsg(eProtocalCommand _protocalType, pb::IMessage data)
  430. {
  431. _msgQueue.Enqueue(new KeyValuePair<eProtocalCommand, pb.IMessage>(_protocalType, data));
  432. }
  433. private ConcurrentQueue<KeyValuePair<eProtocalCommand, pb::IMessage>> _msgQueue = new ConcurrentQueue<KeyValuePair<eProtocalCommand, pb.IMessage>>();
  434. }