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

这里就讲下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 socketClient = new KGSocketClient();
    public Queue ChatQue = new Queue();
    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());
            }
        }
    }


    /// 
    /// 接收事件存入队列
    /// 
    /// 
    public void AddNetData(ChatDatas info)
    {
        lock (obj)
        {
            ChatQue.Enqueue(info);
        }
    }

    /// 
    /// 处理接收的数据
    /// 
    /// 
    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;

        }
    }

    /// 
    /// 按钮绑定事件
    /// 
    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 工具


    /// 
    /// 这个是打开选择文件的
    /// 
    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 action)
    {
        WWW www = new WWW(url);
        yield return www;
        action(www.texture);


    }


    /// 
    /// 提示错误信息文字
    /// 
    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 socketClient ,接着 全部按钮事件和别的事件初始化绑定都在InItClickEvent这里了,
接收服务器消息的事件,处理消息数据
KGSocketClient里面我写了两个 一个是回调函数** OnReciveData(T data) 在自己类调的,还有一个是回调事件Action 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 就好 没有添加什么 ,服务端那边倒是放了些缓存在里面= =懒得弄另外的缓存类了

好了整个过程了

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

你可能感兴趣的:(一个简单 小型的C#Socket网络通信库 聊天室示例(六))