C#解决Socket丢包,段包,粘包算法

C#, C#化解Socket丢包,段包,粘包算法

    /// <summary>
    /// Socket 丢包,段包,粘包 算法
    /// </summary>
    public class RequestHandler
    {
        private string temp = string.Empty;

        /// <summary>
        /// 处理Socket 丢包,段包,粘包 算法
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public string[] GetActualString(string input)
        {
            return GetActualString(input, null);
        }

        private string[] GetActualString(string input, List<string> outputList)
        {
            if (outputList == null)
                outputList = new List<string>();

            if (!string.IsNullOrEmpty(temp))
                input = temp + input;

            string output = "";

            string patten = @"(?<=^\[length=)(\d+)(?=\])";

            int length;

            if (Regex.IsMatch(input, patten))
            {

                Match m = Regex.Match(input, patten);

                //获取消息字符串的有效长度
                length = Convert.ToInt32(m.Groups[0].Value);

                //获取需要截取的位置
                int startIndex = input.IndexOf(']') + 1;

                //获取从此位置开始后所有的字符串长度
                output = input.Substring(startIndex);

                if (output.Length == length)
                {
                    //如果output的长度 = 消息字符串应有长度
                    //说明刚好是完整的一条信息
                    outputList.Add(output);
                    temp = "";
                }

                else if (output.Length < length)
                {
                    //如果output的长度 < 消息字符串应有长度
                    //说明没有发完整,则应该将整条消息,包括元数据,全部缓存
                    temp = input;
                }

                else if (output.Length > length)
                {
                    //如果之后的长度大于应有的长度,
                    //说明消息发完整了,但是有多余的数据
                    //多余的数据可能是截断消息,也可能是多条完整消息

                    //截取字符串
                    output = output.Substring(0, length);
                    outputList.Add(output);
                    temp = "";

                    //缩短 input 的长度
                    input = input.Substring(startIndex + length);

                    //递归调用
                    GetActualString(input, outputList);
                }
            }
            else
            {
                //说明 "[","]"就不完整
                temp = input;
            }
            return outputList.ToArray();
        }

        /// <summary>
        /// 测试数据
        /// </summary>
        public static void Test()
        {
            RequestHandler handler = new RequestHandler();
            string input;

            //第一种情况测试;发送一条完整消息
            input = "[length=13]明天中秋,祝大家节日快乐!";
            handler.PrintOutput(input);

            //第二种情况;两条完整消息一次性发送
            input = "明天中秋,祝大家节日快乐!";
            input = string.Format("[length=13]{0}[length=13]{0}", input);
            handler.PrintOutput(input);

            //第三种情况测试A ;两条消息不完整发送
            input = "[length=13]明天中秋,祝大家节日快乐![length=13]明天中秋";
            handler.PrintOutput(input);

            input = ",祝大家节日快乐!";
            handler.PrintOutput(input);

            //第三种情况测试B;两条消息不完整发送
            input = "[length=13]明天中秋,祝大家";
            handler.PrintOutput(input);

            input = "节日快乐![length=13]明天中秋,祝大家节日快乐!";
            handler.PrintOutput(input);

            //第四种情况:元数据不完整
            input = "[leng";
            handler.PrintOutput(input);

            input = "th=13]明天中秋,祝大家节日快乐!";
            handler.PrintOutput(input);
        }

        /// <summary>
        /// 打印
        /// </summary>
        /// <param name="input"></param>
        private void PrintOutput(string input)
        {
            Console.WriteLine("输入:"+input);
            string[] outputArray = GetActualString(input);
            foreach (var output in outputArray)
            {
                Console.WriteLine("输出:" + output);
            }
            Console.WriteLine();
        }
    }

新建控制台应用还,调用内的Test方法:

    class Program
    {
        static void Main(string[] args)
        {
            RequestHandler.Test();
            Console.Read();
        }
    }

C# 1

横流:本文自《.NET之美 》 作者:张子阳

相关文章