少年修仙传客户端代码仓库
client_Wu Xijin
2018-10-23 930ba67b9f3e4b099f20574319b5d04c2e429552
Core/NetworkPackage/Socket/ClientSocketController.cs
@@ -1,399 +1,415 @@
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
public class ClientSocketController
{
    Socket m_Socket;
    public Socket socket {
        get { return m_Socket; }
    }
    private int connectWaitTime = 2000;                                  // 10秒
    private Thread m_packageThread;
    private byte[] bufferBytes = new byte[4096];                       // 4K,单包字节数组缓存
    private byte[] fragmentBytes;                                               //留包后的内容
    private long getBytesTotal = 0;                                            //发送的数据总量
    private long sendBytesTotal = 0;                                         //发送的数据总量
    public bool Connected { get { return m_Socket == null ? false : m_Socket.Connected; } }
    public bool isStopTreading { get; private set; }
    string ip;
    int port;
    Action onConnected = null;
    public ClientSocketController()
    {
    }
    public void Connect(string _ip, int _port, Action _onConnected)
    {
        try
        {
            ip = _ip;
            port = _port;
            onConnected = _onConnected;
            Dns.BeginGetHostAddresses(_ip, OnGetHostAddresses, null);
        }
        catch (Exception e)
        {
            DesignDebug.LogError(e.Message);
        }
    }
    private void OnGetHostAddresses(IAsyncResult _result)
    {
        var ipAddresses = Dns.EndGetHostAddresses(_result);
        if (ipAddresses[0].AddressFamily == AddressFamily.InterNetworkV6)
        {
            DesignDebug.Log("当前使用的网络: IPV6");
            m_Socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
        }
        else
        {
            DesignDebug.Log("当前使用的网络: IPV4");
            m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }
        var ipEndPoint = new IPEndPoint(ipAddresses[0], port);
        if (ipEndPoint == null)
        {
            Debug.Log("IpEndPoint is null");
        }
        var state = new SocketAsyncState();
        state.IsAsync = true;
        m_Socket.BeginConnect(ipEndPoint, new AsyncCallback(ConnectCallBack), state);
    }
    /// <summary>
    /// 链接成功时的回调
    /// </summary>
    /// <param name="_result"></param>
    private void ConnectCallBack(IAsyncResult _result)
    {
        if (!_result.IsCompleted)
        {
            DesignDebug.Log("链接超时!");
            CloseConnect();
        }
        else
        {
            if (m_Socket != null && m_Socket.Connected)
            {
                DesignDebug.Log("确认的链接实现");
                OnConnectSuccess();
                if (onConnected != null)
                {
                    onConnected();
                    onConnected = null;
                }
            }
            else
            {
                if (m_Socket != null)
                {
                    m_Socket.Disconnect(true);
                }
                onConnected = null;
            }
        }
    }
    /// <summary>
    /// 关闭链接
    /// </summary>
    public void CloseConnect()
    {
        isStopTreading = true;
        if (m_packageThread != null)
        {
            m_packageThread.Abort();
        }
        if (m_Socket != null && m_Socket.Connected)
        {
            m_Socket.Shutdown(SocketShutdown.Both);
            m_Socket.Close();
        }
        sendQueue.Clear();
        m_Socket = null;
    }
    /// <summary>
    /// 链接成功
    /// </summary>
    private void OnConnectSuccess()
    {
        if (m_packageThread != null)
        {
            m_packageThread.Abort();
            m_packageThread = null;
        }
        m_packageThread = new Thread(new ThreadStart(ReceiveInfo)); // 启动线程接收信息
        m_packageThread.IsBackground = true;
        m_packageThread.Start();
        isStopTreading = false;
    }
    /// <summary>
    /// 接收信息
    /// </summary>
    private void ReceiveInfo()
    {
        int vDataLeng;
        byte[] vBytes;
        while (!isStopTreading)
        {
            if (!m_Socket.Connected)
            {
                isStopTreading = true;
                m_Socket.Shutdown(SocketShutdown.Both);
                m_Socket.Close();
                break;
            }
            try
            {
                vDataLeng = m_Socket.Receive(bufferBytes);
                if (vDataLeng <= 0)
                {
                    isStopTreading = true;
                    m_Socket.Shutdown(SocketShutdown.Both);
                    m_Socket.Close();
                    break;
                }
                getBytesTotal += vDataLeng;
                vBytes = new byte[vDataLeng];
                Array.Copy(bufferBytes, 0, vBytes, 0, vDataLeng);
                ReadInfo(vBytes);
            }
            catch (Exception e)
            {
                DesignDebug.Log(e);
            }
        }
    }
    /// <summary>
    /// 阅读信息
    /// </summary>
    /// <param name="vBytes"></param>
    private void ReadInfo(byte[] vBytes)
    {
        try
        {
            byte[] fixBytes = vBytes;
            // 如果存在留包,则并包
            if (fragmentBytes != null && fragmentBytes.Length > 0)
            {
                Array.Resize(ref fixBytes, vBytes.Length + fragmentBytes.Length);
                Array.Copy(fragmentBytes, 0, fixBytes, 0, fragmentBytes.Length);
                Array.Copy(vBytes, 0, fixBytes, fragmentBytes.Length, vBytes.Length);
            }
            fragmentBytes = null; // 清理掉留包
                                  // 分包
            int vReadIndex = 0; // 初始指针
            byte[] vPackBytes;
            int vLeavingLeng = 0;
            int vBodyLeng = 0;
            int vTotalLeng = fixBytes.Length;
            GameNetPackBasic vNetpack;
            while (vReadIndex < vTotalLeng)
            {
                vLeavingLeng = vTotalLeng - vReadIndex;
                if (vLeavingLeng < 6) // 未符合包的最低限度字节量, 留包
                {
                    fragmentBytes = new byte[vLeavingLeng];
                    Array.Copy(fixBytes, vReadIndex, fragmentBytes, 0, vLeavingLeng);
                    break;
                }
                vBodyLeng = BitConverter.ToInt32(fixBytes, vReadIndex + 2);
                if (vBodyLeng > vLeavingLeng - 6)// 未完整的包则留包
                {
                    fragmentBytes = new byte[vLeavingLeng];
                    Array.Copy(fixBytes, vReadIndex, fragmentBytes, 0, vLeavingLeng);
                    break;
                }
                vPackBytes = new byte[vBodyLeng];
                Array.Copy(fixBytes, vReadIndex + 6, vPackBytes, 0, vBodyLeng); // 提取包的字节内容
                                                                                // 完整的包则读包
                vNetpack = PackageRegedit.TransPack(vPackBytes);
                if (vNetpack != null)
                {
                    if (DesignDebug.EnableNet)
                    {
                        DesignDebug.LogNetFormat("收包:{0}", vNetpack.GetType().Name);
                    }
                    GameNetSystem.Instance.PushPackage(vNetpack);
                }
                vReadIndex += 6 + vBodyLeng;
            }
        }
        catch (Exception ex)
        {
            Debug.LogFormat("收包异常:{0}", ex);
        }
    }
    /// <summary>
    /// 发送信息
    /// </summary>
    /// <param name="vNetPack"></param>
    public void SendInfo(GameNetPackBasic vNetPack)
    {
        if (!Connected)
            return;
        if (vNetPack == null)
        {
            DesignDebug.LogError("要发的信息对象为空");
            return;
        }
        if (DesignDebug.EnableNet)
        {
            DesignDebug.LogNetFormat("发包:{0}", vNetPack.GetType().Name);
        }
        if (vNetPack.cmd == (ushort)0x03FE || vNetPack.cmd == (ushort)0x1801)
        {
        }
        if (vNetPack.combineBytes == null)
        {
            vNetPack.WriteToBytes();
        }
        vNetPack.CombineDatas();
#if UNITY_EDITOR
        NetPkgCtl.AddNetPkg(vNetPack.vInfoCont, NetPkgType.Client, vNetPack.ToString(), FieldPrint.PrintFields(vNetPack), FieldPrint.PrintFieldsExpand(vNetPack, true));
#endif
        sendBytesTotal += vNetPack.combineBytes.Length;
        SendBytes(vNetPack.combineBytes);
    }
    /// <summary>
    /// 发送信息
    /// </summary>
    /// <param name="vBytes"></param>
    public void SendInfo(byte[] vBytes)
    {
        if (!Connected)
        {
            DesignDebug.LogError("尚未与该后端链接!无法发送信息");
            return;
        }
        if (vBytes == null || vBytes.Length < 2)
        {
            DesignDebug.LogError("要发的信息数据为空或数据不足");
            return;
        }
        vBytes = GameNetEncode.BaseXorAdd(vBytes);
        byte[] vFrameHead = new byte[] { 255, 204 };
        byte[] vMsgBodyLength = BitConverter.GetBytes(vBytes.Length);
        byte[] vTotal = new byte[vBytes.Length + 6];
        Array.Copy(vFrameHead, 0, vTotal, 0, vFrameHead.Length);
        Array.Copy(vMsgBodyLength, 0, vTotal, 2, vMsgBodyLength.Length);
        Array.Copy(vBytes, 0, vTotal, 6, vBytes.Length);
        SendBytes(vBytes);
    }
    /// <summary>
    /// 发送已加密字节
    /// </summary>
    /// <param name="vBytes"></param>
    public void SendNoEncrypInfo(byte[] vBytes)
    {
        if (!Connected)
        {
            DesignDebug.LogError("尚未与该后端链接!无法发送信息");
            return;
        }
        if (vBytes == null || vBytes.Length < 2)
        {
            DesignDebug.LogError("要发的信息数据为空或数据不足");
            return;
        }
        SendBytes(vBytes);
    }
    Queue<byte[]> sendQueue = new Queue<byte[]>();
    private void SendBytes(byte[] bytes)
    {
        try
        {
            if (sendQueue.Count > 0)
            {
                sendQueue.Enqueue(bytes);
            }
            else
            {
                m_Socket.BeginSend(bytes, 0, bytes.Length, SocketFlags.None, new AsyncCallback(SendInfoCallBack), m_Socket);
            }
        }
        catch
        {
            DesignDebug.LogError("发送时发生异常");
        }
    }
    /// <summary>
    /// 发送完成的回调
    /// </summary>
    /// <param name="vAsyncSend"></param>
    private void SendInfoCallBack(IAsyncResult vAsyncSend)
    {
        try
        {
            if (sendQueue.Count > 0)
            {
                var bytes = sendQueue.Dequeue();
                m_Socket.BeginSend(bytes, 0, bytes.Length, SocketFlags.None, new AsyncCallback(SendInfoCallBack), m_Socket);
            }
        }
        catch (Exception ex)
        {
            DesignDebug.Log(ex);
        }
    }
    internal class SocketAsyncState
    {
        /// <summary>
        /// 是否完成。
        /// </summary>
        public bool Completed { get; set; }
        /// <summary>
        /// 数据
        /// </summary>
        public byte[] Data { get; set; }
        /// <summary>
        /// 是否异步
        /// </summary>
        public bool IsAsync { get; set; }
    }
}
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
public class ClientSocketController
{
    Socket m_Socket;
    public Socket socket
    {
        get { return m_Socket; }
    }
    private int connectWaitTime = 2000;                                  // 10秒
    private Thread m_packageThread;
    private byte[] bufferBytes = new byte[4096];                       // 4K,单包字节数组缓存
    private byte[] fragmentBytes;                                               //留包后的内容
    private long getBytesTotal = 0;                                            //发送的数据总量
    private long sendBytesTotal = 0;                                         //发送的数据总量
    public bool Connected { get { return m_Socket == null ? false : m_Socket.Connected; } }
    public bool isStopTreading { get; private set; }
    string ip;
    int port;
    Action onConnected = null;
    public ClientSocketController()
    {
    }
    public void Connect(string _ip, int _port, Action _onConnected)
    {
        try
        {
            ip = _ip;
            port = _port;
            onConnected = _onConnected;
            Dns.BeginGetHostAddresses(_ip, OnGetHostAddresses, null);
        }
        catch (Exception e)
        {
            DebugEx.LogError(e.Message);
        }
    }
    private void OnGetHostAddresses(IAsyncResult _result)
    {
        var ipAddresses = Dns.EndGetHostAddresses(_result);
        if (ipAddresses[0].AddressFamily == AddressFamily.InterNetworkV6)
        {
            DebugEx.Log("当前使用的网络: IPV6");
            m_Socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
        }
        else
        {
            DebugEx.Log("当前使用的网络: IPV4");
            m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }
        var ipEndPoint = new IPEndPoint(ipAddresses[0], port);
        if (ipEndPoint == null)
        {
            Debug.Log("IpEndPoint is null");
        }
        var state = new SocketAsyncState();
        state.IsAsync = true;
        m_Socket.BeginConnect(ipEndPoint, new AsyncCallback(ConnectCallBack), state);
    }
    /// <summary>
    /// 链接成功时的回调
    /// </summary>
    /// <param name="_result"></param>
    private void ConnectCallBack(IAsyncResult _result)
    {
        if (!_result.IsCompleted)
        {
            DebugEx.Log("链接超时!");
            CloseConnect();
        }
        else
        {
            if (m_Socket != null && m_Socket.Connected)
            {
                DebugEx.Log("确认的链接实现");
                OnConnectSuccess();
                if (onConnected != null)
                {
                    onConnected();
                    onConnected = null;
                }
            }
            else
            {
                if (m_Socket != null)
                {
                    m_Socket.Disconnect(true);
                }
                onConnected = null;
            }
        }
    }
    /// <summary>
    /// 关闭链接
    /// </summary>
    public void CloseConnect()
    {
        try
        {
            isStopTreading = true;
            if (m_packageThread != null)
            {
                m_packageThread.Abort();
            }
        }
        catch (System.Exception ex)
        {
            DebugEx.Log(ex);
        }
        try
        {
            if (m_Socket != null && m_Socket.Connected)
            {
                m_Socket.Shutdown(SocketShutdown.Both);
                m_Socket.Close();
            }
        }
        catch (System.Exception ex)
        {
            DebugEx.Log(ex);
        }
        sendQueue.Clear();
        m_Socket = null;
    }
    /// <summary>
    /// 链接成功
    /// </summary>
    private void OnConnectSuccess()
    {
        if (m_packageThread != null)
        {
            m_packageThread.Abort();
            m_packageThread = null;
        }
        m_packageThread = new Thread(new ThreadStart(ReceiveInfo)); // 启动线程接收信息
        m_packageThread.IsBackground = true;
        m_packageThread.Start();
        isStopTreading = false;
    }
    /// <summary>
    /// 接收信息
    /// </summary>
    private void ReceiveInfo()
    {
        int vDataLeng;
        byte[] vBytes;
        while (!isStopTreading)
        {
            if (!m_Socket.Connected)
            {
                isStopTreading = true;
                m_Socket.Shutdown(SocketShutdown.Both);
                m_Socket.Close();
                break;
            }
            try
            {
                vDataLeng = m_Socket.Receive(bufferBytes);
                if (vDataLeng <= 0)
                {
                    isStopTreading = true;
                    m_Socket.Shutdown(SocketShutdown.Both);
                    m_Socket.Close();
                    break;
                }
                getBytesTotal += vDataLeng;
                vBytes = new byte[vDataLeng];
                Array.Copy(bufferBytes, 0, vBytes, 0, vDataLeng);
                ReadInfo(vBytes);
            }
            catch (Exception e)
            {
                DebugEx.Log(e);
            }
        }
    }
    /// <summary>
    /// 阅读信息
    /// </summary>
    /// <param name="vBytes"></param>
    private void ReadInfo(byte[] vBytes)
    {
        try
        {
            byte[] fixBytes = vBytes;
            // 如果存在留包,则并包
            if (fragmentBytes != null && fragmentBytes.Length > 0)
            {
                Array.Resize(ref fixBytes, vBytes.Length + fragmentBytes.Length);
                Array.Copy(fragmentBytes, 0, fixBytes, 0, fragmentBytes.Length);
                Array.Copy(vBytes, 0, fixBytes, fragmentBytes.Length, vBytes.Length);
            }
            fragmentBytes = null; // 清理掉留包
                                  // 分包
            int vReadIndex = 0; // 初始指针
            byte[] vPackBytes;
            int vLeavingLeng = 0;
            int vBodyLeng = 0;
            int vTotalLeng = fixBytes.Length;
            GameNetPackBasic vNetpack;
            while (vReadIndex < vTotalLeng)
            {
                vLeavingLeng = vTotalLeng - vReadIndex;
                if (vLeavingLeng < 6) // 未符合包的最低限度字节量, 留包
                {
                    fragmentBytes = new byte[vLeavingLeng];
                    Array.Copy(fixBytes, vReadIndex, fragmentBytes, 0, vLeavingLeng);
                    break;
                }
                vBodyLeng = BitConverter.ToInt32(fixBytes, vReadIndex + 2);
                if (vBodyLeng > vLeavingLeng - 6)// 未完整的包则留包
                {
                    fragmentBytes = new byte[vLeavingLeng];
                    Array.Copy(fixBytes, vReadIndex, fragmentBytes, 0, vLeavingLeng);
                    break;
                }
                vPackBytes = new byte[vBodyLeng];
                Array.Copy(fixBytes, vReadIndex + 6, vPackBytes, 0, vBodyLeng); // 提取包的字节内容
                                                                                // 完整的包则读包
                vNetpack = PackageRegedit.TransPack(vPackBytes);
                if (vNetpack != null)
                {
                    if (DebugEx.EnableNetLog)
                    {
                        DebugEx.NetLogFormat("收包:{0}", vNetpack.GetType().Name);
                    }
                    GameNetSystem.Instance.PushPackage(vNetpack);
                }
                vReadIndex += 6 + vBodyLeng;
            }
        }
        catch (Exception ex)
        {
            Debug.LogFormat("收包异常:{0}", ex);
        }
    }
    /// <summary>
    /// 发送信息
    /// </summary>
    /// <param name="vNetPack"></param>
    public void SendInfo(GameNetPackBasic vNetPack)
    {
        if (!Connected)
            return;
        if (vNetPack == null)
        {
            DebugEx.LogError("要发的信息对象为空");
            return;
        }
        if (DebugEx.EnableNetLog)
        {
            DebugEx.NetLogFormat("发包:{0}", vNetPack.GetType().Name);
        }
        if (vNetPack.cmd == (ushort)0x03FE || vNetPack.cmd == (ushort)0x1801)
        {
        }
        if (vNetPack.combineBytes == null)
        {
            vNetPack.WriteToBytes();
        }
        vNetPack.CombineDatas();
#if UNITY_EDITOR
        NetPkgCtl.AddNetPkg(vNetPack.vInfoCont, NetPkgType.Client, vNetPack.ToString(), FieldPrint.PrintFields(vNetPack), FieldPrint.PrintFieldsExpand(vNetPack, true));
#endif
        sendBytesTotal += vNetPack.combineBytes.Length;
        SendBytes(vNetPack.combineBytes);
    }
    /// <summary>
    /// 发送信息
    /// </summary>
    /// <param name="vBytes"></param>
    public void SendInfo(byte[] vBytes)
    {
        if (!Connected)
        {
            DebugEx.LogError("尚未与该后端链接!无法发送信息");
            return;
        }
        if (vBytes == null || vBytes.Length < 2)
        {
            DebugEx.LogError("要发的信息数据为空或数据不足");
            return;
        }
        vBytes = GameNetEncode.BaseXorAdd(vBytes);
        byte[] vFrameHead = new byte[] { 255, 204 };
        byte[] vMsgBodyLength = BitConverter.GetBytes(vBytes.Length);
        byte[] vTotal = new byte[vBytes.Length + 6];
        Array.Copy(vFrameHead, 0, vTotal, 0, vFrameHead.Length);
        Array.Copy(vMsgBodyLength, 0, vTotal, 2, vMsgBodyLength.Length);
        Array.Copy(vBytes, 0, vTotal, 6, vBytes.Length);
        SendBytes(vTotal);
    }
    /// <summary>
    /// 发送已加密字节
    /// </summary>
    /// <param name="vBytes"></param>
    public void SendNoEncrypInfo(byte[] vBytes)
    {
        if (!Connected)
        {
            DebugEx.LogError("尚未与该后端链接!无法发送信息");
            return;
        }
        if (vBytes == null || vBytes.Length < 2)
        {
            DebugEx.LogError("要发的信息数据为空或数据不足");
            return;
        }
        SendBytes(vBytes);
    }
    Queue<byte[]> sendQueue = new Queue<byte[]>();
    private void SendBytes(byte[] bytes)
    {
        try
        {
            if (sendQueue.Count > 0)
            {
                sendQueue.Enqueue(bytes);
            }
            else
            {
                m_Socket.BeginSend(bytes, 0, bytes.Length, SocketFlags.None, new AsyncCallback(SendInfoCallBack), m_Socket);
            }
        }
        catch
        {
            DebugEx.LogError("发送时发生异常");
        }
    }
    /// <summary>
    /// 发送完成的回调
    /// </summary>
    /// <param name="vAsyncSend"></param>
    private void SendInfoCallBack(IAsyncResult vAsyncSend)
    {
        try
        {
            if (sendQueue.Count > 0)
            {
                var bytes = sendQueue.Dequeue();
                m_Socket.BeginSend(bytes, 0, bytes.Length, SocketFlags.None, new AsyncCallback(SendInfoCallBack), m_Socket);
            }
        }
        catch (Exception ex)
        {
            DebugEx.Log(ex);
        }
    }
    internal class SocketAsyncState
    {
        /// <summary>
        /// 是否完成。
        /// </summary>
        public bool Completed { get; set; }
        /// <summary>
        /// 数据
        /// </summary>
        public byte[] Data { get; set; }
        /// <summary>
        /// 是否异步
        /// </summary>
        public bool IsAsync { get; set; }
    }
}