Unity SuperSocket之NetMgr

Unity SuperSocket之NetMgr

using Message;
using SuperSocket.ClientEngine;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using UnityEngine;

/// <summary>
/// 网络管理
/// </summary>
public class NetMgr : MonoBehaviour
{
    public static NetMgr Instance;

    private AsyncTcpSession socket = null;

    private int protoId;
    private List<byte> receiveCache = new List<byte>();
    private bool isSending = false;
    private Queue<byte[]> sendCache = new Queue<byte[]>();

    public delegate void Delegate(bool result);
    public Delegate connectCallBack;
    //123.56.223.55  127.0.0.1
    private string ip = "123.56.223.55";
    //private string ip = "127.0.0.1";
    private int port = 6650;

    //心跳时间
    private float lastTickTime = 0;
    private float heartBeatTime = 3;
    private long lastTime = 0;

    public enum Status
    {
        None,
        Connected,
    };
    public Status status = Status.None;

    private void Awake()
    {
        Instance = this;

        MsgMgr.Instance.AddListener(typeof(SToCHeatBeat), OnHeratBeat);
    }

    public void Connect()
    {
        socket = new AsyncTcpSession();
        socket.Connected += Connected;
        socket.DataReceived += DataReceived;
        socket.Error += Error;
        socket.Closed += Closed;
        socket.Connect(new IPEndPoint(IPAddress.Parse(ip), port));
    }
    private void Connected(object sender, EventArgs e)
    {
        Debug.Log("连接成功");
        status = Status.Connected;
        connectCallBack(true);
    }

    private void DataReceived(object sender, DataEventArgs e)
    { 
        Debug.Log("收到消息");
        try
        {
            byte[] buffer = new byte[e.Length];
            Array.Copy(e.Data, buffer, e.Length);
            receiveCache.AddRange(buffer);
            byte[] data = NetCode.Decode(ref protoId, ref receiveCache);
            if (data != null)
            {
                Type protoType = ProtoDic.GetProtoTypeByProtoId(protoId);
                object tos = ProtoBuf.Serializer.Deserialize(protoType, new MemoryStream(data));
                MsgMgr.Instance.eventDict.Enqueue(new KeyValuePair<Type, object>(protoType, tos));
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

    private void Error(object sender, SuperSocket.ClientEngine.ErrorEventArgs e)
    {
        Debug.Log("连接出错:" + e.ToString());
        connectCallBack(false);
        if (status == Status.Connected)
        {
            status = Status.None;
            Close();
        }
    }

    private void Closed(object sender, EventArgs e)
    {
        Debug.Log("连接关闭:" + e.ToString());
    }

    private void FixedUpdate()
    {
        //心跳
        if (status == Status.Connected)
        {
            if (Time.time - lastTickTime > heartBeatTime)
            {
                CToSHeatBeat hb = new CToSHeatBeat();
                TimeSpan ts = new TimeSpan(DateTime.Now.Ticks);
                hb.time = (long)ts.TotalMilliseconds;
                lastTime = hb.time;
                Send(hb);
                lastTickTime = Time.time;
                Debug.LogWarning("发送心跳 " + hb.time);
            }
        }
        //断线重连
         
    }

    void OnHeratBeat(object protocol)
    {
        SToCHeatBeat sthb = protocol as SToCHeatBeat;
        Debug.LogWarning("收到心跳 " + sthb.time+ " lastTime "+ lastTime);
        Debug.LogWarning("延迟:" + (lastTime-sthb.time)/1000);
    }

    /// <summary>
    /// 关闭连接
    /// </summary>
    /// <returns></returns>
    public void Close()
    {
        if (socket != null)
        {
            if (socket.IsConnected)
            {
                socket.Close();
            }
            socket = null;
        }
    }

    /// <summary>
    /// 发送
    /// </summary>
    /// <param name="obj"></param>
    public void Send(object obj)
    {
        if (status != Status.Connected)
        {
            Debug.LogError("还没链接");
            return;
        }

        if (!ProtoDic.ContainProtoType(obj.GetType()))
        {
            Debug.LogError("未知协议号" + obj.GetType().ToString());
            return;
        }

        byte[] data = NetCode.Encode(obj);
        sendCache.Enqueue(data);
        Send();
    }

    void Send()
    {
        try
        {
            if (sendCache.Count == 0)
            {
                isSending = false;
                return;
            }

            isSending = true;
            byte[] data = sendCache.Dequeue();
            socket.Send(new ArraySegment<byte>(data));
            Debug.Log("发送");
            isSending = false;
            Send();
        }
        catch (Exception e)
        {
            Debug.Log(e.Message);
        }
    }

    //描述
    public string GetDesc(byte[] bytes)
    {
        string str = "";
        if (bytes == null) return str;
        for (int i = 0; i < bytes.Length; i++)
        {
            int b = (int)bytes[i];
            str += b.ToString() + " ";
        }
        return str;
    }

    private void OnApplicationPause(bool pause)
    {
        Close();
    }

    private void OnApplicationFocus(bool focus)
    {
        //重新登录
    }

    /// <summary>
    /// 当应用程序退出或编辑器结束运行
    /// </summary>
    private void OnApplicationQuit()
    {
        Debug.Log("Close");
        Close();
    }
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Unity使用socket可以通过引入socket模块来实现。首先需要构造一个socket对象,可以使用socket.socket()方法来创建。该方法需要传入两个参数,分别是socket.AF_INET和socket.SOCK_STREAM,分别表示使用IPv4地址和流式Socket。\[1\] 在Unity中常用到的Socket方法包括: - IPAddress类:包含了一个IP地址 - IPEndPoint类:包含了一对IP地址和端口号 - Socket类的方法: - 创建一个Socket对象:Socket() - 绑定一个本地的IP和端口号:Bind() - 让Socket侦听传入的连接尝试,并指定侦听队列容量:Listen() - 初始化与另一个Socket的连接:Connect() - 接收连接并返回一个新的socket:Accept() - 输出数据到Socket:Send() - 从Socket中读取数据:Receive() - 关闭Socket(销毁连接):Close()\[2\] 需要注意的是,至少要定义一个要连接的远程主机的IP和端口号。端口号必须在1和65535之间,最好在1024以后。要连接的远程主机必须正在监听指定端口,也就是说你无法随意连接远程主机。一个Socket一次只能连接一台主机。Socket关闭后无法再次使用,每个Socket对象只能连接一台远程主机。如果你想连接到多台远程主机,你必须创建多个Socket对象。\[2\] 另外,需要注意的是,在Unity 5.1 ~ Unity2018中可以使用UNet(Unity Networking),但在Unity 2019之后,UNet已经被废弃,Mirror成为了替代UNet的解决方案。因此,不建议再使用UNet进行网络通信。\[3\] #### 引用[.reference_title] - *1* *3* [【游戏开发实战】Unity使用Socket通信实现简单的多人聊天室(万字详解 | 网络 | TCP | 通信 | Mirror | ...](https://blog.csdn.net/linxinfa/article/details/118888064)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Unity的Socket网络编程](https://blog.csdn.net/weixin_45348216/article/details/128084313)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

地狱为王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值