Program.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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. Console.ReadLine();
  44. SocketWatch.Close();
  45. }
  46. internal static void AddPeer(Peer p)
  47. {
  48. lock (Peers)
  49. {
  50. Peers.Add(p.Key, p);
  51. }
  52. }
  53. internal static void RemovePeer(string key)
  54. {
  55. lock (Peers)
  56. {
  57. Peers.Remove(key);
  58. }
  59. }
  60. /// <summary>
  61. /// 发送消息
  62. /// </summary>
  63. /// <param name="peerId"></param>
  64. /// <param name="data"></param>
  65. static void On_SendMessage(string peerKey, sSocketData data)
  66. {
  67. if (Peers.TryGetValue(peerKey, out Peer p))
  68. {
  69. var msg = CS_ChatSendMsg.Parser.ParseFrom(data._data);
  70. if (null != msg && msg.Msg.Trim().Length>0)
  71. {
  72. var rdb = Redis.Ins.GetDatabase(0);
  73. var sd = new SC_ChatNewMsg() { FromChannel = msg.ToChannel, SenderName = p.Name, Msg = msg.Msg, SenderUid = p.UID };
  74. switch (msg.ToChannel)
  75. {
  76. case ChatChannel.System: // 这个一般是客户端生成的, 除非是GM号,一般人发送这种消息拒绝转发.
  77. if (rdb.HashExists(MemKey_Cfg.GM_uids_hash, p.UID))
  78. {
  79. Peers.Values.ToList().ForEach(_p => _p.SendEvent(eProtocalCommand.ScChatNewMsg, sd));
  80. }
  81. else
  82. {
  83. Console.WriteLine($"非GM用户({p.UID})发送了系统消息转发请求!");
  84. }
  85. break;
  86. case ChatChannel.World:
  87. Peers.Values.ToList().ForEach(_p => _p.SendEvent(eProtocalCommand.ScChatNewMsg, sd));
  88. break;
  89. case ChatChannel.Guild:
  90. if (rdb.HashExists(MemKey_User.Guild(p.UID, p.zoneid), "guildId"))
  91. {
  92. var a = rdb.HashGet(MemKey_User.Guild(p.UID, p.zoneid), "guildId").ToString();
  93. var guildId = int.Parse(a);
  94. if (guildId > 0)
  95. {
  96. JArray jArray = JArray.Parse(rdb.HashGet(MemKey_Game.Guild(p.zoneid, guildId), "members").ToString());
  97. if (jArray.Count > 0)
  98. {
  99. var keys = from j in jArray select j.ToString() + ":" + p.zoneid;
  100. Peers.Where(kv => keys.Contains(kv.Key)).ToList().ForEach(kv => kv.Value.SendEvent(eProtocalCommand.ScChatNewMsg, sd));
  101. }
  102. }
  103. else
  104. {
  105. Console.WriteLine($"找不到用户({p.UID})的公会信息");
  106. }
  107. }
  108. else
  109. {
  110. Console.WriteLine($"找不到用户({p.UID})的公会信息");
  111. }
  112. break;
  113. case ChatChannel.Single:
  114. Peers.Values.Where(peer =>peer.Name == msg.ToNickName).ToList().ForEach(_p => _p.SendEvent(eProtocalCommand.ScChatNewMsg, sd));
  115. break;
  116. default:
  117. Console.WriteLine("chat:未知的发送目标");
  118. break;
  119. }
  120. }
  121. }
  122. }
  123. /// <summary>
  124. /// 监听客户端发来的请求
  125. /// </summary>
  126. async static Task WatchConnecting()
  127. {
  128. while (true) // 持续不断监听客户端发来的请求
  129. {
  130. Socket connection;
  131. try
  132. {
  133. connection = await SocketWatch.AcceptAsync();
  134. }
  135. catch (Exception ex)
  136. {
  137. Console.WriteLine(ex.Message); // 提示套接字监听异常
  138. break;
  139. }
  140. var p = new Peer(connection);
  141. }
  142. }
  143. /// <summary>
  144. /// 客户端消息队列
  145. /// </summary>
  146. public static Channel<KeyValuePair<string, sSocketData>> MsgChannel = Channel.CreateBounded<KeyValuePair<string, sSocketData>>(1000);
  147. static async void MsgLoop()
  148. {
  149. while (true)
  150. {
  151. var msg = await MsgChannel.Reader.ReadAsync();
  152. if (callbacks.ContainsKey(msg.Value._protocallType))
  153. {
  154. callbacks[msg.Value._protocallType](msg.Key, msg.Value);
  155. }
  156. else
  157. {
  158. // 未找到消息处理逻辑
  159. }
  160. }
  161. }
  162. }
  163. }