{"id":1113,"date":"2015-01-16T04:00:11","date_gmt":"2015-01-16T04:00:11","guid":{"rendered":"http:\/\/blog.zhukunqian.com\/?p=1113"},"modified":"2015-01-19T15:21:24","modified_gmt":"2015-01-19T15:21:24","slug":"%e6%b8%b8%e6%88%8f%e4%b8%ad%e9%87%8d%e6%9e%84%e4%ba%86%e7%bd%91%e7%bb%9c%e6%a8%a1%e5%9d%97","status":"publish","type":"post","link":"https:\/\/blog.zhukunqian.com\/?p=1113","title":{"rendered":"\u6e38\u620f\u4e2d\u91cd\u6784\u4e86\u7f51\u7edc\u6a21\u5757"},"content":{"rendered":"<p>\u6211\u4eec\u6e38\u620f\u4e2d\u65ad\u7ebf\u548c\u8d85\u65f6\u8fd9\u4e00\u5757\u51fa\u95ee\u9898\u975e\u5e38\u591a\u3002<\/p>\n<p>\u8fd9\u4e00\u6b21\u6211\u4e13\u95e8\u62bd\u51fa\u4e86\u4e00\u5468\u65f6\u95f4\uff0c\u4e86\u89e3\u4e86\u4e0bc#\u4e0b\u7684socket\u76f8\u5173\u51fd\u6570\u91cd\u5199\u4e86\u7f51\u7edc\u6a21\u5757\u3002<\/p>\n<p>\u9996\u8981\u76ee\u6807\u662f\u907f\u514d\u53e6\u5f00\u7ebf\u7a0b\uff0c\u4f7f\u7528nio\u3002\u7136\u540e\u662f\u5185\u90e8\u5904\u7406\u8d85\u65f6\uff0c\u65ad\u7ebf\u548c\u5176\u5b83IO\u5f02\u5e38\uff0c\u91cd\u8fde3\u6b21\u5931\u8d25\u540e\uff0c\u624d\u63d0\u4ea4\u7ed9\u6e38\u620f\u81ea\u5df1\u5904\u7406\u3002\u91cd\u8fde\u65f6\uff0c\u81ea\u52a8\u767b\u9646\u5e76\u7eed\u53d1\u6d88\u606f\u3002<\/p>\n<p>\u8fd9\u91cc\u672c\u6765\u8fd8\u9700\u8981\u6dfb\u52a0\u4e00\u4e2a\u8865\u53d1\u6d88\u606f\u7684\u673a\u5236(\u65ad\u7ebf\u540e\u7f51\u7edc\u4f20\u8f93\u4e2d\u5bfc\u81f4\u4e22\u5931\u7684\u6d88\u606f)\uff0c\u4f46\u662f\u6d4b\u8bd5\u53ea\u6709\u7eed\u53d1\u6d88\u606f\uff0c\u5df2\u7ecf\u89e3\u51b3\u6389\u4e86\u539f\u676599%\u95ee\u9898\u3002\u6240\u4ee5\u8865\u53d1\u6d88\u606f\u5148\u653e\u4e00\u4e0b\uff0c\u5148\u518d\u91cd\u6784\u5176\u5b83\u5730\u65b9\u3002<\/p>\n<p>\u91cd\u6784\u540e\u6d4b\u8bd5\u7684\u7ed3\u679c\u975e\u5e38\u597d\uff0c\u4ee5\u524d\u5404\u79cd\u7f51\u7edc\u95ee\u9898\u90fd\u6ca1\u6709\u590d\u73b0\uff0c\u65ad\u7ebf\u5bf9\u73a9\u5bb6\u6765\u8bf4\u662f\u4e0d\u53ef\u89c1\u7684\uff0c\u53ea\u8981\u957f\u65f6\u95f4\u65ad\u7ebf(\u4e09\u6b21\u91cd\u8fde\u5931\u8d25)\u624d\u4f1a\u7ed9\u73a9\u5bb6\u4e00\u4e2a\u63d0\u793a\u6846\uff0c\u8ba9\u73a9\u5bb6\u624b\u52a8\u70b9\u51fb\u53bb\u91cd\u8fde\u3002<\/p>\n<pre class=\"brush: bash; gutter: true\">\/\/----------------------------------------------\r\n\/\/           NET        : NetManager\r\n\/\/           AUTHOR: zhu kun qian\r\n\/\/----------------------------------------------\r\n\r\nusing System.IO;\r\n\r\npublic class NetMsg\r\n{\r\n    \/\/ \u6709\u5fc5\u8981\u7528id\u5417\uff1f\r\n    \/\/ \r\n    public cmd.CmdType cmdType;\r\n    public uint loop;\/\/ \u552f\u4e00\u7684\u5faa\u73afid\r\n    public byte[] data;\/\/ protobuf\u4e8c\u8fdb\u5236\u6570\u636e\r\n    public byte[] totalData;\/\/\u5b8c\u6574\u7684\u6d88\u606f\u4e8c\u8fdb\u5236\u6570\u636e\r\n    public MemoryStream netdata;\r\n\r\n    \/\/ \u8fd9\u91cc\u80fd\u907f\u514d\u4e00\u6b21array copy\u4e0d\uff1f\r\n    \/\/ TODO:\u6682\u4e0d\u8003\u8651\u8fd9\u907f\u514darry copy\u7684\u6d88\u8017\uff0c\u4ee5\u540e\u6709\u65f6\u95f4\u65f6\uff0c\u53ef\u4ee5\u8003\u8651\u5904\u7406\u4e0b\u3002\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<pre class=\"brush: bash; gutter: true\">\/\/----------------------------------------------\r\n\/\/           NET        : NetManager\r\n\/\/           AUTHOR: zhu kun qian\r\n\/\/----------------------------------------------\r\n\r\nusing System.Net;\r\nusing System.Net.Sockets;\r\nusing System.Runtime.Remoting.Messaging;\r\nusing UnityEngine;\r\nusing System;\r\nusing System.Collections;\r\nusing System.Collections.Generic;\r\nusing System.IO;\r\n\r\n\/*\r\n * \u6ca1\u6709\u4f7f\u7528\u4efb\u4f55\u963b\u585e\u51fd\u6570\u3002\r\n * \r\n * connect\u662fblock\u51fd\u6570\uff0c\u6240\u4ee5\u6539\u4e3a\u4f7f\u7528ConnectAsync, beginConnect\u4e5f\u662f\u5f02\u6b65\uff0c\u4e5f\u53ef\u4ee5\u4f7f\u7528\r\n * \r\n * \u8fde\u63a5\u6210\u529f\u540e\uff0csocket\u4fee\u6539\u4e3anon-blocking\r\n*\/\r\npublic class NetManagerSocket\r\n{\r\n\r\n    \/\/ \u5982\u679c\u65ad\u5f00\u8fde\u63a5\uff0c\u76f4\u63a5new socket\r\n\r\n    public string ip;\r\n    public int port;\r\n\r\n    private Socket socket;\r\n    private byte[] readBuf = new byte[64 * 1024];\/\/ \u6700\u9ad8\u7f13\u5b58\u63a5\u653664k\u6570\u636e\u3002\r\n\r\n    private int readBufIndex = 0;\/\/\u5df2\u7ecf\u4ecereadBuf\u4e2d\u8bfb\u53d6\u7684\u5b57\u8282\u6570\r\n    private int available = 0;\/\/ readbuf\u5df2\u7ecf\u4ecesocket\u4e2d\u63a5\u6536\u7684\u5b57\u8282\u6570\r\n\r\n    public SocketError socketError = SocketError.Success;\/\/ \u8fd9\u91cc\u5e94\u8be5\u662f\u4f20\u9012\u5230\u4e0a\u5c42\uff0c\u8fd8\u662f\u5728\u8fd9\u91cc\u5904\u7406\uff1f\r\n\r\n    \/\/ ---------------------------------------\r\n    \/\/ -- decoder\u76f8\u5173\r\n    private int length = 0;\/\/ protobuf\u6d88\u606f\u4f53\u4e2d\u7684\u957f\u5ea6\r\n    private int needRead = 0;\/\/ protobuf\u6d88\u606f\u4f53\u4e2d\u5269\u4f59\u9700\u8981\u8bfb\u53d6\u7684\u957f\u5ea6\r\n    \/\/ ---------------------------------------\r\n\r\n    public void connect()\r\n    {\r\n        socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);\r\n        socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);\r\n        socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 5000);\/\/ \u8bbe\u7f6e5\u79d2\u53d1\u9001\u8d85\u65f6\r\n        socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, false);\r\n        socket.NoDelay = true;\r\n        \/\/ socket.Blocking = false;\r\n        socket.Blocking = true;\/\/\u8bbe\u7f6e\u4e3a\u975e\u963b\u585e\r\n\r\n        socketError = SocketError.Success;\r\n\r\n        Debug.Log(&quot;dontLinger:&quot; + socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger));\r\n        try\r\n        {\r\n            \/\/ \u8fd9\u91cc\u9700\u8981\u4fee\u6539\u4e3a\u5f02\u6b65connect\r\n            \/\/ http:\/\/msdn.microsoft.com\/en-us\/library\/d7ew360f%28v=vs.110%29.aspx\r\n            \/\/ Connect method will block, unless you specifically set the Blocking property to false prior to calling Connect.\r\n            \/\/ If you are using a connection-oriented protocol like TCP and you do disable blocking, Connect will throw a SocketException because it needs time to make the connection\r\n            \/\/ \u7ed3\u8bba\uff1a\u5f88\u5947\u602a\uff0c\u5e76\u6ca1\u6709\u6309\u6587\u6863\u4e0a\u63cf\u8ff0\u7684\u6267\u884c\uff0c\u8bbe\u7f6e\u4e3ablocking\uff0c\u5e76\u6ca1\u6709\u629b\u51fa\u5f02\u5e38\u3002\r\n\r\n            \/\/ socket.Connect(ip, port);\r\n\r\n            \/\/ The asynchronous BeginConnect operation must be completed by calling the EndConnect method.\r\n            \/\/ IAsyncResult result= socket.BeginConnect(ip, port, new AsyncCallback(connectCallback), socket);\r\n\r\n            \/\/ Debug.Log(&quot;asyncResult is completed:&quot;+result.IsCompleted);\r\n\r\n            \/\/ \u5f02\u6b65\u5904\u7406\u5fc5\u987b\u8bbe\u7f6e\u4e3ablocking\uff0cwhy?\r\n            \/\/*\r\n            SocketAsyncEventArgs eventArgs = new SocketAsyncEventArgs();\r\n            eventArgs.RemoteEndPoint = new IPEndPoint(IPAddress.Parse(ip), port);\r\n            eventArgs.Completed += new EventHandler&lt;SocketAsyncEventArgs&gt;(connectCallback2);\r\n            eventArgs.UserToken = socket;\r\n\r\n            socket.ConnectAsync(eventArgs);\r\n\r\n            \/\/ *\/\r\n            \/\/ \u8fd9\u91cc\u9700\u8981\u6dfb\u52a0\u8d85\u65f6\u5904\u7406\u5417\uff1f\r\n        }\r\n        catch (Exception ex)\r\n        {\r\n            Debug.LogError(&quot;socket connection exception:&quot; + ex);\r\n            socketError = SocketError.ConnectionRefused;\r\n        }\r\n    }\r\n\r\n    private void connectCallback2(object src, SocketAsyncEventArgs result)\r\n    {\r\n        Debug.Log(&quot;connectCallback2, isCompleted:&quot; + result + &quot; &quot; + result.SocketError);\r\n        if (result.SocketError != SocketError.Success)\r\n        {\r\n            socketError = result.SocketError;\r\n        }\r\n        else\r\n        {\r\n            Socket socket = (Socket)src;\r\n            socket.Blocking = false;\r\n        }\r\n    }\r\n\r\n    void connectCallback(IAsyncResult result)\r\n    {\r\n        Debug.Log(&quot;connectCallback22, isCompleted:&quot; + result.IsCompleted);\r\n        \/\/ connected = true;\r\n        try\r\n        {\r\n            Socket socket = (Socket)result.AsyncState;\r\n            socket.EndConnect(result);\r\n\r\n            Debug.Log(&quot;socket is connected:&quot; + socket.Connected);\r\n            socket.Send(new byte[] { });\r\n        }\r\n        catch (Exception e)\r\n        {\r\n            Debug.LogError(&quot;error:&quot; + e);\r\n            socketError = SocketError.ConnectionRefused;\r\n        }\r\n    }\r\n\r\n    public void disconnect()\r\n    {\r\n        if (socket != null)\r\n        {\r\n            socket.Close();\r\n            socket = null;\r\n        }\r\n    }\r\n\r\n    \/\/\r\n\r\n    public NetMsg read()\r\n    {\r\n        \/\/ \u8fd9\u91cc\u540c\u6b65\u8bfb\u4e5f\u53ef\u4ee5\uff0c\u4f46\u53ea\u8bfb\u6570\u636e\u63a5\u6536\u5230\u8db3\u591f\u4e00\u4e2a\u6d88\u606f\u7684\u60c5\u51b5\r\n        \/\/ \u4f7f\u7528availed\u9884\u5224\u8fdb\u884c\u540c\u6b65\u8bfb\uff0c\u4e0d\u4f1a\u963b\u585e\u4e3b\u7ebf\u7a0b\r\n        \/\/ \u89e3\u6790\u6d88\u606f\u653e\u5728\u8fd9\u91cc\u3002\r\n        if (socket != null &amp;&amp; socket.Available &gt; 0)\r\n        {\r\n            if (available == 0)\r\n            {\r\n                if (socket.Available &lt; 12)\r\n                {\r\n                    \/\/ \u4e00\u4e2a\u6570\u636e\u5305\uff0c\u6700\u5c0f\u4e3a12\u5b57\u8282\r\n                    return null;\r\n                }\r\n                \/\/ \u5f00\u59cb\u4ecesocket\u4e2d\u8bfb\u5165\u4e00\u6761\u6570\u636e\r\n                \/\/ \u5982\u679c\u8db3\u591f\uff0c\u5c31\u76f4\u63a5\u89e3\u6790\u4e3a\u6d88\u606f\u8fd4\u56de\r\n                \/\/ \u5982\u679c\u4e0d\u591f\uff0c\u5c31\u5c06\u6570\u636e\u653e\u5728cache\u4e2d\r\n\r\n                socketRead(2);\r\n                if (socketError != SocketError.Success)\r\n                {\r\n                    return null;\r\n                }\r\n\r\n                length = readUshort();\r\n\r\n                if (length == 0)\r\n                {\r\n                    socketRead(4);\r\n                    if (socketError != SocketError.Success)\r\n                    {\r\n                        return null;\r\n                    }\r\n                    length = readInt();\r\n                }\r\n                int socketAvailable = socket.Available;\r\n                needRead = length;\r\n                if (socketAvailable &lt; needRead)\r\n                {\r\n                    \/\/ \u4e0d\u8db3\u65f6\uff0csocket\u6709\u591a\u5c11\u7f13\u5b58\u6570\u636e\u5c31\u8bfb\u591a\u5c11\r\n                    socketRead(socketAvailable);\r\n                    if (socketError != SocketError.Success)\r\n                    {\r\n                        return null;\r\n                    }\r\n\r\n                    needRead = needRead - socketAvailable;\r\n                    return null;\r\n                }\r\n                else\r\n                {\r\n                    \/\/ \u6570\u636e\u8db3\u591f\uff0c\u89e3\u6790\u6570\u636e\r\n                    socketRead(needRead);\r\n                    if (socketError != SocketError.Success)\r\n                    {\r\n                        return null;\r\n                    }\r\n                    return readMsg();\r\n                }\r\n            }\r\n            else\r\n            {\r\n                \/\/ \u7ee7\u7eed\u4ecesocket\u4e2d\u63a5\u6536\u6570\u636e\r\n                int socketAvailable = socket.Available;\r\n                if (socketAvailable &lt; needRead)\r\n                {\r\n                    \/\/ \u6570\u636e\u4f9d\u65e7\u4e0d\u8db3\r\n                    socketRead(socketAvailable);\r\n                    if (socketError != SocketError.Success)\r\n                    {\r\n                        return null;\r\n                    }\r\n\r\n                    needRead = needRead - socketAvailable;\r\n                    return null;\r\n                }\r\n                else\r\n                {\r\n                    \/\/ \u6570\u636e\u8db3\u591f\uff0c\u89e3\u6790\u6570\u636e\r\n                    socketRead(needRead);\r\n                    if (socketError != SocketError.Success)\r\n                    {\r\n                        return null;\r\n                    }\r\n\r\n                    return readMsg();\r\n                }\r\n            }\r\n        }\r\n        return null;\r\n    }\r\n\r\n    private void readReset()\r\n    {\r\n        \/\/ \u8bfb\u5165\u4e00\u4e2a\u5b8c\u6574\u6d88\u606f\u540e\uff0c\u91cd\u7f6e\u6570\u636e\r\n        available = 0;\r\n        readBufIndex = 0;\r\n        length = 0;\r\n        needRead = 0;\r\n    }\r\n    private NetMsg readMsg()\r\n    {\r\n        NetMsg netMsg = new NetMsg();\r\n\r\n        UInt32 loop = readUInt();\r\n        short cmdId = readShort();\r\n\r\n        byte[] protoData = null;\r\n        if (cmdId &gt; 0)\r\n        {\r\n            protoData = new byte[length - 10];\r\n            Array.Copy(readBuf, readBufIndex, protoData, 0, length - 10);\r\n        }\r\n        else\r\n        {\r\n            \/\/ \u6709\u538b\u7f29\r\n            MemoryStream inms = new MemoryStream(readBuf, readBufIndex, length - 10);\r\n            MemoryStream outms = new MemoryStream();\r\n            SevenZipTool.Unzip(inms, outms);\r\n            protoData = outms.ToArray();\r\n            cmdId = (short)-cmdId;\r\n        }\r\n        \r\n\r\n        netMsg.loop = loop;\r\n        netMsg.cmdType = (cmd.CmdType)cmdId;\r\n        netMsg.data = protoData;\r\n        netMsg.netdata=new MemoryStream(protoData);\r\n        readReset();\r\n        return netMsg;\r\n    }\r\n\r\n    private short readShort()\r\n    {\r\n        short ret = BitConverter.ToInt16(readBuf, readBufIndex);\r\n        readBufIndex += 2;\r\n        return Endian.SwapInt16(ret);\r\n    }\r\n    private ushort readUshort()\r\n    {\r\n        ushort ret = BitConverter.ToUInt16(readBuf, readBufIndex);\r\n        readBufIndex += 2;\r\n        return Endian.SwapUInt16(ret);\r\n    }\r\n\r\n    private int readInt()\r\n    {\r\n        int ret = BitConverter.ToInt32(readBuf, readBufIndex);\r\n        readBufIndex += 4;\r\n        return Endian.SwapInt32(ret);\r\n    }\r\n\r\n    private uint readUInt()\r\n    {\r\n        uint ret = BitConverter.ToUInt32(readBuf, readBufIndex);\r\n        readBufIndex += 4;\r\n        return Endian.SwapUInt32(ret);\r\n\r\n    }\r\n    private void socketRead(int readLen)\r\n    {    \/\/\u4ecesocket\u4e2d\u8bfb\u5165\u6570\u636e\u5165\u5728readBuf\u4e2d\r\n        socket.Receive(readBuf, available, readLen, SocketFlags.None, out socketError);\r\n        if (socketError != SocketError.Success)\r\n        {\r\n            Debug.LogError(&quot;socket Read error:&quot; + socketError);\r\n        }\r\n        available += readLen;\r\n    }\r\n\r\n    public int send(NetMsg netMsg, int offset)\r\n    {\r\n        if (netMsg.totalData == null)\r\n        {\r\n            encode(netMsg);\r\n        }\r\n\r\n        int sendNum = socket.Send(netMsg.totalData, offset, netMsg.totalData.Length - offset, SocketFlags.None, out socketError);\r\n        if (socketError != SocketError.Success)\r\n        {\r\n            Debug.LogError(&quot;socket send error:&quot; + socketError);\r\n            return 0;\r\n        }\r\n\r\n        if (sendNum + offset == netMsg.totalData.Length)\r\n        {\r\n            return -1;\/\/\u6807\u5fd7\uff0c\u5168\u90e8\u53d1\u9001\u5b8c\u6210\r\n        }\r\n        return sendNum;\r\n    }\r\n\r\n\r\n    private void encode(NetMsg netMsg)\r\n    {\r\n        MemoryStream outstream = new MemoryStream();\r\n        byte[] _t = null;\r\n\r\n        int totalLength = netMsg.data.Length + 10;\r\n        if (totalLength &gt; 65535)\r\n        {\r\n            _t = BitConverter.GetBytes(Endian.SwapInt16((short)0));\r\n            outstream.Write(_t, 0, _t.Length);\r\n            _t = BitConverter.GetBytes(Endian.SwapInt32(totalLength));\r\n            outstream.Write(_t, 0, _t.Length);\r\n        }\r\n        else\r\n        {\r\n            _t = BitConverter.GetBytes(Endian.SwapInt16((short)totalLength));\r\n            outstream.Write(_t, 0, _t.Length);\r\n        }\r\n\r\n        _t = BitConverter.GetBytes(Endian.SwapUInt32(netMsg.loop));\r\n        outstream.Write(_t, 0, _t.Length);\r\n        _t = BitConverter.GetBytes(Endian.SwapInt16((short)netMsg.cmdType));\r\n        outstream.Write(_t, 0, _t.Length);\r\n        outstream.Write(netMsg.data, 0, netMsg.data.Length);\r\n        _t = BitConverter.GetBytes(Endian.SwapInt32((int)0));\r\n        outstream.Write(_t, 0, _t.Length);\r\n\r\n        _t = outstream.ToArray();\r\n        netMsg.totalData = _t;\r\n    }\r\n\r\n    public bool isConnected()\r\n    {\r\n        return socket != null &amp;&amp; (socket.Connected);\r\n    }\r\n}<\/pre>\n<pre class=\"brush: bash; gutter: true\">\/\/----------------------------------------------\r\n\/\/           NET        : NetManager\r\n\/\/           AUTHOR: zhu kun qian\r\n\/\/----------------------------------------------\r\n\r\nusing System;\r\nusing System.Linq;\r\nusing System.Net.Sockets;\r\n\r\nusing UnityEngine;\r\nusing System.Collections.Generic;\r\nusing System.IO;\r\n\r\n\r\npublic class NetManager\r\n{\r\n    public uint loop;\/\/ \u6c38\u4e0d\u91cd\u590d\uff0c\u4e00\u76f4\u52a01\r\n\r\n    public string ip = &quot;&quot;;\r\n    public int port = 0;\r\n\r\n    private NetManagerSocket socket = null;\r\n\r\n    private int maxQuerySize = 100;\/\/\u63a5\u6536\u548c\u53d1\u9001\u6700\u591acache 100\u6761\u6d88\u606f\r\n    private int maxReconnectTimes = 3;\/\/\u91cd\u8fde\u6700\u591a\u91cd\u8bd53\u6b21\r\n\r\n    \/\/ \u53d1\u9001\u76f8\u5173\r\n    public Queue&lt;NetMsg&gt; msgQuery = new Queue&lt;NetMsg&gt;(); \/\/ \u53d1\u9001\u6d88\u606f\u961f\u5217\r\n    public NetMsg reconnectTokenLogin = null;\/\/\u91cd\u8fde\u53d1\u9001\u7684\u767b\u9646\u6d88\u606f\r\n    public bool loginSuccess = false;\r\n\r\n    private int sendBytes = 0;\r\n    private float sendBytesTimeout = 0f; \/\/ \u53d1\u9001\u6d88\u606f\u8d85\u65f6\r\n\r\n    \/\/ \u63a5\u6536\u7684\u6d88\u606f\u961f\u5217\r\n    private Queue&lt;NetMsg&gt; receviedMsgQueue = new Queue&lt;NetMsg&gt;();\/\/ \u4ece\u670d\u52a1\u5668\u63a5\u6536\u5230\u7684\u6d88\u606f\r\n\r\n    private int reconnectTryTimes = 0; \/\/ \u91cd\u8fde\u6b21\u6570\r\n    private float connectTimeout = 0f; \/\/ \u8fde\u63a5\u8d85\u65f6\r\n    public EventDelegate.Callback reconnectErrorCallback; \/\/ \u5982\u679c\u51fa\u73b0\u5185\u90e8\u65e0\u6cd5\u5904\u7406\u7684\u5f97\u8fde(1\u3001\u8fde\u8bd53\u6b21\u65e0\u6cd5\u91cd\u8fde\u6210\u529f 2\u3001\u7d2f\u79ef\u7684\u6d88\u606f\u6570\u91cf\u8fc7\u91cf\uff0c\u9700\u8981\u91cd\u542f\u6e38\u620f\u5ba2\u6237\u7aef)\r\n    \r\n\r\n    \/\/ \u5982\u679c\u65ad\u7ebf\u540e\uff0c\u662f\u4f7f\u7528\u539fsocket\u91cd\u8fde\uff0c\u8fd8\u662f\u4f7f\u7528\u65b0\u7684socket?\u65b0new\u51fa\u6765\r\n    public static NetManager Instance = null;\r\n    public NetManager()\r\n    {\r\n        Instance = this;\r\n    }\r\n\r\n    public bool isConnected()\r\n    {\r\n        return socket != null &amp;&amp; socket.isConnected();\r\n    }\r\n    public void connect()\r\n    {\r\n        if (socket != null)\r\n        {\r\n            Debug.LogError(&quot;socket is not closed,try close&quot;);\r\n            socket.disconnect();\r\n        }\r\n\r\n        Debug.Log(&quot;start connect ip:&quot; + ip + &quot; port:&quot; + port);\r\n\r\n        socket = new NetManagerSocket();\r\n        socket.ip = ip;\r\n        socket.port = port;\r\n        socket.connect();\r\n\r\n        sendBytes = 0;\r\n        sendBytesTimeout = 0f;\r\n\r\n        connectTimeout = 0f;\r\n    }\r\n\r\n    public void disconnect()\r\n    {\r\n        if (socket == null)\r\n        {\r\n            Debug.LogError(&quot;socket is null&quot;);\r\n            return;\r\n        }\r\n        socket.disconnect();\r\n        socket = null;\r\n    }\r\n\r\n    public void onUpdate()\r\n    {\r\n        \/\/ \u6bcf\u796f\u6267\u884c\uff0c\u6ca1\u6709\u963b\u585e\r\n        if (socket != null)\r\n        {\r\n            \/\/ \u6539\u4e3a\u5728socket\u4e2d\u5904\u7406\u5462\r\n            if (socket.socketError != SocketError.Success)\r\n            {\r\n                \/\/ \u5982\u679c\u9047\u5230sokcet\u9519\u8bef\uff0c\u4e0d\u9700\u8981\u7b49\u7b49\u8d85\u65f6\uff0c\u7acb\u5373\u91cd\u8fde\r\n                Debug.LogError(&quot;socket error:&quot; + socket.socketError);\r\n                tryReconnect();\r\n                return;\r\n            }\r\n\r\n            if (socket.isConnected())\r\n            {\r\n                NetMsg msg = socket.read();\r\n                if (msg != null)\r\n                {\r\n                    receviedMsgQueue.Enqueue(msg);\r\n                }\r\n                NetMsg netMsg = null;\r\n                if (reconnectTokenLogin != null)\r\n                {\r\n                    netMsg = reconnectTokenLogin;\r\n                }\r\n                else\r\n                {\r\n                    if (loginSuccess)\r\n                    {\r\n                        lock (msgQuery)\r\n                        {\r\n                            if (msgQuery.Count &gt; 0)\r\n                            {\r\n                                netMsg = msgQuery.First();\r\n                            }\r\n                        }\r\n                    }\r\n                }\r\n                if (netMsg != null)\r\n                {\r\n                    socketSend(netMsg);\r\n                }\r\n            }\r\n            else\r\n            {\r\n                if (connectTimeout == 0f)\r\n                {\r\n                    connectTimeout = Time.realtimeSinceStartup;\r\n                }\r\n                else if (Time.realtimeSinceStartup - connectTimeout &gt; 5)\r\n                {\r\n                    \/\/ \u8fde\u63a55\u79d2\u8d85\u65f6\uff0c\u5904\u7406\u91cd\u8fde\r\n                    tryReconnect();\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    private void tryReconnect()\r\n    {\r\n        if (reconnectTryTimes &gt;= 3)\r\n        {\r\n            \/\/ \u8df3\u51fa\u9519\u8bef\u5904\u7406\u56de\u8c03\uff0c\u4ea4\u7ed9\u5916\u90e8\u5904\u7406\r\n            if (reconnectErrorCallback != null)\r\n            {\r\n                reconnectErrorCallback();\r\n            }\r\n            disconnect();\r\n            return;\r\n        }\r\n        Debug.LogError(&quot;socket connect timeout, try reconnect:&quot; + reconnectTryTimes + &quot; &quot; + socket.socketError);\r\n        reconnectTryTimes++;\r\n        disconnect();\r\n        connect();\r\n        \/\/ \u91cd\u8bd5\u9700\u8981\uff0c\u91cd\u65b0\u53d1\u9001\u767b\u9646\u6d88\u606f505\r\n        LoginState.Instance.loginWithTokenSub(true);\r\n\r\n    }\r\n\r\n    public NetMsg readMsg()\r\n    {\r\n        if (receviedMsgQueue.Count == 0)\r\n        {\r\n            return null;\r\n        }\r\n        return receviedMsgQueue.Dequeue();\r\n    }\r\n\r\n    \/\/ true:\u8d85\u65f6\r\n    private void socketSend(NetMsg netMsg)\r\n    {\r\n        \/\/ \u53d1\u9001\u6570\u636e\r\n        bool newMsg = false;\/\/ \u65b0\u53d1\u9001\u7684\u6d88\u606f\r\n        if (sendBytes == 0)\r\n        {\r\n            newMsg = true;\r\n\r\n        }\r\n        int num = socket.send(netMsg, sendBytes);\r\n        if (num &gt; 0)\r\n        {\r\n            sendBytes += num;\r\n        }\r\n        if (num == -1)\r\n        {\r\n            \/\/ \u5168\u90e8\u53d1\u9001\u5b8c\u6210\r\n            if (cmd.CmdType.tokenLogin == netMsg.cmdType)\r\n            {\r\n                reconnectTokenLogin = null;\r\n            }\r\n            else\r\n            {\r\n                lock (msgQuery)\r\n                {\r\n                    msgQuery.Dequeue();\r\n                }\r\n            }\r\n            sendBytes = 0;\r\n            sendBytesTimeout = 0f;\r\n        }\r\n        else\r\n        {\r\n            \/\/ \u672a\u53d1\u9001\u5b8c\u6210,\u5904\u7406\u8d85\u65f6\u903b\u8f91\r\n            if (newMsg)\r\n            {\r\n                sendBytesTimeout = Time.realtimeSinceStartup;\r\n            }\r\n            else\r\n            {\r\n                \/\/ \u68c0\u67e5\u65f6\u95f4\u662f\u5426\u8d85\u65f6\r\n                if (Time.realtimeSinceStartup - sendBytesTimeout &gt; 5)\r\n                {\r\n                    \/\/ \u8d85\u8fc75\u79d2\r\n                    Debug.LogError(&quot;socket timeout.try reconnect&quot;);\r\n                    \/\/ \u91cd\u8fde\u91cd\u53d1\r\n                    if (socket.socketError != SocketError.Success)\r\n                    {\r\n                        Debug.LogError(&quot;socket error:&quot; + socket.socketError);\r\n                    }\r\n                    socket.socketError = SocketError.TimedOut;\r\n                }\r\n            }\r\n        }\r\n    }\r\n\r\n    public void SendCmd&lt;T&gt;(cmd.CmdType cmdType, T protoObj)\r\n    {\r\n        send(cmdType,protoObj);\r\n    }\r\n    public void send&lt;T&gt;(cmd.CmdType cmdType, T protoObj)\r\n    {\r\n        NetMsg netMsg = new NetMsg();\r\n        netMsg.loop = ++loop;\r\n        netMsg.cmdType = cmdType;\r\n\r\n        MemoryStream outms = new MemoryStream();\r\n        ProtoBuf.Serializer.Serialize(outms, protoObj);\r\n        netMsg.data = outms.ToArray();\r\n\r\n        \/\/ todo:\u56e0\u4e3a\u653e\u5728onupdate\u4e2d\uff0c\u611f\u89c9\u8fd9\u4e2alock\u4e5f\u662f\u53ef\u4ee5\u907f\u514d\u6389\u7684\u3002\u6682\u65f6\u5148\u52a0\u4e0a\uff0c\u4ee5\u540e\u6d4b\u8bd5\u540e\u518d\u8003\u8651\u53bb\u6389\u3002\r\n        \/\/ \u53ea\u8981\u80fd\u786e\u8ba4\u4e0d\u4f1a\u591a\u7ebf\u7a0b\u64cd\u4f5c\uff0c\u5c31\u53ef\u4ee5\u53bb\u6389\u8fd9\u4e2alock\r\n        if (cmdType == cmd.CmdType.tokenLogin)\r\n        {\r\n            reconnectTokenLogin = netMsg;\r\n            loginSuccess = false;\r\n            return;\r\n        }\r\n        lock (msgQuery)\r\n        {\r\n            msgQuery.Enqueue(netMsg);\r\n            \/\/ \u5728onupdate\u4e2d\u53d1\u9001\uff0c\u8fd9\u6837\u53ea\u5dee3ms\uff0c\u662f\u53ef\u4ee5\u63a5\u53d7\u7684\r\n        }\r\n\r\n        if (msgQuery.Count &gt; maxQuerySize)\r\n        {\r\n            Debug.LogError(&quot;msgQuery more than max size:&quot; + msgQuery.Count);\r\n        }\r\n    }\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n<\/pre>\n<p>2015.01.19\u8bb0\uff1a\u6211\u91cd\u6784\u65f6\uff0c\u672a\u6dfb\u52a0\u65ad\u7ebf\u8865\u53d1\u672a\u9001\u8fbe\u7684\u6d88\u606f\uff0c\u6211\u4eec\u5ba2\u6237\u7aef\u5199\u7684\u903b\u8f91\u4e0d\u4e25\u8c28\uff0c\u5728\u767b\u9646\u6e38\u620f\u6309\u94ae\u4e0a\u8fde\u7eed\u591a\u6b21\u70b9\u51fb\uff0c\u4f1a\u5bfc\u81f4\u5361\u4f4f\u767b\u9646\u3002\u6211\u8fd9\u91cc\u53ea\u662f\u4f7f\u7528\u7981\u6b62\u591a\u6b21\u70b9\u51fb\u6765\u907f\u514d\u8fd9\u4e2a\u95ee\u9898\uff0c\u5982\u679c\u4f7f\u7528\u6709\u65ad\u7ebf\u8865\u53d1\u672a\u9001\u8fbe\u7684\u6d88\u606f\u4e5f\u53ef\u4ee5\u4e0d\u4f1a\u51fa\u73b0\u8fd9\u4e2a\u95ee\u9898\u3002\u603b\u4e4b\uff0c\u4e0d\u8981\u4f9d\u8d56\u5ba2\u6237\u7aef\u4ee3\u7801\u5f88\u5f3a\u58ee\uff0c\u6700\u597d\u8fd8\u662f\u6dfb\u52a0\u4e0a\u65ad\u7ebf\u8865\u53d1\u6d88\u606f\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u6211\u4eec\u6e38\u620f\u4e2d\u65ad\u7ebf\u548c\u8d85\u65f6\u8fd9\u4e00\u5757\u51fa\u95ee\u9898\u975e\u5e38\u591a\u3002 \u8fd9\u4e00\u6b21\u6211\u4e13\u95e8\u62bd\u51fa\u4e86\u4e00\u5468\u65f6\u95f4\uff0c\u4e86\u89e3\u4e86\u4e0bc &hellip;<\/p>\n<p class=\"read-more\"><a href=\"https:\/\/blog.zhukunqian.com\/?p=1113\">\u7ee7\u7eed\u9605\u8bfb &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.zhukunqian.com\/index.php?rest_route=\/wp\/v2\/posts\/1113"}],"collection":[{"href":"https:\/\/blog.zhukunqian.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.zhukunqian.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.zhukunqian.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.zhukunqian.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1113"}],"version-history":[{"count":3,"href":"https:\/\/blog.zhukunqian.com\/index.php?rest_route=\/wp\/v2\/posts\/1113\/revisions"}],"predecessor-version":[{"id":1116,"href":"https:\/\/blog.zhukunqian.com\/index.php?rest_route=\/wp\/v2\/posts\/1113\/revisions\/1116"}],"wp:attachment":[{"href":"https:\/\/blog.zhukunqian.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1113"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.zhukunqian.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1113"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.zhukunqian.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1113"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}