网络框架

客户端 


using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class mManagerSocket :Singleton<mManagerSocket>

{

    // 消息队列中的元素类型

    class MsgItem

    {

        //消息类型

        public int msgid;

        public byte[] msg;

    }

    // 代参数的委托类

    public delegate void OnMessage_CenterFunce( byte[] msg);

    // 每一个客户端给服务器的消息ID对应一个委托类,放入字典管理起来

    public Dictionary<int, OnMessage_CenterFunce> dic = new Dictionary<int, OnMessage_CenterFunce>();

    // 消息队列,用于存储从服务器接受来的包,便于主线程获取处理

    private Queue<MsgItem> all_Msgitem = new Queue<MsgItem>();

    // 注册消息处理回调

    public void OnResour_Funces(int msgid, OnMessage_CenterFunce resFunces)

    {

        //定义一个准备接受从那个字典类去除来的属性

        OnMessage_CenterFunce funce = null;

        //判断根据消息类型拿出对应的委托类

        if (dic.TryGetValue(msgid, out funce))

        {

            //注册消息回调函数

            funce += resFunces;

        }

        else

        {

            //如果没有加入到字典管理起来

            dic.Add(msgid, resFunces);

        }

    }

    /// <summary>

    /// 对队里中的数据进行发布

    /// </summary>

    /// <param name="msgid"></param>

    /// <param name="clientid"></param>

    /// <param name="msg"></param>

    public void OnMessagehandling(int msgid,byte[] msg)

    {

        //根据从队列去处的消息类型拿到集合内对应的事件类

        OnMessage_CenterFunce funce = null;

        //判断根据消息类型拿出对应的委托类

        if (dic.TryGetValue(msgid, out funce))

        {

            //事件发布

            funce(msg);

        }

    }

    // 把收到的消息压入队列

    public void All_Enqueue(int msgid, byte[] msg)

    {

        //建立一个元素对象

        MsgItem item = new MsgItem();

        //同上(消息类型)

        item.msgid = msgid;

        //把传入进来的具体消息复制到队列类中

        item.msg = msg;

        //防止多个客户端连接进来

        lock (all_Msgitem)

        {

            //把消息压入队列

            all_Msgitem.Enqueue(item);

        }

    }

    // 处理该客户端消息队列中的消息

    public void Dele_Dequeue()

    {

        //一次性处理完所有的积累消息

        while (true)

        {

            //如果消息处里完毕了,退出

            if (all_Msgitem.Count <= 0)

            {

                return;

            }

            //处理消息出队

            MsgItem item = all_Msgitem.Dequeue();

            //调用--- 事件发布

            OnMessagehandling(item.msgid,item.msg);

        }

    }

}





using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using System.Net;

using System.Net.Sockets;

using System;

using System.IO;

public class NetClicent : Singleton<NetClicent>

{

    // 异步通讯所用的附带数据类型

    class AscyData

    {

        // 消息ID

        public int mesid;

        // 当前写入位置

        public int pos;

        // 缓冲区

        public byte[] buff;

    }

    // 消息ID长度

    public const int MSG_ID_SIZE = sizeof(int);

    // 包头长度

    public const int HONE_SIZE = sizeof(ushort);

    public Socket mServerSocket;

    public void StartServer(string mIP, int mPort)

    {

        mServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        IPEndPoint IPE = new IPEndPoint(IPAddress.Parse(mIP), mPort);

        try

        {

            mServerSocket.Connect(IPE);

        }

        catch (System.Exception)

        {

          Debug.Log("连接失败");

            throw;

        }

        Debug.Log("连接服务端成功。。。");

        Start_Subpackage();

    }

    //异步读取包处

    private void Start_Subpackage()

    {

        //异步读取所有用到的属性,读取从包头加消息类型开始

        AscyData data = new AscyData()

        {

            buff = new byte[HONE_SIZE + MSG_ID_SIZE],

        };

        mServerSocket.BeginReceive(data.buff, 0, data.buff.Length, SocketFlags.None, BeginHone, data);

    }

    private void BeginHone(IAsyncResult ar)

    {

        //拿到发送过来的长度

        int len = mServerSocket.EndReceive(ar);

        //从系统中取出之前传入的参数

        AscyData data = ar.AsyncState as AscyData;

        //判断包的长度和MSGID是否都接受成功

        if (len + data.pos == data.buff.Length)

        {

            //从接受完的字节数组中取出总长度 0代表从0开始全部转换完毕

            ushort paselen = BitConverter.ToUInt16(data.buff, 0);

            //从接受完的字节数组中取出消息的ID类型 2代表从0开始只转换两个字节

            int mesid = BitConverter.ToInt32(data.buff, HONE_SIZE);

            //开启一个异步读取包体的对象存储的位置

            AscyData da = new AscyData()

            {

                buff = new byte[paselen - MSG_ID_SIZE],

                mesid = mesid,

            };

            mServerSocket.BeginReceive(da.buff, 0, da.buff.Length, SocketFlags.None, BeginBody, da);

        }

        else

        {

            //没有读取完则继续读取包头的剩余部分

            data.pos += len;

            //异步开始读取包体

            mServerSocket.BeginReceive(data.buff, data.pos, data.buff.Length - data.pos, SocketFlags.None, BeginHone, data);

        }

    }

    private void BeginBody(IAsyncResult ar)

    {

        //同上 --他们所拿到的数据和长度都是真实的数据

        int len = mServerSocket.EndReceive(ar);

        //获取之前开启存储数据的类的对象

        AscyData data = ar.AsyncState as AscyData;

        //判断是否读取完毕,读取完毕就放入队列

        if (len + data.pos == data.buff.Length)

        {

          mManagerSocket.Instance .All_Enqueue(data.mesid,data.buff);


            //开启读取下一个包

            Start_Subpackage();//再次进行回调

        }

        else

        {

            //把么有读取完的数据增加到有效数据的末尾

            data.pos += len;

            mServerSocket.BeginReceive(data.buff, data.pos, data.buff.Length - data.pos, SocketFlags.None, BeginHone, data);

        }

    }

    //服务返回给客户端发送消息

    public void Send(int msgid, byte[] msg)

    {

        //这个要倒IO包 他相当于一个记忆  短暂记忆的一个流  全部拿到发出去

        using (MemoryStream mm = new MemoryStream())

        {

            //拿到你要发送的总长度

            ushort length = (ushort)(msg.Length + MSG_ID_SIZE);

            //通过IO流的方式连接到MemoryStream

            BinaryWriter bw = new BinaryWriter(mm);

            //包头放置数据长度,2个字节

            bw.Write(length);

            //消息类型

            bw.Write(msgid);

            //具体数据

            bw.Write(msg);

            //两种写法  这种是全部发送 也没问题

            // mServerSocket.Send(mm.GetBuffer());

            //返回给客户端消息处,参数一全部的数据包,参数二发送的长度(要加上包头的长度)

            mServerSocket.Send(mm.GetBuffer(), length + HONE_SIZE, SocketFlags.None);

        }

    }

}





using System;

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

using Google.Protobuf;

using MyUser;

//意思是 S——服务端  2——TO C --客户端

public enum S2C

{

    TankLoginResult = 0,

    Generate_playerlist = 1,

    Anaphase_Player = 2,

    WantMove = 3,

}

/// <summary>

/// 所有客户端给服务器的消息id类型

/// </summary>

//客户端发送给服务端

public enum C2S

{

    TankLoginResult = 0,

    Generate_playerlist = 1,

    Anaphase_Player = 2,

    WantMove = 3,

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,717评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,501评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,311评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,417评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,500评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,538评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,557评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,310评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,759评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,065评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,233评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,909评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,548评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,172评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,420评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,103评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,098评论 2 352

推荐阅读更多精彩内容