/// <summary>
        /// Send given packet to the client
        /// </summary>
        /// <param name="packet">the packet to send</param>
        public void Send(Packet packet)
        {
            if (!IsConnectionAlive)
            {
                Task t = new Task(delegate()
                {
                    OnSent(this, SendStatus.FAIL_NOT_CONNECTED, packet);
                });
                t.Start();

                return;
            }
            if (packet.PacketByteSize <= 0)
            {
                Task t = new Task(delegate()
                {
                    OnSent(this, SendStatus.FAIL_INVALID_PACKET, packet);
                });
                t.Start();

                return;
            }

            lock (m_sendLock)
            {
                Packet            sendSizePacket = new Packet(null, 0, Preamble.SIZE_PACKET_LENGTH, false);
                PacketTransporter transport      = new PacketTransporter(PacketType.SIZE, sendSizePacket, 0, Preamble.SIZE_PACKET_LENGTH, this, packet);

                //sendSizePacket.SetPacket(BitConverter.GetBytes(packet.GetPacketByteSize()), 4);
                sendSizePacket.SetPacket(Preamble.ToPreamblePacket(packet.PacketByteSize), 0, Preamble.SIZE_PACKET_LENGTH);
                if (m_sendEvent.TryLock())
                {
                    try { m_client.Client.BeginSend(sendSizePacket.PacketRaw, 0, Preamble.SIZE_PACKET_LENGTH, SocketFlags.None, new AsyncCallback(IocpTcpSocket.onSent), transport); }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message + " >" + ex.StackTrace);
                        Disconnect();
                        return;
                    }
                }
                else
                {
                    lock (m_sendQueueLock)
                    {
                        m_sendQueue.Enqueue(transport);
                    }
                }
            }
        }
        /// <summary>
        /// Receive callback function
        /// </summary>
        /// <param name="result">result</param>
        private static void onReceived(IAsyncResult result)
        {
            PacketTransporter transport = result.AsyncState as PacketTransporter;
            Socket            socket    = transport.m_iocpTcpClient.m_client.Client;

            int readSize = 0;

            try { readSize = socket.EndReceive(result); }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + " >" + ex.StackTrace);
                transport.m_iocpTcpClient.Disconnect(); return;
            }
            if (readSize == 0)
            {
                transport.m_iocpTcpClient.Disconnect();
                return;
            }
            if (readSize < transport.m_size)
            {
                transport.m_offset = transport.m_offset + readSize;
                transport.m_size   = transport.m_size - readSize;
                try{ socket.BeginReceive(transport.m_packet.PacketRaw, transport.m_offset, transport.m_size, SocketFlags.None, new AsyncCallback(IocpTcpClient.onReceived), transport); }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message + " >" + ex.StackTrace);
                    transport.m_iocpTcpClient.Disconnect(); return;
                }
            }
            else
            {
                if (transport.m_packetType == PacketType.SIZE)
                {
                    //int shouldReceive = BitConverter.ToInt32(transport.m_packet.PacketRaw, 0);
                    int shouldReceive = Preamble.ToShouldReceive(transport.m_packet.PacketRaw);

                    // preamble packet is corrupted
                    // try to receive another byte to check preamble
                    if (shouldReceive < 0)
                    {
                        int preambleOffset = Preamble.CheckPreamble(transport.m_packet.PacketRaw);
                        // set offset to length - preamble offset
                        transport.m_offset = transport.m_packet.PacketByteSize - preambleOffset;
                        // need to receive as much as preamble offset
                        transport.m_size = preambleOffset;
                        try
                        {
                            // shift to left by preamble offset
                            Buffer.BlockCopy(transport.m_packet.PacketRaw, preambleOffset, transport.m_packet.PacketRaw, 0, transport.m_packet.PacketByteSize - preambleOffset);
                            // receive rest of bytes at the end
                            socket.BeginReceive(transport.m_packet.PacketRaw, transport.m_offset, transport.m_size, SocketFlags.None, new AsyncCallback(IocpTcpClient.onReceived), transport);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message + " >" + ex.StackTrace);
                            transport.m_iocpTcpClient.Disconnect(); return;
                        }
                        return;
                    }
                    Packet            recvPacket    = new Packet(null, 0, shouldReceive);
                    PacketTransporter dataTransport = new PacketTransporter(PacketType.DATA, recvPacket, 0, shouldReceive, transport.m_iocpTcpClient);
                    try { socket.BeginReceive(recvPacket.PacketRaw, 0, shouldReceive, SocketFlags.None, new AsyncCallback(IocpTcpClient.onReceived), dataTransport); }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message + " >" + ex.StackTrace);
                        transport.m_iocpTcpClient.Disconnect(); return;
                    }
                }
                else
                {
                    PacketTransporter sizeTransport = new PacketTransporter(PacketType.SIZE, transport.m_iocpTcpClient.m_recvSizePacket, 0, Preamble.SIZE_PACKET_LENGTH, transport.m_iocpTcpClient);
                    try { socket.BeginReceive(sizeTransport.m_packet.PacketRaw, 0, Preamble.SIZE_PACKET_LENGTH, SocketFlags.None, new AsyncCallback(IocpTcpClient.onReceived), sizeTransport); }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message + " >" + ex.StackTrace);
                        transport.m_iocpTcpClient.Disconnect(); return;
                    }
                    transport.m_iocpTcpClient.OnReceived(transport.m_iocpTcpClient, transport.m_packet);
                }
            }
        }