protected abstract void OnSessionClose(WebSocketSession session, WebSocketReceiveError error);
        public WebSocketFragment Parse(byte[] receiveBytes, out WebSocketReceiveError error)
        {
            error = null;
            WebSocketFragment fragment = new WebSocketFragment(receiveBytes);

            #region validate
            if (fragment.IsExtensionNegotiated)
            {
                error = new WebSocketReceiveError()
                {
                    CloseStatusCode = WebSocketCloseStatusCode.ProtocolError, CloseReason = "RSV1,RSV2,RSV3 must be 0,because extension negotiation is not supported"
                };
            }
            if (fragment.IsFinal && fragment.Opcode == WebSocketOpcode.Continuation)
            {
                error = new WebSocketReceiveError()
                {
                    CloseStatusCode = WebSocketCloseStatusCode.ProtocolError, CloseReason = "FIN is set to 1 but opcode indicate a contituation"
                };
            }
            if (fragment.Opcode == WebSocketOpcode.ReservedNoncontrolframe)
            {
                error = new WebSocketReceiveError()
                {
                    CloseStatusCode = WebSocketCloseStatusCode.ProtocolError, CloseReason = "Opcode 3-7 is reserved for non-control frames and is not suported now"
                };
            }
            if (fragment.Opcode == WebSocketOpcode.ReservedControlframe)
            {
                error = new WebSocketReceiveError()
                {
                    CloseStatusCode = WebSocketCloseStatusCode.ProtocolError, CloseReason = "Opcode B-F is reserved for controlframes and is not suported now"
                };
            }
            if (fragment.IsFinal && fragment.Opcode == WebSocketOpcode.Ping)
            {
                error = new WebSocketReceiveError()
                {
                    CloseStatusCode = WebSocketCloseStatusCode.ProtocolError, CloseReason = "Ping frame can not be fragmented"
                };
            }
            if (fragment.IsFinal && fragment.Opcode == WebSocketOpcode.Pong)
            {
                error = new WebSocketReceiveError()
                {
                    CloseStatusCode = WebSocketCloseStatusCode.ProtocolError, CloseReason = "Pong frame can not be fragmented"
                };
            }
            if (fragment.IsFinal && fragment.Opcode == WebSocketOpcode.Close)
            {
                error = new WebSocketReceiveError()
                {
                    CloseStatusCode = WebSocketCloseStatusCode.ProtocolError, CloseReason = "Close frame can not be fragmented"
                };
            }
            if (fragment.Opcode == WebSocketOpcode.Unkown)
            {
                error = new WebSocketReceiveError()
                {
                    CloseStatusCode = WebSocketCloseStatusCode.ProtocolError, CloseReason = "Unkown Opcode"
                };
            }
            if (!fragment.IsMasked)
            {
                error = new WebSocketReceiveError()
                {
                    CloseStatusCode = WebSocketCloseStatusCode.ProtocolError, CloseReason = "Message send from client must be masked"
                };
            }
            if (fragment.PayloadLength != (ulong)fragment.PayloadData.Length)
            {
                error = new WebSocketReceiveError()
                {
                    CloseStatusCode = WebSocketCloseStatusCode.ProtocolError, CloseReason = "payloadlength field value does not match the length of received payload data"
                };
            }
            #endregion
            return(fragment);
        }