private void readCallback(IAsyncResult ar)
        {
            //The callback messages
            object[] messages = (object[])ar.AsyncState;

            //The channel
            ConnectionChannel channel = (ConnectionChannel)messages[0];

            //The packet
            Packet packet = (Packet)messages[1];

            try {
                //If we are unable to poll the channel's socket, it must be terminated
                if (channel.getSocket().Poll(1000, SelectMode.SelectRead))
                {
                    channel.getPipeline().getHandler().connectionTerminated(channel);
                    connectedChannels.Remove(channel);
                    return;
                }

                //Send the packet to the channel's decoder
                channel.getPipeline().getHandler().messageReceived(channel, channel.getPipeline().getDecoder().decode(channel, packet));

                //Await another packet
                channel.getSocket().BeginReceive(packet.getPayload(), 0, packet.getPayload().Length, 0, new AsyncCallback(readCallback), new object[] { channel, packet });
            } catch (Exception e) {
                //Send the exception to the channel's handler
                channel.getPipeline().getHandler().exceptionCaught(channel, e);
            }
        }