/// <summary>
        /// Send header only (without body)
        /// </summary>
        /// <param name="header"></param>
        public void Send(IProtocolHeader header)
        {
            if (_isClosing)
            {
                throw new AsyncSocketException("Connection has closed");
            }

            _lastSendHeader  = header;
            _isSendingHeader = true;
            _toBeSendData    = null;
            _sendingProgress.Reset();

            byte[]          headerData = header.GetHeaderRawData();
            SocketSendState sendState  = new SocketSendState(headerData, 0, headerData.Length);

            beginSendData(sendState);
        }
        /// <summary>
        /// Send header and body at one time
        /// </summary>
        /// <param name="header"></param>
        /// <param name="data"></param>
        /// <param name="offset"></param>
        /// <param name="length"></param>
        public void Send(IProtocolHeader header, byte[] data, int offset, int length)
        {
            //NOTE::
            //when this operation complete, it raise SendComplete event only once when
            //the header and body all send complete.

            if (_isClosing)
            {
                throw new AsyncSocketException("Connection has closed");
            }

            _lastSendHeader  = header;
            _isSendingHeader = true;
            _toBeSendData    = new SocketSendState(data, offset, length);
            _sendingProgress.Reset();
            _sendingProgress.Total = length;

            byte[]          headerData = header.GetHeaderRawData();
            SocketSendState sendState  = new SocketSendState(headerData, 0, headerData.Length);

            beginSendData(sendState);
        }
        /// <summary>
        /// Combine with 'ContinueSendingBody' method to send big data
        /// </summary>
        /// <param name="header"></param>
        /// <param name="totalPlanSendingLength"></param>
        public void Send(IProtocolHeader header, long totalPlanSendingLength)
        {
            //NOTE::
            //when need sending big data, call this method first,
            //and when this header send complete, call "ContinueSendingBody" many times
            //to send the body until all has been send.

            if (_isClosing)
            {
                throw new AsyncSocketException("Connection has closed");
            }

            _lastSendHeader  = header;
            _isSendingHeader = true;
            _toBeSendData    = null;
            _sendingProgress.Reset();
            _sendingProgress.Total = totalPlanSendingLength;

            byte[]          headerData = header.GetHeaderRawData();
            SocketSendState sendState  = new SocketSendState(headerData, 0, headerData.Length);

            beginSendData(sendState);
        }