Program.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. using System.Text;
  7. using System.Threading;
  8. using System.Threading.Tasks;
  9. using System.Threading.Channels;
  10. using Newtonsoft.Json;
  11. using Newtonsoft.Json.Linq;
  12. using ProtoDataBuff;
  13. using ChatServer.server;
  14. using Chat;
  15. namespace ChatServer
  16. {
  17. class Program
  18. {
  19. const int port = 6000; // 端口号(用来监听的)
  20. static Socket SocketWatch = null; // 创建一个和客户端通信的套接字
  21. /// <summary>
  22. /// peer管理集合
  23. /// </summary>
  24. static public Dictionary<string, Peer> Peers = new Dictionary<string, Peer>();
  25. /// <summary>
  26. /// 消息分发
  27. /// </summary>
  28. private static Dictionary<eProtocalCommand, Action<string, sSocketData>> callbacks = new Dictionary<eProtocalCommand, Action<string, sSocketData>>();
  29. static void Main(string[] args)
  30. {
  31. IPAddress ip = IPAddress.Any;
  32. IPEndPoint ipe = new IPEndPoint(ip, port); //将IP地址和端口号绑定到网络节点point上
  33. // callbacks.Add(eProtocalCommand.CsChatLogin, On_Login); // 绑定处理逻辑
  34. callbacks.Add(eProtocalCommand.CsChatSendMsg, On_SendMessage); // 绑定处理逻辑
  35. //定义一个套接字用于监听客户端发来的消息,包含三个参数(IP4寻址协议,流式连接,Tcp协议)
  36. SocketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  37. SocketWatch.Bind(ipe); // 监听绑定的网络节点
  38. SocketWatch.Listen(20); // 将套接字的监听队列长度限制为20
  39. Console.WriteLine("开启监听......");
  40. Console.WriteLine("ctrl + c 退出程序......");
  41. Task.Run(MsgLoop);
  42. Task.Run(WatchConnecting).Wait();
  43. SocketWatch.Close();
  44. }
  45. internal static void AddPeer(Peer p)
  46. {
  47. lock (Peers)
  48. {
  49. Peers.Add(p.Key, p);
  50. }
  51. }
  52. internal static void RemovePeer(string key)
  53. {
  54. lock (Peers)
  55. {
  56. Peers.Remove(key);
  57. }
  58. }
  59. /// <summary>
  60. /// 发送消息
  61. /// </summary>
  62. /// <param name="peerId"></param>
  63. /// <param name="data"></param>
  64. static void On_SendMessage(string peerKey, sSocketData data)
  65. {
  66. if (Peers.TryGetValue(peerKey, out Peer p))
  67. {
  68. var msg = CS_ChatSendMsg.Parser.ParseFrom(data._data);
  69. if (null != msg)
  70. {
  71. var rdb = Redis.Ins.GetDatabase(0);
  72. var sd = new SC_ChatNewMsg() { FromChannel = msg.ToChannel, SenderName = p.Name, Msg = msg.Msg };
  73. switch (msg.ToChannel)
  74. {
  75. case ChatChannel.System: // 这个一般是客户端生成的, 除非是GM号,一般人发送这种消息拒绝转发.
  76. if (rdb.HashExists(MemKey_Cfg.GM_uids_hash, p.UID))
  77. {
  78. Peers.Values.ToList().ForEach(_p => _p.SendEvent(eProtocalCommand.ScChatNewMsg, sd));
  79. }
  80. else
  81. {
  82. Console.WriteLine($"非GM用户({p.UID})发送了系统消息转发请求!");
  83. }
  84. break;
  85. case ChatChannel.World:
  86. Peers.Values.ToList().ForEach(_p => _p.SendEvent(eProtocalCommand.ScChatNewMsg, sd));
  87. break;
  88. case ChatChannel.Guild:
  89. if (rdb.HashExists(MemKey_User.Guild(p.UID, p.zoneid), "guildId"))
  90. {
  91. var a = rdb.HashGet(MemKey_User.Guild(p.UID, p.zoneid), "guildId").ToString();
  92. var guildId = int.Parse(a);
  93. if (guildId > 0)
  94. {
  95. JArray jArray = JArray.Parse(rdb.HashGet(MemKey_Game.Guild(p.zoneid, guildId), "members").ToString());
  96. if (jArray.Count > 0)
  97. {
  98. var keys = from j in jArray select j.ToString() + ":" + p.zoneid;
  99. Peers.Where(kv => keys.Contains(kv.Key)).ToList().ForEach(kv => kv.Value.SendEvent(eProtocalCommand.ScChatNewMsg, sd));
  100. }
  101. }
  102. else
  103. {
  104. Console.WriteLine($"找不到用户({p.UID})的公会信息");
  105. }
  106. }
  107. else
  108. {
  109. Console.WriteLine($"找不到用户({p.UID})的公会信息");
  110. }
  111. break;
  112. default:
  113. Console.WriteLine("chat:未知的发送目标");
  114. break;
  115. }
  116. }
  117. }
  118. }
  119. /// <summary>
  120. /// 监听客户端发来的请求
  121. /// </summary>
  122. async static Task WatchConnecting()
  123. {
  124. while (true) // 持续不断监听客户端发来的请求
  125. {
  126. Socket connection;
  127. try
  128. {
  129. connection = await SocketWatch.AcceptAsync();
  130. }
  131. catch (Exception ex)
  132. {
  133. Console.WriteLine(ex.Message); // 提示套接字监听异常
  134. break;
  135. }
  136. var p = new Peer(connection);
  137. }
  138. }
  139. /// <summary>
  140. /// 客户端消息队列
  141. /// </summary>
  142. public static Channel<KeyValuePair<string, sSocketData>> MsgChannel = Channel.CreateBounded<KeyValuePair<string, sSocketData>>(1000);
  143. static async void MsgLoop()
  144. {
  145. while (true)
  146. {
  147. var msg = await MsgChannel.Reader.ReadAsync();
  148. if (callbacks.ContainsKey(msg.Value._protocallType))
  149. {
  150. callbacks[msg.Value._protocallType](msg.Key, msg.Value);
  151. }
  152. else
  153. {
  154. // 未找到消息处理逻辑
  155. }
  156. }
  157. }
  158. }
  159. }