TCP通讯协议(中)字符串边界问题

案例来自张子阳的《NET之美》,经消化后放在这。

如果希望字符串整齐传输,那么需要提出一个“标志”,比如下面传输“今天圣诞,祝大家节日快乐!”,在字符串前加入【length=13】,有点类似数据包的帧头帧尾,有效数据总是紧跟其后。 得到有效数据的长度后,可以进行截取、打印。有效数据的长度可以自定义,例子中是13,即每次打印完整的“今天圣诞,祝大家节日快乐!”。这里的标志,相当于Http的协议

以下有四种情况:1.收到数据的标志完整【length=13】,那么看后面有效数据,假如后者字符个数刚刚好等于13,就当次打印;如果大于13,就递归调用GetActualString(string input, List outputlist),见所有完整的“今天圣诞,祝大家节日快乐!”都保存到列表里,当次一并打印出来,多余的凑不齐的,存到temp里头,和下次传入的字符串合并;如果小于13,存temp。2.收到的数据的标志不完整,比如“【leng:”,存temp。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Client
{
 
    public class RequestHandler
    {
        public string temp = string.Empty;
        public string[] GetActualString(string input)
        {
            return GetActualString(input, null);
        }
        public string[] GetActualString(string input, List outputlist) //处理字符串,return a stringlist
        {
            if (outputlist == null) { outputlist = new List(); }
            if (!string.IsNullOrEmpty(temp)) { input = temp + input; }
            string output = "";
            string pattern = @"(?<=^\[length=)(\d+)(?=\])";//正则表达式
            int length;
            if (Regex.IsMatch(input, pattern))//标志完整,有效字符串总是在标志之后出现
            {
                Match m = Regex.Match(input, pattern); //寻找特定正则表达式对应的字符出现的位置,返回配对信息。
                length = Convert.ToInt32(m.Groups[0].Value);//得到有效字符串,比如“今天圣诞,祝大家节日快乐”的长度
                int startIndex = input.IndexOf(']') + 1;
                output = input.Substring(startIndex);//截取的有效字符串
                if (output.Length == length)
                {
                    outputlist.Add(output);
                    temp = "";
                }
                else if (output.Length < length)
                {
                    temp = input;
                }
                else if (output.Length >length)
                {
                    output = output.Substring(0, length);
                    outputlist.Add(output);
                    temp = "";
                    input = input.Substring(startIndex + length);
                    GetActualString(input, outputlist);//运用回调函数的目的是,假如字符串中有多个有效字符串,可一并存入outputlist,一并输出。
                }
            }
            else { temp = input; }//标志不完整,暂存
            return outputlist.ToArray();
        }


        static void Main(string[] args)
        {
            RequestHandler handler = new RequestHandler();
            string input;
            //test1 标志和字符串完整
            input = "[length=13]今天圣诞,祝大家节日快乐!";
            handler.PrintOutput(input);//符合要求,则打印,反之,存到缓存;如果标志不完整,也暂存。
            //test2 传入两条完整信息
            input = "今天圣诞,祝大家节日快乐!";
            input = String.Format("[length=13]{0}[length=13]{0}", input);
            handler.PrintOutput(input);
            //test3 标志完整,但有效字符串多了,多余的放在缓存,与下一次传入的合并
            input = "[length=13]今天圣诞,祝大家节日快乐![length=13]今天圣诞";
            handler.PrintOutput(input);

            input = ",祝大家节日快乐!";
            handler.PrintOutput(input);
            //test4 标志完整,但有效字符串少了,放在缓存,与下一次传入的字符串合并
            input = "[length=13]今天圣诞,祝大家";
            handler.PrintOutput(input);

            input = "节日快乐![length=13]今天圣诞,祝大家节日快乐!";
            handler.PrintOutput(input);

            //test4 标志完整,但有效字符串少了,放在缓存,与下一次传入的字符串合并
            input = "[leng";
            handler.PrintOutput(input);

            input = "th=13]今天圣诞,祝大家节日快乐![length=13]今天圣诞,祝大家节日快乐!";
            handler.PrintOutput(input);

            Console.ReadKey();

        }
        private void PrintOutput(string input)//打印字符串
        {
            Console.WriteLine("输入:" + input);

            string[] outputArray = GetActualString(input);
            foreach (string output in outputArray)
            {
                Console.WriteLine("输出:" + output);
            }
            Console.WriteLine();
        }
    }
}

 

你可能感兴趣的:(C#)