public void GetHostEntryCallback(IAsyncResult ar)
        {
            DNSCbContext ct         = (DNSCbContext)ar.AsyncState;
            IPHostEntry  ipHostInfo = Dns.EndGetHostEntry(ar);
            IPAddress    ipAddress  = ipHostInfo.AddressList[0];

            DNSCache.GetInstence().Put(ct.host, ipAddress);
            IPEndPoint remoteEP = new IPEndPoint(ipAddress, ct.port);

            remote = new Socket(ipAddress.AddressFamily,
                                SocketType.Stream, ProtocolType.Tcp);

            remote.BeginConnect(remoteEP,
                                new AsyncCallback(remoteConnectCallback), null);
        }
        private void handshakeReceiveCallback(IAsyncResult ar)
        {
            try
            {
                int bytesRead = connection.EndReceive(ar);
                //Console.WriteLine("bytesRead" + bytesRead.ToString() + " stage" + stage.ToString());
                if (stage == 0)
                {
                    //recv numbers of ivlen data
                    byte[] iv = encryptor.Decrypt(this.connetionBuffer, bytesRead);
                    //Decrypt sucessful
                    //iv
                    stage = 1;
                    connection.BeginReceive(this.connetionBuffer, 0, 1, 0,
                                            new AsyncCallback(handshakeReceiveCallback), null);
                }
                else if (stage == 1)
                {
                    byte[] buff = encryptor.Decrypt(this.connetionBuffer, bytesRead);
                    //Decrypt sucessful
                    //addrtype
                    char addrtype = (char)buff[0];
                    if (addrtype == 1)
                    {
                        //type of ipv4
                        stage = 4;
                        connection.BeginReceive(this.connetionBuffer, 0, 4, 0,
                                                new AsyncCallback(handshakeReceiveCallback), null);
                    }
                    else if (addrtype == 3)
                    {
                        //type of url
                        stage = 3;
                        connection.BeginReceive(this.connetionBuffer, 0, 1, 0,
                                                new AsyncCallback(handshakeReceiveCallback), null);
                    }
                    else if (addrtype == 4)
                    {
                        //type of ipv6
                        stage = 4;
                        connection.BeginReceive(this.connetionBuffer, 0, 16, 0,
                                                new AsyncCallback(handshakeReceiveCallback), null);
                    }
                    else
                    {
                        throw new Exception("Error Socket5 AddrType");
                    }
                }
                else if (stage == 3)
                {
                    //addr len
                    byte[] buff = encryptor.Decrypt(this.connetionBuffer, bytesRead);
                    stage = 4;
                    //recv addr
                    connection.BeginReceive(this.connetionBuffer, 0, buff[0], 0,
                                            new AsyncCallback(handshakeReceiveCallback), null);
                }
                else if (stage == 4)
                {
                    //addr
                    byte[] buff = encryptor.Decrypt(this.connetionBuffer, bytesRead);
                    destAddr = ASCIIEncoding.Default.GetString(buff);
                    stage    = 5;
                    connection.BeginReceive(this.connetionBuffer, 0, 2, 0,
                                            new AsyncCallback(handshakeReceiveCallback), null);
                }
                else if (stage == 5)
                {
                    //port
                    byte[] buff = encryptor.Decrypt(this.connetionBuffer, bytesRead);
                    int    port = (int)(buff[0] << 8) + (int)buff[1];

                    stage = 6;

                    //Begin to connect remote
                    IPAddress ipAddress;
                    bool      parsed = IPAddress.TryParse(destAddr, out ipAddress);
                    if (!parsed)
                    {
                        IPAddress cache_ipAddress = DNSCache.GetInstence().Get(destAddr);
                        if (cache_ipAddress == null)
                        {
                            DNSCbContext ct = new DNSCbContext(destAddr, port);
                            Dns.BeginGetHostEntry(destAddr, new AsyncCallback(GetHostEntryCallback), ct);
                            return;
                        }
                        ipAddress = cache_ipAddress;
                    }

                    IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);

                    remote = new Socket(ipAddress.AddressFamily,
                                        SocketType.Stream, ProtocolType.Tcp);

                    remote.BeginConnect(remoteEP,
                                        new AsyncCallback(remoteConnectCallback), null);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                this.Close();
            }
        }