RedisHelper.cs 11.8 KB
using HslCommunication.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;

namespace HslCommunication.Enthernet.Redis
{
    /// <summary>
    /// 提供了redis辅助类的一些方法
    /// </summary>
    public class RedisHelper
    {
        #region Socket Helper
        
        /// <summary>
        /// 接收一行命令数据
        /// </summary>
        /// <param name="socket">网络套接字</param>
        /// <returns>带有结果对象的数据信息</returns>
        public static OperateResult<byte[]> ReceiveCommandLine( Socket socket )
        {
            return NetSupport.ReceiveCommandLineFromSocket( socket, (byte)'\n' );
        }

        /// <summary>
        /// 接收一行字符串的信息
        /// </summary>
        /// <param name="socket">网络套接字</param>
        /// <param name="length">字符串的长度</param>
        /// <returns>带有结果对象的数据信息</returns>
        public static OperateResult<byte[]> ReceiveCommandString( Socket socket, int length )
        {
            try
            {
                List<byte> bufferArray = new List<byte>( );
                bufferArray.AddRange( NetSupport.ReadBytesFromSocket( socket, length ) );

                OperateResult<byte[]> commandTail = ReceiveCommandLine( socket );
                if (!commandTail.IsSuccess) return commandTail;

                bufferArray.AddRange( commandTail.Content );
                return OperateResult.CreateSuccessResult( bufferArray.ToArray( ) );
            }
            catch (Exception ex)
            {
                return new OperateResult<byte[]>( ex.Message );
            }
        }


        /// <summary>
        /// 从网络接收一条redis消息
        /// </summary>
        /// <param name="socket">网络套接字</param>
        /// <returns>接收的结果对象</returns>
        public static OperateResult<byte[]> ReceiveCommand( Socket socket )
        {
            List<byte> bufferArray = new List<byte>( );

            OperateResult<byte[]> readCommandLine = ReceiveCommandLine( socket );
            if (!readCommandLine.IsSuccess) return readCommandLine;

            bufferArray.AddRange( readCommandLine.Content );
            if (readCommandLine.Content[0] == '+' || readCommandLine.Content[0] == '-' || readCommandLine.Content[0] == ':')
            {
                // 状态回复,错误回复,整数回复
                return OperateResult.CreateSuccessResult( bufferArray.ToArray( ) );
            }
            else if (readCommandLine.Content[0] == '$')
            {
                // 批量回复,允许最大512M字节
                OperateResult<int> lengthResult = GetNumberFromCommandLine( readCommandLine.Content );
                if (!lengthResult.IsSuccess) return OperateResult.CreateFailedResult<byte[]>( lengthResult );

                if (lengthResult.Content < 0) return OperateResult.CreateSuccessResult( bufferArray.ToArray( ) );

                // 接收字符串信息
                OperateResult<byte[]> receiveContent = ReceiveCommandString( socket, lengthResult.Content );
                if (!receiveContent.IsSuccess) return receiveContent;

                bufferArray.AddRange( receiveContent.Content );
                return OperateResult.CreateSuccessResult( bufferArray.ToArray( ) );
            }
            else if (readCommandLine.Content[0] == '*')
            {
                // 多参数的回复
                OperateResult<int> lengthResult = GetNumberFromCommandLine( readCommandLine.Content );
                if (!lengthResult.IsSuccess) return OperateResult.CreateFailedResult<byte[]>( lengthResult );

                for (int i = 0; i < lengthResult.Content; i++)
                {
                    OperateResult<byte[]> receiveCommand = ReceiveCommand( socket );
                    if (!receiveCommand.IsSuccess) return receiveCommand;

                    bufferArray.AddRange( receiveCommand.Content );
                }

                return OperateResult.CreateSuccessResult( bufferArray.ToArray( ) );
            }
            else
            {
                return new OperateResult<byte[]>( "Not Supported HeadCode: " + readCommandLine.Content[0] );
            }
        }

        #endregion

        #region Prase Helper

        /// <summary>
        /// 将字符串数组打包成一个redis的报文信息
        /// </summary>
        /// <param name="commands">字节数据信息</param>
        /// <returns>结果报文信息</returns>
        public static byte[] PackStringCommand( string[] commands )
        {
            StringBuilder sb = new StringBuilder( );
            sb.Append( '*' );
            sb.Append( commands.Length.ToString( ) );
            sb.Append( "\r\n" );
            for (int i = 0; i < commands.Length; i++)
            {
                sb.Append( '$' );
                sb.Append( Encoding.UTF8.GetBytes( commands[i] ).Length.ToString( ) );
                sb.Append( "\r\n" );
                sb.Append( commands[i] );
                sb.Append( "\r\n" );
            }
            return Encoding.UTF8.GetBytes( sb.ToString( ) );
        }

        /// <summary>
        /// 从原始的结果数据对象中提取出数字数据
        /// </summary>
        /// <param name="commandLine">原始的字节数据</param>
        /// <returns>带有结果对象的数据信息</returns>
        public static OperateResult<int> GetNumberFromCommandLine( byte[] commandLine )
        {
            try
            {
                string command = Encoding.UTF8.GetString( commandLine ).TrimEnd( '\r', '\n' );
                return OperateResult.CreateSuccessResult( Convert.ToInt32( command.Substring( 1 ) ) );
            }
            catch (Exception ex)
            {
                return new OperateResult<int>( ex.Message );
            }
        }
        
        /// <summary>
        /// 从原始的结果数据对象中提取出数字数据
        /// </summary>
        /// <param name="commandLine">原始的字节数据</param>
        /// <returns>带有结果对象的数据信息</returns>
        public static OperateResult<long> GetLongNumberFromCommandLine( byte[] commandLine )
        {
            try
            {
                string command = Encoding.UTF8.GetString( commandLine ).TrimEnd( '\r', '\n' );
                return OperateResult.CreateSuccessResult( Convert.ToInt64( command.Substring( 1 ) ) );
            }
            catch (Exception ex)
            {
                return new OperateResult<long>( ex.Message );
            }
        }

        /// <summary>
        /// 从结果的数据对象里提取字符串的信息
        /// </summary>
        /// <param name="commandLine">原始的字节数据</param>
        /// <returns>带有结果对象的数据信息</returns>
        public static OperateResult<string> GetStringFromCommandLine( byte[] commandLine )
        {
            try
            {
                if (commandLine[0] != '$') return new OperateResult<string>( Encoding.UTF8.GetString( commandLine ) );

                // 先找到换行符
                int index_start = -1;
                int index_end = -1;
                // 下面的判断兼容windows系统及linux系统
                for (int i = 0; i < commandLine.Length; i++)
                {
                    if (commandLine[i] == '\r' || commandLine[i] == '\n')
                    {
                        index_start = i;
                    }

                    if (commandLine[i] == '\n')
                    {
                        index_end = i;
                        break;
                    }
                }

                int length = Convert.ToInt32( Encoding.UTF8.GetString( commandLine, 1, index_start - 1 ) );
                if (length < 0) return new OperateResult<string>( "(nil) None Value" );

                return OperateResult.CreateSuccessResult( Encoding.UTF8.GetString( commandLine, index_end + 1, length ) );
            }
            catch (Exception ex)
            {
                return new OperateResult<string>( ex.Message );
            }
        }

        /// <summary>
        /// 从redis的结果数据中分析出所有的字符串信息
        /// </summary>
        /// <param name="commandLine">结果数据</param>
        /// <returns>带有结果对象的数据信息</returns>
        public static OperateResult<string[]> GetStringsFromCommandLine( byte[] commandLine )
        {
            try
            {
                List<string> lists = new List<string>( );
                if (commandLine[0] != '*') return new OperateResult<string[]>( Encoding.UTF8.GetString( commandLine ) );

                int index = 0;
                for (int i = 0; i < commandLine.Length; i++)
                {
                    if (commandLine[i] == '\r' || commandLine[i] == '\n')
                    {
                        index = i;
                        break;
                    }
                }

                int length = Convert.ToInt32( Encoding.UTF8.GetString( commandLine, 1, index - 1 ) );
                for (int i = 0; i < length; i++)
                {
                    // 提取所有的字符串内容
                    int index_end = -1;
                    for (int j = index; j < commandLine.Length; j++)
                    {
                        if (commandLine[j] == '\n')
                        {
                            index_end = j;
                            break;
                        }
                    }
                    index = index_end + 1;
                    if (commandLine[index] == '$')
                    {
                        // 寻找子字符串
                        int index_start = -1;
                        for (int j = index; j < commandLine.Length; j++)
                        {
                            if (commandLine[j] == '\r' || commandLine[j] == '\n')
                            {
                                index_start = j;
                                break;
                            }
                        }
                        int stringLength = Convert.ToInt32( Encoding.UTF8.GetString( commandLine, index + 1, index_start - index - 1 ) );
                        if (stringLength >= 0)
                        {
                            for (int j = index; j < commandLine.Length; j++)
                            {
                                if (commandLine[j] == '\n')
                                {
                                    index_end = j;
                                    break;
                                }
                            }
                            index = index_end + 1;

                            lists.Add( Encoding.UTF8.GetString( commandLine, index, stringLength ) );
                            index = index + stringLength;
                        }
                        else
                        {
                            lists.Add( null );
                        }
                    }
                    else
                    {
                        int index_start = -1;
                        for (int j = index; j < commandLine.Length; j++)
                        {
                            if (commandLine[j] == '\r' || commandLine[j] == '\n')
                            {
                                index_start = j;
                                break;
                            }
                        }
                        lists.Add( Encoding.UTF8.GetString( commandLine, index, index_start - index - 1 ) );
                    }
                }
                
                return OperateResult.CreateSuccessResult( lists.ToArray( ) );
            }
            catch (Exception ex)
            {
                return new OperateResult<string[]>( ex.Message );
            }
        }


        #endregion
    }
}