美文网首页
一个简单 小型的C#Socket网络通信库 聊天室示例(二)

一个简单 小型的C#Socket网络通信库 聊天室示例(二)

作者: 懒_开果 | 来源:发表于2019-08-27 11:14 被阅读0次

接下来 先讲讲服务端的吧

代码部分解析

这里两个类都要引用 KGSocket dll的

1.ChatNetData 建立一个 客户端 服务端共用的数据 类库 因为要互相传的所以肯定要统一

目标框架要选择这个Unity 3.5 .net Subset Base Class Libraries 1.png

导出的dll Unity 才能用

新建的类库选这个 2.png

里面就是一些数据结构了
网络消息自定义类 要继承KGNetData 打上Serializable 序列化标签
枚举那些因为没办法序列化所以用Int的代替然后接收到再强转回来

using KGSocket;
using System;

namespace ChatNetData
{
    [Serializable]
    public class ChatDatas:KGNetData
    {
        public byte[] HeadData;

        public string PlayerName;

        public SendChat Chatdata;
    }
}
namespace ChatNetData
{

    public enum CMD
    {
        None,
        ReqLogin,
        ReqChatInfo,

        RspLogin,
        RspChatInfo,

    }
}
namespace ChatNetData
{
    public enum ErrorInfo
    {
        None,
        NameRepeatsErr,//名字重复登录错误指令
    }
}
using System;

namespace ChatNetData
{
    [Serializable]
    public  class SendChat
    {
        public string chat;
        public int Islocal;
    }
}

2.ChatDatasPack 用于分辨数据是哪个客户端发定的数据类型**

using ChatNetData;

namespace ChatServer
{
    public class ChatDatasPack
    {
        public ChatSession chatSession;

        public ChatDatas chatDatas;

    }
}
using ChatNetData;

namespace ChatServer
{
    public class ChatDatasPack
    {
        public ChatSession chatSession;

        public ChatDatas chatDatas;

    }
}

3.ChatSessio 每个客户端的通信都是他来操作**

要继承KGNetSession<ChatDatas> ChatDatas就是自己定义继承KGNetData的数据类

这里主要的就是 OnDisRecive 断开回调 ,OnReciveData接收到数据回调 OnStartRecive 连接成功回调

OnReciveData(ChatDatas data) 接收到数据会 new一个ChatDatasPack 赋值 添加到ChatServe的任务队列 排序处理

using KGSocket;
using ChatNetData;

namespace ChatServer
{
    public class ChatSession : KGNetSession<ChatDatas>
    {

        public int SessionID = 0;
public string PlayerName;//缓存用户的名字public byte[] HeadData;//缓存用户的头像图片数据

        protected override void OnDisRecive()
        {
            ("名字:" + PlayerName + "已下线").KLog();

        }
        protected override void OnReciveData(ChatDatas data)
        {
            ("收到名字:" + data.PlayerName + "的请求"+(CMD)data.Cmd).KLog();
            ChatServe.Instance.AddDataPackQue(this,data);
        }

        protected override void OnStartRecive()
        {
            SessionID = ChatServe.Instance.GetSessionID();
            ("ID:" + SessionID + "已连接").KLog();

        }
    }
}

4.ChatServe 这个就是创建服务器socket的了 缓存客户端 处理接收各个客户端信息返回的业务逻辑

要继承KGSocketServe<ChatSession, ChatDatas>

这里AddDataPackQue 就是添加接收到的消息任务队列的,会用到一个线程锁,
lock 这里简单说一下 作用是被lock的对象,里面的语句块 一次只被一个线程使用 如果在使用中的 其他线程就会排队等待执行完再轮到下一个 不会出现一窝蜂调用 顺序错乱情况
添加完后 在Update() 这里进行出列调用 主线程那边就可以直接一直调用Update一直刷新有没有新的任务队列就好
然后DisposePack这里就是处理从客户端接收到的数据了 判断指令调用对应业务逻辑

using System.Linq;

using KGSocket;
using ChatNetData;

namespace ChatServer
{
    public class ChatServe : KGSocketServe<ChatSession, ChatDatas>
    {
        private static ChatServe instance;
        public static ChatServe Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new ChatServe();
                }
                return instance;
            }
            set => instance = value;
        }

        public static readonly object obj = "lock";

        public Queue<ChatDatasPack> DataPackQue = new Queue<ChatDatasPack>();

        #region 缓存
        private int SessionID = 0;

        public int GetSessionID()
        {
            if (SessionID == int.MaxValue)
            {
                SessionID = 0;
            }
            return SessionID += 1;
        }

        public bool IsUserOnLine(string name)
        {
            return SessionList.Select(v=>v.PlayerName).ToList().Contains(name) ;
        }

        #endregion

        public void Update()
        {
            if (DataPackQue.Count>0)
            {
                lock (obj)
                {
                    DisposePack(DataPackQue.Dequeue());
                }
            }
        }

        public void DisposePack(ChatDatasPack pack)
        {
            switch ((CMD)pack.chatDatas.Cmd)
            {
                case CMD.ReqLogin:
                    //判断在线的名字是否重复
                    if (IsUserOnLine(pack.chatDatas.PlayerName))
                    {
                        pack.chatDatas.Err = (int)ErrorInfo.NameRepeatsErr;
                    }
                    else
                    {
                        pack.chatSession.PlayerName = pack.chatDatas.PlayerName;
                        pack.chatSession.HeadData = pack.chatDatas.HeadData;
                        pack.chatDatas.Cmd = (int)CMD.RspLogin;

                    }

                    pack.chatSession.SendData(pack.chatDatas);

                    break;
                case CMD.ReqChatInfo:
                    pack.chatDatas.Cmd = (int)CMD.RspChatInfo;
                    pack.chatDatas.HeadData = pack.chatSession.HeadData;
                    pack.chatDatas.PlayerName = pack.chatSession.PlayerName;
                    //发回给自身聊天
                    pack.chatSession.SendData(pack.chatDatas);
                    //改成对方
                    pack.chatDatas.Chatdata.Islocal = 1;
                    //分发到各个客户端 聊天消息
                    SessionList.Where(v=>v!=pack.chatSession).ToList().ForEach(v=> 
                    {
                        v.SendData(pack.chatDatas);
                    });
                    break;
            }
        }
        public void AddDataPackQue(ChatSession session, ChatDatas chatData)
        {
            lock (obj)
            {
                DataPackQue.Enqueue(new ChatDatasPack { chatSession = session, chatDatas = chatData });
            }
        }

    }
}

https://github.com/LKaiGuo/KGScriptGenerator 喜欢的给我点个星星啊
u3d萌新QQ群844087555 欢迎进来灌水=。=

相关文章

网友评论

      本文标题:一个简单 小型的C#Socket网络通信库 聊天室示例(二)

      本文链接:https://www.haomeiwen.com/subject/mmwsectx.html