/// <summary>
        /// Send the specified datagram.
        /// </summary>
        public void Send(Buffer buffer, IPEndPoint ip)
        {
            if (ip.Address.Equals(IPAddress.Broadcast))
            {
            Broadcast(buffer, ip.Port);
            return;
            }

            buffer.MarkAsUsed();

            if (mSocket != null)
            {
            buffer.BeginReading();

            lock (mOut)
            {
                Datagram dg = new Datagram();
                dg.buffer = buffer;
                dg.ip = ip;
                mOut.Enqueue(dg);

                if (mOut.Count == 1)
                {
                    // If it's the first datagram, begin the sending process
                    mSocket.BeginSendTo(buffer.buffer, buffer.position, buffer.size,
                        SocketFlags.None, ip, OnSend, null);
                }
            }
            }
            else
            {
            buffer.Recycle();
            throw new InvalidOperationException("The socket is null. Did you forget to call UdpProtocol.Start()?");
            }
        }
        /// <summary>
        /// Receive incoming data.
        /// </summary>
        void OnReceive(IAsyncResult result)
        {
            if (!isActive) return;
            int bytes = 0;

            try
            {
            bytes = mSocket.EndReceiveFrom(result, ref mEndPoint);
            }
            catch (System.Exception ex)
            {
            Error(new IPEndPoint(Tools.localAddress, 0), ex.Message);
            }

            if (bytes > 4)
            {
            // This datagram is now ready to be processed
            Buffer buffer = Buffer.Create();
            buffer.BeginWriting(false).Write(mTemp, 0, bytes);
            buffer.BeginReading(4);

            // The 'endPoint', gets reassigned rather than updated.
            Datagram dg = new Datagram();
            dg.buffer = buffer;
            dg.ip = (IPEndPoint)mEndPoint;
            lock (mIn) mIn.Enqueue(dg);
            }

            // Queue up the next receive operation
            if (mSocket != null)
            {
            mEndPoint = mDefaultEndPoint;
            mSocket.BeginReceiveFrom(mTemp, 0, mTemp.Length, SocketFlags.None, ref mEndPoint, OnReceive, null);
            }
        }
        /// <summary>
        /// Add an error packet to the incoming queue.
        /// </summary>
        public void Error(IPEndPoint ip, string error)
        {
            Buffer buffer = Buffer.Create();
            buffer.BeginPacket(Packet.Error).Write(error);
            buffer.EndTcpPacketWithOffset(4);

            Datagram dg = new Datagram();
            dg.buffer = buffer;
            dg.ip = ip;
            lock (mIn) mIn.Enqueue(dg);
        }