using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Threading.Channels; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using ProtoDataBuff; using ChatServer.server; using Chat; namespace ChatServer { class Program { const int port = 6000; // 端口号(用来监听的) static Socket SocketWatch = null; // 创建一个和客户端通信的套接字 /// /// peer管理集合 /// static public Dictionary Peers = new Dictionary(); /// /// 消息分发 /// private static Dictionary> callbacks = new Dictionary>(); static void Main(string[] args) { IPAddress ip = IPAddress.Any; IPEndPoint ipe = new IPEndPoint(ip, port); //将IP地址和端口号绑定到网络节点point上 // callbacks.Add(eProtocalCommand.CsChatLogin, On_Login); // 绑定处理逻辑 callbacks.Add(eProtocalCommand.CsChatSendMsg, On_SendMessage); // 绑定处理逻辑 //定义一个套接字用于监听客户端发来的消息,包含三个参数(IP4寻址协议,流式连接,Tcp协议) SocketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); SocketWatch.Bind(ipe); // 监听绑定的网络节点 SocketWatch.Listen(20); // 将套接字的监听队列长度限制为20 Console.WriteLine("开启监听......"); Console.WriteLine("ctrl + c 退出程序......"); Task.Run(MsgLoop); Task.Run(WatchConnecting).Wait(); Console.ReadLine(); SocketWatch.Close(); } internal static void AddPeer(Peer p) { lock (Peers) { Peers.Add(p.Key, p); } } internal static void RemovePeer(string key) { lock (Peers) { Peers.Remove(key); } } /// /// 发送消息 /// /// /// static void On_SendMessage(string peerKey, sSocketData data) { if (Peers.TryGetValue(peerKey, out Peer p)) { var msg = CS_ChatSendMsg.Parser.ParseFrom(data._data); if (null != msg && msg.Msg.Trim().Length>0) { var rdb = Redis.Ins.GetDatabase(0); var sd = new SC_ChatNewMsg() { FromChannel = msg.ToChannel, SenderName = p.Name, Msg = msg.Msg, SenderUid = p.UID }; switch (msg.ToChannel) { case ChatChannel.System: // 这个一般是客户端生成的, 除非是GM号,一般人发送这种消息拒绝转发. if (rdb.HashExists(MemKey_Cfg.GM_uids_hash, p.UID)) { Peers.Values.ToList().ForEach(_p => _p.SendEvent(eProtocalCommand.ScChatNewMsg, sd)); } else { Console.WriteLine($"非GM用户({p.UID})发送了系统消息转发请求!"); } break; case ChatChannel.World: Peers.Values.ToList().ForEach(_p => _p.SendEvent(eProtocalCommand.ScChatNewMsg, sd)); break; case ChatChannel.Guild: if (rdb.HashExists(MemKey_User.Guild(p.UID, p.zoneid), "guildId")) { var a = rdb.HashGet(MemKey_User.Guild(p.UID, p.zoneid), "guildId").ToString(); var guildId = int.Parse(a); if (guildId > 0) { JArray jArray = JArray.Parse(rdb.HashGet(MemKey_Game.Guild(p.zoneid, guildId), "members").ToString()); if (jArray.Count > 0) { var keys = from j in jArray select j.ToString() + ":" + p.zoneid; Peers.Where(kv => keys.Contains(kv.Key)).ToList().ForEach(kv => kv.Value.SendEvent(eProtocalCommand.ScChatNewMsg, sd)); } } else { Console.WriteLine($"找不到用户({p.UID})的公会信息"); } } else { Console.WriteLine($"找不到用户({p.UID})的公会信息"); } break; case ChatChannel.Single: Peers.Values.Where(peer =>peer.Name == msg.ToNickName).ToList().ForEach(_p => _p.SendEvent(eProtocalCommand.ScChatNewMsg, sd)); break; default: Console.WriteLine("chat:未知的发送目标"); break; } } } } /// /// 监听客户端发来的请求 /// async static Task WatchConnecting() { while (true) // 持续不断监听客户端发来的请求 { Socket connection; try { connection = await SocketWatch.AcceptAsync(); } catch (Exception ex) { Console.WriteLine(ex.Message); // 提示套接字监听异常 break; } var p = new Peer(connection); } } /// /// 客户端消息队列 /// public static Channel> MsgChannel = Channel.CreateBounded>(1000); static async void MsgLoop() { while (true) { var msg = await MsgChannel.Reader.ReadAsync(); if (callbacks.ContainsKey(msg.Value._protocallType)) { callbacks[msg.Value._protocallType](msg.Key, msg.Value); } else { // 未找到消息处理逻辑 } } } } }