RedisHelper.cs 11.6 KB
using HslCommunication.Core;
using System;
using System.Collections.Generic;
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
    }
}