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

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

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

    这里就讲下GameRoot这个类了,业务逻辑,UI管理,收发消息 都在这里了=。=

    先上代码吧:

    using System.Collections;
    using System.Collections.Generic;
    using System.Windows.Forms;
    using UnityEngine;
    using KGSocket;
    using ChatNetData;
    using UnityEngine.UI;
    using System.IO;
    using System;
    
    
    public class GameRoot : MonoBehaviour
    {
    
        public KGSocketClient<ChatNetSession, ChatDatas> socketClient = new KGSocketClient<ChatNetSession, ChatDatas>();
        public Queue<ChatDatas> ChatQue = new Queue<ChatDatas>();
        private static readonly string obj = "lock";
    
    
    
        public LoginPanel loginPanel;
        public ChatPanel chatPanel;
    
        public Text ErrorTxt;
    
    
    
        public byte[] HeadData;
    
    
    
    
        private void Awake()
        {
            loginPanel.gameObject.SetActive(true);
            chatPanel.gameObject.SetActive(false);
        }
        void Start()
        {
            socketClient.StartCreate("127.0.0.1", 8895);
            InItClickEvent();
        }
    
        // Update is called once per frame
        void Update()
        {
            if (ChatQue.Count > 0)
            {
                lock (obj)
                {
                    //出列 处理
                    ProcessNetData(ChatQue.Dequeue());
                }
            }
        }
    
    
        /// <summary>
        /// 接收事件存入队列
        /// </summary>
        /// <param name="info"></param>
        public void AddNetData(ChatDatas info)
        {
            lock (obj)
            {
                ChatQue.Enqueue(info);
            }
        }
    
        /// <summary>
        /// 处理接收的数据
        /// </summary>
        /// <param name="info"></param>
        public void ProcessNetData(ChatDatas info)
        {
            //先判断是否有错误
            if ((ErrorInfo)(info.Err) != ErrorInfo.None)
            {
    
                switch ((ErrorInfo)(info.Err))
                {
                    case ErrorInfo.NameRepeatsErr:
                        StartDelayTxt("用户名重复请更换");
                        loginPanel.LoginBtn.interactable = true;
                        break;
    
                }
                return;
            }
    
            //然后判断收到的指令 做处理
            switch ((CMD)(info.Cmd))
            {
                case CMD.None:
                    break;
                case CMD.RspLogin:
                    loginPanel.gameObject.SetActive(false);
                    chatPanel.gameObject.SetActive(true);
                    chatPanel.HeadImg.LoadImage(info.HeadData);
                    chatPanel.PlayerNameTxt.text = info.PlayerName;
                    // StartCoroutine(DownloadImage(dialog.FileName, v => loginPanel.PlayerHead.texture = v));
                    break;
                case CMD.RspChatInfo:
                    Debug.Log(info.PlayerName);
                    chatPanel.SpawnDialogUI(info.PlayerName, info.Chatdata.chat, info.HeadData.ByteToTexture(), info.Chatdata.Islocal);
                    
                    break;
    
            }
        }
    
        /// <summary>
        /// 按钮绑定事件
        /// </summary>
        public void InItClickEvent()
        {
    
            //接收事件
            socketClient.Client.OnReciveDataEvent += AddNetData;
            //登录按钮
            loginPanel.LoginBtn.onClick.AddListener(() =>
            {
                if (loginPanel.PlayerHead.texture.name== "unselected"|| loginPanel.NameInput.text=="")
                {
                    StartDelayTxt("未选择头像或者名字为空 不能登录");
                }
                else
                {
    
                    loginPanel.LoginBtn.interactable = false;
                    socketClient.Client.SendData(new ChatDatas
                    {
                        Cmd = (int)(CMD.ReqLogin),
                        PlayerName = loginPanel.NameInput.text,
                        HeadData = this.HeadData
    
                    });
    
    
    
    
                }
            });
    
            loginPanel.SelectHeadBtn.onClick.AddListener(() =>
            {
                OpenFile();
            });
    
            //      发送消息按钮
            chatPanel.SendChatBtn.onClick.AddListener(() =>
            {
                if (chatPanel.chatInput.text == "")
                {
                    StartDelayTxt("发送的内容不能为空");
                }
                else
                {
                    ChatDatas chat = new ChatDatas
                    {
                        Cmd = (int)(CMD.ReqChatInfo),
    
                        Chatdata = new SendChat() { chat = chatPanel.chatInput.text },
                    };
    
                    socketClient.Client.SendData(chat);
                    chatPanel.chatInput.text = "";
                }
            });
    
    
            socketClient.SetLog((v, l) =>
            {
                Debug.Log(v + "Level:" + l);
            });
    
        }
    
    
        private void OnDestroy()
        {
            socketClient.Client.mSocket.Close();
        }
        #region 工具
    
    
        /// <summary>
        /// 这个是打开选择文件的
        /// </summary>
        public void OpenFile()
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = "PNG图片|*.png|JPG图片|*.jpg";  //过滤文件类型
            
            dialog.InitialDirectory = UnityEngine.Application.dataPath;  //定义打开的默认文件夹位置,可以在显示对话框之前设置好各种属性
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                HeadData = dialog.FileName.GetPictureBytes();
                StartCoroutine(DownloadImage(dialog.FileName, v => loginPanel.PlayerHead.texture = v));
    
            }
           
        }
    
        //加载路径图片
        IEnumerator DownloadImage(string url, Action<Texture2D> action)
        {
            WWW www = new WWW(url);
            yield return www;
            action(www.texture);
    
    
        }
    
    
        /// <summary>
        /// 提示错误信息文字
        /// </summary>
        public void StartDelayTxt(string info)
        {
            ErrorTxt.text = info;
            StopAllCoroutines();
            StartCoroutine(DelayTxt());
        }
    
        IEnumerator DelayTxt()
        {
            ErrorTxt.gameObject.SetActive(true);
            yield return new WaitForSeconds(2);
            ErrorTxt.gameObject.SetActive(false);
        }
        #endregion
    
    }
    

    这里还要添加从服务端那边生成出来的两个dll KGSocket 这个就是之前通信库的 和ChatNetData 这个是两端共用的 数据类库

    一开始 会连接服务器 socketClient.StartCreate("127.0.0.1", 8895); 当然这里得定义好类KGSocketClient<ChatNetSession, ChatDatas> socketClient ,接着 全部按钮事件和别的事件初始化绑定都在InItClickEvent这里了,
    接收服务器消息的事件,处理消息数据
    KGSocketClient里面我写了两个 一个是回调函数** OnReciveData(T data) 在自己类调的,还有一个是回调事件Action<T> OnReciveDataEvent 给外部用的,这边图省事直接用事件OnReciveDataEvent** 了 socketClient.Client.OnReciveDataEvent += AddNetData; 所以接收消息处理在AddNetData 上 然后AddNetData 接收到会天添加到ChatQue 队列里面 在Updata里每帧判断是否有任务存在里面 如果有就就行出列 在ProcessNetData 进行数据处理 在ProcessNetData 里面会根据接收到的数据先判断有没有错误指令Err再进行判断任务指令CMD进行对应的处理 这里可以看下代码就行了

    登录按钮事件

    这里会先判断 头像和名字有没有输入如果没有直接返回错误信息 不会发消息给服务器,如果都输入了直接发消息给服务器socketClient.Client.SendData(这里就是自己定义的两端都通用数据类型),CMD必须要填准确。服务器是根据CMD来进行对应的操作的

    选择头像图片按钮事件

    OpenFile()这里
    需要用到 System.Windows.Forms ——****Windows 的应用程序的类的OpenFileDialog 这里要using System.Windows.Forms 了 注意的是 u3d里面默认没引用这个dll的需要去u3d文件夹搜索System.Windows.Forms.dll这个文件 如图

    5.png
    ,然后把它拖进来u3d
    这里打包时候还要注意的是u3d默认环境不支持打包这个dll的所以还要设置 如图
    6.png

    然后就可以调用这个选择文件了 效果就是这样

    7.png
    这里说一下代码

    OpenFileDialog.Filter 就是定义选择文件的类型 我这里就写了两个图片的,你们喜欢可以自行增加** "显示在窗口的名称|.后缀名|JPG图片|.jpg" **格式就这样
    OpenFileDialog.InitialDirectory 就是定义初始打开文件的位置
    if (dialog.ShowDialog() == DialogResult.OK) 判断是否打开完成了 然后dialog.FileName 获取该文件的路径 字符 然后就可以进行转化byte[]数据了 用的拓展工具类的GetPictureBytes

    服务器打印事件

    在KGSocketClient里面所有打印事件都在KGSocketClient.SetLog 自行添加就好
    [mw_shl_code=csharp,false]socketClient.SetLog((v, l) =>
    {
    Debug.Log(v + "Level:" + l);
    });[/mw_shl_code]

    发送按钮事件

    和登录按钮差不多做法的

    提醒错误消息的

    StartDelayTxt(string info) 都在这了

    还有个ChatNetSession类

    这里直接继承抽象类KGNetSession<ChatDatas> 就好 没有添加什么 ,服务端那边倒是放了些缓存在里面= =懒得弄另外的缓存类了

    好了整个过程了

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

    相关文章

      网友评论

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

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