Unity TCP

介绍

Unity TCP_第1张图片

前后端均采用C# 降低学习成本

代码依赖 Newtonsoft.Json, 您可以通过Nuget获取或者去github下载最新版

服务端

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using Newtonsoft.Json;

public class TCPServers
{


    // 各阶段处理回调
    public delegate bool ReceiveAction(Socket arg0, string arg1);
    protected static Action<Socket> _linkHandler;
    protected static ReceiveAction _receiveHandler;
    protected static Action<Socket> _clientOutHandler;
    protected static Action<Socket> _illegalityHandler;



    /// 
    /// 
    /// 
    ///  服务器配置地址 
    ///  新客户端连接处理方法 
    ///  客户端消息处理 
    ///  客户端掉线处理 
    ///  程序连接异常崩溃处理 
    public static void Listen(string configFile, Action<Socket> newLinkHandler, ReceiveAction receiveHandler, Action<Socket> clientOutHandler, Action<Socket> illegalityHandler)
    {

        //读取配置
        string ip = "0.0.0.0";
        int port = 5566;
        int backlog = 5000;
        Encoding encoding = Encoding.UTF8;
        try
        {
            var jsonstr = File.ReadAllText(configFile);
            var conf = JsonConvert.DeserializeObject<JsonData>(jsonstr);
            ip = conf.GetStr("ip");
            port = conf.GetInt("port");
            backlog = conf.GetInt("max-client-count");
            encoding = Encoding.GetEncoding(conf.GetInt("Encoding-Code"));
        }
        catch (Exception e)
        {
            Console.WriteLine($"配置文件异常: {configFile}\n${e.Message}\n${e.StackTrace}");
        }


        //回调绑定
        _linkHandler = newLinkHandler;
        _receiveHandler = receiveHandler;
        _clientOutHandler = clientOutHandler;
        _illegalityHandler = illegalityHandler;


        try
        {

            //初始化服务器
            _netServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            var endPoint = new IPEndPoint(IPAddress.Parse(ip), port);
            _netServer.Bind(endPoint);
            _netServer.Listen(backlog);
            Console.WriteLine("服务器已启动... ...");

        }
        catch (SocketException e)
        {

            Console.WriteLine($"套接字绑定异常: \n${e.Message}\n${e.StackTrace}");
        }
        catch (Exception e2)
        {

            Console.WriteLine($"程序异常: \n${e2.Message}\n${e2.StackTrace}");
        }

        var T1 = new Thread(() =>
            {

                while (true)
                {
                    var newAccept = _netServer.Accept();//接收新的客户端接入
                    Console.WriteLine($"客户端 {newAccept.RemoteEndPoint.ToString()} 建立连接......");
                    _linkHandler?.Invoke(newAccept);//新客户端连接

                    var T2 = new Thread(() =>
                    {

                        byte[] buffer = new byte[1024 * 1024];
                        bool runState = true;

                        try
                        {

                            //循环监听客户端事件
                            while (runState)
                            {
                                int len = newAccept.Receive(buffer, 0, buffer.Length, SocketFlags.None);

                                if (len == 0)
                                {
                                    break;
                                }

                                runState = _receiveHandler(newAccept, encoding.GetString(buffer, 0, len));
                            }

                            //断开连接
                            Console.WriteLine($"客户端 {newAccept.RemoteEndPoint.ToString()} 断开连接......");
                            _clientOutHandler?.Invoke(newAccept);
                        }
                        catch
                        {
                            //程序连接异常崩溃处理
                            Console.WriteLine($"客户端 {newAccept.RemoteEndPoint.ToString()} 程序连接异常......");
                            _illegalityHandler?.Invoke(newAccept);
                        }

                    });

                    //运行后台运行
                    T2.IsBackground = true;
                    T2.Start();
                }

            });

        //运行后台运行
        T1.IsBackground = true;
        T1.Start();


    }



    #region private


    ///  唯一套接字 
    static Socket _netServer = null;



    ///  共享Socket 不允许修改 
    public static Socket shareSocketInstance { get { return _netServer; } }



    ///  不允许用户自己创建 
    private TCPServers() { }

    #endregion


}



客户端


using System;
using System.Net.Sockets;
using UnityEngine;
using System.Collections.Generic;
using Newtonsoft.Json;
using System.Text;


public class TCPClient
{
    private Socket init()
    {
        Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        // 接收的消息数据包大小限制为 0x4000 byte, 即16KB
        m_recvBuff = new byte[0x4000];
        m_recvCb = new AsyncCallback(RecvCallBack);
        return clientSocket;
    }

    /// 
    /// 连接服务器
    /// 
    /// ip地址
    /// 端口号
    ///  是否连接成功 
    public bool Connect(string host, int port)
    {
        if (m_socket == null)
            m_socket = init();
        try
        {
            Debug.Log("connect: " + host + ":" + port);
            m_socket.SendTimeout = 3;
            m_socket.Connect(host, port);
            connected = true;

        }
        catch (Exception ex)
        {
            Debug.LogError(ex);
            connected = false;
        }

        return connected;
    }

    /// 
    /// 发送消息
    /// 
    public void SendData(byte[] bytes)
    {
        NetworkStream netstream = new NetworkStream(m_socket);
        netstream.Write(bytes, 0, bytes.Length);
    }
    /// 
    /// 发送消息
    /// 
    /// 
    public void SendData(ProtocolEvent e, JsonData data)
    {
        data["Event"] = e;
        string pkt = JsonConvert.SerializeObject(data);
        SendData(Encoding.UTF8.GetBytes(pkt));
    }

    /// 
    /// 尝试接收消息(每帧调用)
    /// 
    public void BeginReceive()
    {
        m_socket.BeginReceive(m_recvBuff, 0, m_recvBuff.Length, SocketFlags.None, m_recvCb, this);
    }

    /// 
    /// 当收到服务器的消息时会回调这个函数
    /// 
    private void RecvCallBack(IAsyncResult ar)
    {
        var len = m_socket.EndReceive(ar);
        byte[] msg = new byte[len];
        Array.Copy(m_recvBuff, msg, len);
        var msgStr = Encoding.UTF8.GetString(msg);
        // 将消息塞入队列中
        m_msgQueue.Enqueue(msgStr);
        // 将buffer清零
        for (int i = 0; i < m_recvBuff.Length; ++i)
        {
            m_recvBuff[i] = 0;
        }
    }

    /// 
    /// 从消息队列中取出消息
    /// 
    /// 
    public string GetMsgFromQueue()
    {
        if (m_msgQueue.Count > 0)
            return m_msgQueue.Dequeue();
        return null;
    }

    /// 
    /// 关闭Socket
    /// 
    public void CloseSocket()
    {
        Debug.Log("close socket");
        try
        {
            m_socket.Shutdown(SocketShutdown.Both);
            m_socket.Close();
        }
        catch (Exception e)
        {
            //Debug.LogError(e);
        }
        finally
        {
            m_socket = null;
            connected = false;
        }
    }


    public bool connected = false;

    private byte[] m_recvBuff;
    private AsyncCallback m_recvCb;
    private Queue<string> m_msgQueue = new Queue<string>();
    private Socket m_socket;
}

JsonData


using System;
using System.Collections;
using System.Collections.Generic;


/// 
/// JsonData 对象
///
/// example:
/// 
///     //JsonData对象转json字符串
///     var t = new JsonData();
///     t["name"] = "geek7";
///     t["age"] = 24;
///     t["isMan"] = true;
///     var jsonstr = JsonConvert.SerializeObject(t);
///     //输出
///     Debug.Log($"jsonString:\n{jsonstr}");
///
/// 
///     //json字符串转JsonData对象
///     var obj = JsonConvert.DeserializeObject(jsonstr);
///     //输出
///     Debug.Log($"jsonData:\nname: {obj.GetStr("name")}\tage: {obj.GetInt("age")}\tsex: {(obj.GetBoolean("isMan") ? "man" : "woman")}");
/// 
/// 
[Serializable]
public class JsonData : Dictionary<string, object>
{
    /// 
    /// 获取一个整形值
    /// 
    /// 
    ///  value || default(int) 
    public int GetInt(string k)
    {
        object v;
        if (TryGetValue(k, out v))
        {
            return Convert.ToInt32(v);
        }
        return default(int);
    }

    /// 
    /// 获取一个字符串值
    /// 
    /// 
    ///  value || string.Empty
    public string GetStr(string k)
    {
        object v;
        if (TryGetValue(k, out v))
        {
            return v.ToString();
        }
        return string.Empty;
    }

    /// 
    /// 获取一个float值
    /// 
    /// 
    ///  value || float.NaN
    public float GetFloat(string k)
    {
        object v;
        if (TryGetValue(k, out v))
        {
            return Convert.ToSingle(v);
        }
        return float.NaN;
    }

    /// 
    /// 获取一个bool值
    /// 
    /// 
    ///  value || default(bool)
    public bool GetBoolean(string k)
    {
        object v;
        if (TryGetValue(k, out v))
        {
            return Convert.ToBoolean(v);
        }
        return default(bool);
    }

    /// 
    /// 获取一个Double值
    /// 
    /// 
    ///  value || Double.NaN
    public double GetDouble(string k)
    {
        object v;
        if (TryGetValue(k, out v))
        {
            return Convert.ToDouble(v);
        }
        return Double.NaN;
    }
}


你可能感兴趣的:(Unity,Network,Communication,Protocol,unity,tcp/ip,游戏引擎)