在C#中创建最大长度的所有可能缓冲区

时间:2014-01-06 13:57:01

标签: c# .net

对于我们的嵌入式设备,我们使用RS232(COM端口)定义了通信协议。

现在我想做一些利用最大长度的所有可能缓冲区的漏洞/漏洞测试。

所以我需要一些代码来创建给定长度的所有可能字节模式的列表。

例如,对于给定的长度2,我想要这个列表:

0x00
0x01
...
0xFF
0x0000
0x0001
...
0xFFFF

有关如何在C#中创建此列表的任何建议吗?

THX

4 个答案:

答案 0 :(得分:2)

基本代码始终相同:for循环。要发送所有可能的值,您只需循环它们即可。

for (int i=0; i < numberOfBytes; ++i) 
{
    for (BigInteger j=0; j < BigInteger.Pow(2, i * 8); ++j) 
    {
        SendData(j.ToByteArray());
    }
}

答案 1 :(得分:0)

解决方案:

private static void SequencesInner(byte[] bytes, int i, Action<byte[]> action)
{
    if (i == bytes.Length)
    {
        action(bytes);
    }
    else
    {
        int j = i + 1;
        for (int v = 0; v < 256; v++)
        {
            bytes[i] = Convert.ToByte(v);
            SequencesInner(bytes, j, action);
        }
    }
}

private static void Sequences(int length, Action<byte[]> action)
{
    for (int n = 1; n <= length; n++)
    {
        SequencesInner(new byte[n], 0, action);
    }
}

完整代码:

using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;

namespace ConsoleApplication
{
    class Program
    {
        private static void SequencesInner(byte[] bytes, int i, Action<byte[]> action)
        {
            if (i == bytes.Length)
            {
                action(bytes);
            }
            else
            {
                int j = i + 1;
                for (int v = 0; v < 256; v++)
                {
                    bytes[i] = Convert.ToByte(v);
                    SequencesInner(bytes, j, action);
                }
            }
        }

        private static void Sequences(int length, Action<byte[]> action)
        {
            for (int n = 1; n <= length; n++)
            {
                SequencesInner(new byte[n], 0, action);
            }
        }

        static void Main()
        {
            var maxBufferSize = 2;
            var outputFilePath = Path.GetTempFileName();
            var sb = new StringBuilder();
            using (var sw = new StreamWriter(outputFilePath))
            {
                Sequences(
                    maxBufferSize,
                    a => sw.WriteLine(sb.Clear().Append("0x").Append(String.Join("", Array.ConvertAll(a, x => x.ToString("X2", CultureInfo.InvariantCulture))))));
                sw.Flush();
            }
            var process = Process.Start("notepad.exe", outputFilePath);
            process.WaitForExit();
            File.Delete(outputFilePath);
        }
    }
}

答案 2 :(得分:0)

我可能会弄错,但当前的问题似乎要求所有可能的字节序列长度达到N ,这需要很长时间才能发送假设:

  • 115200波特率
  • 每字节10位
  • 长度为N = 256 ^ N
  • 的可能字节序列的数量
  • 我的数学是对的......

长度为1到4的可能序列数为4311810304,总字节数为17230332160,发送时间为17天。

所以最好的算法可能是(n.b.需要直接发送缓冲区而不是我想象的存储它们):

public static List<byte[]> GetBuffers(int maxLength)
{
    if (maxLength > 4) throw new InvalidOperationException("Fail");
    var result = new List<byte[]>();
    for (int i = 1; i <= maxLength; i++)
    {
        var max = 1 << (i * 8);
        for (long j = 0; j < max; j++)
        {
            // Can remove the Reverse() if endianness/ordering doesn't matter
            var buffer = BitConverter.GetBytes(j).Take(i).Reverse().ToArray());
            result.Add(buffer);
        }
    }
    return result;
}

如果您仍想运行测试并且想要更长的序列,可以根据@Adriano的答案修改它以使用BigInteger.ToByteArray。

答案 3 :(得分:-1)

正如韦斯顿所指出的,这基本上是一种排列问题。

因此,您可以使用他链接到的帖子 - https://stackoverflow.com/questions/852536/calculating-all-possible-sub-sequences-of-a-given-length-c,但他链接的代码不会重复使用旧字母,因此您无法获得所需的完整列表。这可以通过修改链接到该帖子中的优秀代码(在此处找到 - http://www.interact-sw.co.uk/iangblog/2004/09/16/permuterate)来修复

using System;
using System.Collections.Generic;

public class PermuteUtils
{
    // Returns an enumeration of enumerators, one for each permutation
    // of the input.
    public static IEnumerable<IEnumerable<T>> Permute<T>(IEnumerable<T> list, int count)
    {
        if (count == 0)
        {
            yield return new T[0];
        }
        else
        {
            int startingElementIndex = 0;
            foreach (T startingElement in list)
            {
                IEnumerable<T> remainingItems = list;// - Removed to get all permutations AllExcept(list, startingElementIndex);

                foreach (IEnumerable<T> permutationOfRemainder in Permute(remainingItems, count - 1))
                {
                    yield return Concat<T>(
                        new T[] { startingElement },
                        permutationOfRemainder);
                }
                startingElementIndex += 1;
            }
        }
    }

    // Enumerates over contents of both lists.
    public static IEnumerable<T> Concat<T>(IEnumerable<T> a, IEnumerable<T> b)
    {
        foreach (T item in a) { yield return item; }
        foreach (T item in b) { yield return item; }
    }

}

然后做你想做的事情,我们只需要为所有十六进制数字得到2,3和4列表的排列

static void Main(string [] args)     {         char [] items = new char [] {'0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F'};

    for (int length = 2; length <= 4; length++)
    {
        foreach (IEnumerable<char> permutation in PermuteUtils.Permute(items, length))
        {
            StringBuilder output = new StringBuilder("0x");
            foreach (char c in permutation)
            {
                output.Append(c);
            }

            Console.WriteLine(output.ToString());
        }
    }
    Console.WriteLine("Done");
    Console.ReadLine();
}

所有的排列都会打印出来给你。然后,您可以将其转换为您需要的任何格式(或构建您需要的格式而不仅仅是字符串)。