Program_Chat.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. using System;
  2. using System.IO;
  3. using System.Text;
  4. using System.Threading;
  5. using System.Threading.Tasks;
  6. using System.Threading.Channels;
  7. using System.Linq;
  8. using System.Net.Http;
  9. using System.Collections.Generic;
  10. using Newtonsoft.Json;
  11. using Newtonsoft.Json.Linq;
  12. using System.Net;
  13. using System.Net.Sockets;
  14. using System.Diagnostics;
  15. using ProtoDataBuff;
  16. using Chat;
  17. using pb = global::Google.Protobuf;
  18. namespace clientTest.chat
  19. {
  20. public static class TaskWaitingExtensions
  21. {
  22. public static async Task<TResult> WaitAsync<TResult>(this Task<TResult> task, TimeSpan timeout)
  23. {
  24. using (var timeoutCancellationTokenSource = new CancellationTokenSource())
  25. {
  26. var delayTask = Task.Delay(timeout, timeoutCancellationTokenSource.Token);
  27. if (await Task.WhenAny(task, delayTask) == task)
  28. {
  29. timeoutCancellationTokenSource.Cancel();
  30. return await task;
  31. }
  32. throw new TimeoutException("The operation has timed out.");
  33. }
  34. }
  35. public static async Task WaitAsync(this Task task, TimeSpan timeout)
  36. {
  37. using (var timeoutCancellationTokenSource = new CancellationTokenSource())
  38. {
  39. var delayTask = Task.Delay(timeout, timeoutCancellationTokenSource.Token);
  40. if (await Task.WhenAny(task, delayTask) == task)
  41. {
  42. timeoutCancellationTokenSource.Cancel();
  43. return;
  44. }
  45. throw new TimeoutException("The operation has timed out.");
  46. }
  47. }
  48. }
  49. class Program
  50. {
  51. static readonly string[] names = new string[] { "你猜(尼采)", "黑哥儿(黑格尔)", "孟德四舅" };
  52. static readonly string[] texts = new string[] {
  53. "一个人可以失败很多次,但是只要他没有开始责怪旁人,他还不是一个失败者。",
  54. "这个世界既不是有钱人的世界,也不是有权人的世界,它是有心人的世界。",
  55. "伟人之所以伟大,是因为他与别人共处逆境时,别人失去了信心,他却下决心实现自己的目标。",
  56. "世上没有绝望的处境,只有对处境绝望的人。 ",
  57. "时间就像一张网,你撒在哪里,收获就在哪里。",
  58. "心若计较,处处都是怨言;心不计较,时时都是晴天。",
  59. "能使我们感觉快乐的,不是环境,而是态度。",
  60. "学问是用来实践的,不是拿来用嘴说的。",
  61. "自己打败自己是最可悲的失败,自己战胜自己是最可贵的胜利。",
  62. "我们得成功,其实成功有一条很简单的定律:“只要站起来的次数比被击倒的次数多一次就行。",
  63. " 弱者坐待良机,强者创造时机。",
  64. " 没有不会做的事, 只有不想做的事。",
  65. "任何的限制, 都是从自己内心开始的。",
  66. "只要还有明天, 今日就永远是起跑线。",
  67. "既然认准一条道路, 何必去打听要走多久。",
  68. "现在站在什么地方不重要,重要的是你往什么方向移动?",
  69. "如果什么都想要,只会什么都得不到。"
  70. };
  71. static readonly Random r = new Random();
  72. /// <summary>
  73. /// 消息分发
  74. /// </summary>
  75. static private Dictionary<eProtocalCommand, Action<sSocketData>> callbacks = new Dictionary<eProtocalCommand, Action<sSocketData>>();
  76. static void Main(string[] args)
  77. {
  78. callbacks.Add(eProtocalCommand.ScChatNewMsg, On_update);
  79. callbacks.Add(eProtocalCommand.ScChatLogin, On_LoginOver);
  80. var n = 10;
  81. var list = new Task[n];
  82. for (int i = 0; i < n; i++)
  83. {
  84. list[i] = Task.Run(async () => await send());
  85. }
  86. Task.Run(Dispatch);
  87. Task.WaitAll(list);
  88. }
  89. static string ChannelName(ChatChannel c) => c switch
  90. {
  91. ChatChannel.System => "系统",
  92. ChatChannel.World => "世界",
  93. ChatChannel.Guild => "公会",
  94. _ => "x",
  95. };
  96. /// <summary>
  97. /// 处理客户端上报伤害请求
  98. /// </summary>
  99. static void On_update(sSocketData data)
  100. {
  101. var msg = SC_ChatNewMsg.Parser.ParseFrom(data._data);
  102. Console.WriteLine($"[{ChannelName(msg.FromChannel)}]-[{msg.SenderName}] : " + msg.Msg);
  103. }
  104. /// <summary>
  105. /// 处理客户端上报伤害请求
  106. /// </summary>
  107. static void On_LoginOver(sSocketData data)
  108. {
  109. var msg = SC_ChatLogin.Parser.ParseFrom(data._data);
  110. Console.WriteLine("登录结果: " + msg.Code);
  111. //Task.Delay(3000).ContinueWith(t => Environment.Exit(0));
  112. }
  113. static async Task send()
  114. {
  115. var port = 6000;
  116. var endPoint = new IPEndPoint(IPAddress.Parse("192.168.10.86"), port);
  117. //var endPoint = new IPEndPoint(IPAddress.Parse("115.159.121.129"), port);
  118. using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
  119. {
  120. try
  121. {
  122. await client.ConnectAsync(endPoint);
  123. }
  124. catch (Exception ee)
  125. {
  126. Debug.WriteLine(ee.Message);
  127. }
  128. var t = Task.Run(() => recv(client));
  129. await login(client);
  130. var i = 0;
  131. while (i++ < 10)
  132. {
  133. try
  134. {
  135. await sendMsg(client);
  136. Thread.Sleep(r.Next(1000, 1100));
  137. }
  138. catch (Exception e)
  139. {
  140. client.Close();
  141. break;
  142. }
  143. }
  144. }
  145. }
  146. async static Task login(Socket Sock)
  147. {
  148. try
  149. {
  150. var msg = new CS_ChatLogin() { Uid = Guid.NewGuid().ToString(), Zoneid = 1, Name = names[r.Next(0, 3)] + r.Next() };
  151. var data = SocketDataToBytes(BytesToSocketData(eProtocalCommand.CsChatLogin, IMsg2Bytes(msg)));
  152. await Sock.SendAsync(new ArraySegment<byte>(data), SocketFlags.None);
  153. }
  154. catch (Exception e)
  155. {
  156. Sock.Close();
  157. }
  158. }
  159. async static Task sendMsg(Socket sock)
  160. {
  161. var c = (ChatChannel)r.Next(0, 3);
  162. var info = texts[r.Next(0, texts.Length)];
  163. var msg = new CS_ChatSendMsg() { ToChannel = c, Msg = info };
  164. var data = SocketDataToBytes(BytesToSocketData(eProtocalCommand.CsChatSendMsg, IMsg2Bytes(msg)));
  165. await sock.SendAsync(new ArraySegment<byte>(data), SocketFlags.None);
  166. }
  167. static byte[] IMsg2Bytes(pb::IMessage msg)
  168. {
  169. using var ms = new MemoryStream();
  170. using var goutstream = new pb::CodedOutputStream(ms);
  171. msg.WriteTo(goutstream);
  172. goutstream.Flush();
  173. ms.Seek(0, SeekOrigin.Begin);
  174. return ms.ToArray();
  175. }
  176. static async void Dispatch()
  177. {
  178. while (true)
  179. {
  180. var msg = await recvDataBuffer.Reader.ReadAsync();
  181. if (callbacks.ContainsKey(msg._protocallType))
  182. {
  183. callbacks[msg._protocallType](msg);
  184. }
  185. else
  186. {
  187. // 未找到消息处理逻辑
  188. Console.WriteLine("未识别的消息类型:" + msg._protocallType.ToString());
  189. }
  190. }
  191. }
  192. /// <summary>
  193. /// 向客户端写入消息
  194. /// </summary>
  195. static async void WriteToserver(Socket Sock)
  196. {
  197. while (true)
  198. {
  199. var msg = await sendDataBuffer.Reader.ReadAsync();
  200. var data = SocketDataToBytes(msg);
  201. await Sock.SendAsync(new ArraySegment<byte>(data), SocketFlags.None);
  202. }
  203. }
  204. /// <summary>
  205. /// 网络结构转数据
  206. /// </summary>
  207. /// <param name="tmpSocketData"></param>
  208. /// <returns></returns>
  209. static private byte[] SocketDataToBytes(sSocketData tmpSocketData)
  210. {
  211. byte[] _tmpBuff = new byte[tmpSocketData._buffLength];
  212. byte[] _tmpBuffLength = BitConverter.GetBytes(tmpSocketData._buffLength);
  213. byte[] _tmpDataLenght = BitConverter.GetBytes((UInt16)tmpSocketData._protocallType);
  214. Array.Copy(_tmpBuffLength, 0, _tmpBuff, 0, Constants.HEAD_DATA_LEN);//缓存总长度
  215. Array.Copy(_tmpDataLenght, 0, _tmpBuff, Constants.HEAD_DATA_LEN, Constants.HEAD_TYPE_LEN);//协议类型
  216. Array.Copy(tmpSocketData._data, 0, _tmpBuff, Constants.HEAD_LEN, tmpSocketData._dataLength);//协议数据
  217. return _tmpBuff;
  218. }
  219. /// <summary>
  220. /// 数据转网络结构
  221. /// </summary>
  222. /// <param name="_protocalType"></param>
  223. /// <param name="_data"></param>
  224. /// <returns></returns>
  225. static private sSocketData BytesToSocketData(eProtocalCommand _protocalType, byte[] _data)
  226. {
  227. sSocketData tmpSocketData = new sSocketData();
  228. tmpSocketData._buffLength = Constants.HEAD_LEN + _data.Length;
  229. tmpSocketData._dataLength = _data.Length;
  230. tmpSocketData._protocallType = _protocalType;
  231. tmpSocketData._data = _data;
  232. return tmpSocketData;
  233. }
  234. /// <summary>
  235. /// 接收buffer
  236. /// </summary>
  237. static private Channel<sSocketData> recvDataBuffer = Channel.CreateUnbounded<sSocketData>();
  238. /// <summary>
  239. /// 发送buffer
  240. /// </summary>
  241. static private Channel<sSocketData> sendDataBuffer = Channel.CreateUnbounded<sSocketData>();
  242. /// <summary>
  243. /// 接收客户端发来的信息,客户端套接字对象
  244. /// </summary>
  245. /// <param name="socketclientpara"></param>
  246. static async void recv(Socket socketServer)
  247. {
  248. socketServer.ReceiveTimeout = 800; // 接收等待超时时间设为800毫秒
  249. var _databuffer = new DataBuffer();
  250. byte[] arrServerRecMsg = new byte[4096]; // 创建一个内存缓冲区,其大小为4k字节
  251. while (true)
  252. {
  253. try
  254. {
  255. var length = await socketServer.ReceiveAsync(new ArraySegment<byte>(arrServerRecMsg), SocketFlags.None); // 将接收到的信息存入到内存缓冲区,并返回其字节数组的长度
  256. if (length <= 0) // 视为客户端已经close连接
  257. {
  258. break;
  259. }
  260. _databuffer.AddBuffer(arrServerRecMsg, length); //将收到的数据添加到缓存器中
  261. while (_databuffer.GetData(out sSocketData _socketData)) //取出一条完整数据
  262. {
  263. await recvDataBuffer.Writer.WriteAsync(_socketData); // 放入channel
  264. }
  265. Array.Clear(arrServerRecMsg, 0, length);
  266. }
  267. catch (SocketException e)
  268. {
  269. if (e.ErrorCode == 10060) // 超时的时候错误号码是10060
  270. {
  271. continue; // 继续等待
  272. }
  273. break;
  274. }
  275. catch (Exception)
  276. {
  277. break;
  278. }
  279. }
  280. socketServer.Close(); // 关闭之前accept出来的和客户端进行通信的套接字
  281. }
  282. }
  283. }