Example #1
0
    public void Worker()
    {
        IPAddress addr   = null;
        bool      isIPV6 = false;

        if (IPAddress.TryParse(ip, out addr))
        {
//			isIPV6 = AppEnv.IsInIPV6;
        }
        else
        {
            // 域名,需要dns解析出ip
            IPHostEntry ipHost = Dns.GetHostEntry(ip);
            if (ipHost.AddressList.Length > 0)
            {
                addr = ipHost.AddressList[0];
                var nameType = Uri.CheckHostName(addr.ToString());
                isIPV6 = nameType == UriHostNameType.IPv6;
            }
            else
            {
                State = SocketConnectionState.Closed;
                Debug.LogError("# dns parse error");
                return;
            }
        }

        IPEndPoint ipe = new IPEndPoint(addr, port);

        Socket socket = new Socket(isIPV6 ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
        socket.NoDelay        = true;
        socket.SendBufferSize = 1024 * 32;
        socket.SendTimeout    = 10 * 1000;      //10s
        socket.Blocking       = true;

        State = SocketConnectionState.Connecting;

        int startTick = Environment.TickCount;

        do
        {
            try
            {
                // 重试30s
                int nowTick = Environment.TickCount;
                if (nowTick - startTick >= 30000)
                {
                    break;
                }

                socket.Connect(ipe);

                if (socket.Connected)
                {
                    State = SocketConnectionState.Connected;
                    Debug.Log("# Socket Connected Success");

                    OnConnectionSuccess(new EventArgs());

                    break;
                }
            }
            catch (SocketException ex)
            {
                // 什么都不做,因为要反复的重新connect
            }
            catch (Exception ex)
            {
            }
        }while(true);

        if (State != SocketConnectionState.Connected)
        {
            State = SocketConnectionState.Closed;
            Debug.Log("# Socket connect failed");

            OnConnectionFailed(new EventArgs());
            return;
        }

        //Read & Write
        while (true)
        {
            if (mainThreadCloseSocket)
            {
                // 主线程关闭, 调用socketmgr的close接口会触发
                break;
            }

            try
            {
                //Read
                while (socket.Poll(10, SelectMode.SelectRead))
                {
                    int         recvSize = 0;
                    SocketError sock_err = SocketError.Success;
                    recvSize = socket.Receive(_recvBytes, 0, _recvBytes.Length, SocketFlags.None, out sock_err);

                    if (sock_err == SocketError.Success && recvSize > 0)
                    {
                        _recvBuf.Write(_recvBytes, recvSize);
                    }
                    else if (sock_err == SocketError.Success && recvSize == 0)
                    {
                        // 服务器断开连接,或者客户端拔网线,切网络之类的
                        throw new Exception("server disconnect or client timeout!");
                    }
                    else if (sock_err == SocketError.WouldBlock ||
                             sock_err == SocketError.IOPending ||
                             sock_err == SocketError.NoBufferSpaceAvailable)
                    {
                        Debug.LogError("socket woold block " + sock_err.ToString());

                        continue;
                    }
                    else if (sock_err == SocketError.TimedOut)
                    {
                        Debug.LogError("socket receive timeout");
                        continue;
                    }
                    else
                    {
                        throw new Exception("Socket Receive " + recvSize + " bytes, SocketError " + sock_err);
                    }
                }

                _recvBuf.DeserializeBuffer();

                //Write
                UpdateSendBuf();
                if (socket.Poll(10, SelectMode.SelectWrite))
                {
                    byte[] msg = _sendBuf.Read();

                    if (null != msg && msg.Length != 0)
                    {
                        int msgLen = msg.Length;
                        int sent   = 0;

                        while (sent < msgLen)
                        {
                            SocketError sock_err = SocketError.Success;
                            int         size     = socket.Send(msg, sent, msgLen - sent, SocketFlags.None, out sock_err);

                            if (sock_err == SocketError.Success && size > 0)
                            {
                                sent += size;
                            }
                            else if (sock_err == SocketError.WouldBlock ||
                                     sock_err == SocketError.IOPending ||
                                     sock_err == SocketError.NoBufferSpaceAvailable)
                            {
                                continue;
                            }
                            else
                            {
                                throw new Exception("Socket Send " + size + " bytes, SocketError " + sock_err);
                            }
                        }
                    }
                }
            }
            catch (SocketException ex)
            {
                Debug.LogError(ex);
                break;
            }
            catch (Exception ex)
            {
                Debug.LogError(ex);
                break;
            }

            Thread.Sleep(10);
        }

        //Close
        try
        {
            if (socket.Connected)
            {
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
            }
        }
        catch (Exception ex)
        {
            Debug.LogError(ex);
        }

        // 最后无论怎样都设置socket 关闭的状态
        State = SocketConnectionState.Closed;

        OnConnectionLost(new EventArgs());
        Debug.Log("# Socket Thread Close");
    }