sharppcap: '.'使用 printHex() 方法使用字符而不是空格

sharppcap: '.' characters instead of spaces with printHex() method

我使用 SharpPcap 库成功地解析了“.pcap”文件。

目标是从 TCP/HTTP 数据包中检索 XML 数据。为此,我使用了以下代码(删除了空检查以使其更具可读性):

Packet packet = Packet.ParsePacket(eventArguments.Packet.LinkLayerType, eventArguments.Packet.Data);
EthernetPacket ethernetPacket = ((EthernetPacket)packet);

IpPacket ipPacket = (IpPacket)packet.Extract(typeof(IpPacket));

TcpPacket tcpPacket = (TcpPacket)packet.Extract(typeof(TcpPacket));

string rawData = tcpPacket.PrintHex();

移动,除了十六进制值和初始行,我能够从 rawData 变量中提取 XML 数据,以及意外的副作用.

.PrintHex() returns '.' 而不是空格字符:

而不是:

<xml>Only text here</xml>

我得到这个:

<xml>Only.text.here</xml>

我没有做任何奇怪的替换或字节转换。以上行为正是 .PrintHex() returns.


库版本:

尝试使用 ToString() 方法的覆盖,它似乎完全符合您的期望。

如果这不起作用,您可以选择从 Packet 实现 public string PrintHex()。如果你看一下反编译代码,这就是你的问题:

    if ((int) bytes[index - 1] < 33 || (int) bytes[index - 1] > 126)
      str2 += ".";
    else
      str2 += Encoding.ASCII.GetString(new byte[1]
      {
        bytes[index - 1]
      });

只有dec编码在33到126之间的字符会保持不变,其余的会被替换为.(包括space也就是32http://www.asciitable.com/) .由于 BytesHighPerformance.Bytes 是 public,您可以很容易地按照这些思路编写自己的扩展方法。

TcpPacket tcpPacket = (TcpPacket)packet.Extract(typeof(TcpPacket));
string rawData = tcpPacket.CustomPrintHex();

public static class Extensions
{
    public static string CustomPrintHex(this TcpPacket self)
    {
        byte[] bytes = self.BytesHighPerformance.Bytes;

        // copy / paste of `PrintHex()` with your custom conversion
    }
}

这可能对其他人有帮助,所以我发布了我的最终解决方案(基于已接受的答案)。

附加功能:

  • 利用字符串生成器提高性能
  • 包括换行符

public class TcpPacketCustom: TcpPacket
{
    public static int AsciiRangeMin { get; } = 32;
    public static int AsciiRangeMax { get; } = 126;
    public static HashSet<int> AdditionalAsciiCodes { get; } = new HashSet<int> { 10, 13 }; //ascii codes of carriage and new line

    public TcpPacketCustom(ByteArraySegment byteArraySegment) : base(byteArraySegment) { }

    public new string PrintHex()
    {
        StringBuilder stringBuilder = new StringBuilder();
        foreach (byte b in this.BytesHighPerformance.Bytes)
        {
            int asciiCode = (int)b;
            if ( ((asciiCode < AsciiRangeMin) || (asciiCode > AsciiRangeMax)) && !AdditionalAsciiCodes.Contains(asciiCode) )
            {
                stringBuilder.Append(".");
            }
            else
            {
                stringBuilder.Append(Encoding.ASCII.GetString(new byte[1] { b }));
            }
        }
        return stringBuilder.ToString();
    }

}