1

我想发送这个十六进制数据包:

00 38 60 dc 00 00 04 33  30 3c 00 00 00 20 63 62 
39 62 33 61 36 37 34 64  31 36 66 32 31 39 30 64 
30 34 30 63 30 39 32 66  34 66 38 38 32 62 00 06 
35 2e 31 33 2e 31 00 00  02 3c

所以我建立了字符串:

string packet = "003860dc0000" + textbox1.text+ "00000020" + textbox2.text+ "0006" + textbox3.text;

然后将其“转换”为ASCII:

conn_str = HexString2Ascii(packet);

然后我发送数据包......但我有这个:

00 38 60 **c3 9c** 00 00 04 33  30 3c 00 00 00 20 63 
62 39 62 33 61 36 37 34 64  31 36 66 32 31 39 30 
64 30 34 30 63 30 39 32 66  34 66 38 38 32 62 00 
06 35 2e 31 33 2e 31 00 00  02 3c **0a**

为什么??谢谢!PS函数是:

private string HexString2Ascii(string hexString)
{
     byte[] tmp;
     int j = 0;
     int lenght;
     lenght=hexString.Length-2;
     tmp = new byte[(hexString.Length)/2];
     for (int i = 0; i <= lenght; i += 2)
     {
         tmp[j] =(byte)Convert.ToChar(Int32.Parse(hexString.Substring(i, 2), System.Globalization.NumberStyles.HexNumber));
         j++;
     }
     return Encoding.GetEncoding(1252).GetString(tmp);
}

编辑:如果我直接转换为字节,则将十六进制数据包编码为字符串:

00000000  30 30 33 38 36 30 64 63  30 30 30 30 30 34 33 33 003860dc 00000433
00000010  33 30 33 43 30 30 30 30  30 30 32 30 33 34 33 32 303C0000 00203432
00000020  36 33 36 33 33 35 33 39  33 32 33 34 36 36 33 39 63633539 32346639
00000030  36 33 33 39 33 31 33 39  33 30 33 36 33 33 36 35 63393139 30363365
00000040  33 35 36 33 36 35 36 35  36 35 33 31 33 39 33 38 35636565 65313938
00000050  36 33 33 31 36 34 33 34  36 33 33 30 30 30 30 36 63316434 63300006
00000060  33 35 32 65 33 31 33 33  32 65 33 31 30 30 30 30 352e3133 2e310000
00000070  30 32 33 43                                      023C
4

1 回答 1

2

您不能将原始二进制数据转换为字符串数据并期望一切正常。它们是不相同的。当您混淆字符编码时尤其如此。

C# 字符不是 ASCII 字符。它们是 Unicode 字符,由 Unicode 代码点表示。当你转身写出这些字符时,你需要指定写出什么样的数据。当您使用 Encoding.GetEncoding(1252) 将字节数组读入字符串时,您将获得与代码页 1252 对应的字符,其中0xdcÜ.

但是,当您的字符串被转换回字节以通过网络发送时,它会被写为 UTF-8。在 UTF-8 中,UTF-00DC 不能编码为单个字节,因为该字节值用于指示多字节序列的开始。相反,它被编码为多字节序列0xc3 0x9c。就 C# 而言,这两个值是相同的字符。(我不知道额外的 0x0a 来自哪里,但我的猜测是来自您的一个文本框和/或您的流程的其他部分的错误换行)。

目前尚不清楚您到底要做什么,但我怀疑您转换的次数太多,无法正常工作。如果您知道要发送的字节序列,为什么不直接将其编码为 byte[] 呢?例如,使用 aMemoryStream并将所需的常量字节写入其中。

为了从文本框中获取值,将十六进制数字字符串“转换”为 ASCII 字符字符串的原始代码具有正确的想法。你只需要停在你有一个字节数组的地方,因为最终字节数组就是你想要的。

public byte[] GetBytesFrom(string hex)
{
    var length = hex.Length / 2;
    var result = new byte[length];
    for (var i = 0; i < length; i++)
    {          
      result[i] = byte.Parse(hex.Substring(i, 2), NumberStyles.HexNumber);
    }

    return result;
}

// Variable portions of packet structure.
var byte[] segment2 = GetBytesFrom(textbox1.Text);
var byte[] segment4 = GetBytesFrom(textbox2.Text);
var byte[] segment6 = GetBytesFrom(textbox3.Text);

MemoryStream output = new MemoryStream();
output.Write(new[] { 0x00, 0x38, 0x60, 0xdc, 0x00, 0x00 }, 0, 6);
output.Write(segment2, 0, segment2.Length);
output.Write(new[] { 0x00, 0x00, 0x00, 0x20 }, 0, 4);
output.Write(segment4, 0, segment4.Length);
output.Write(new[] { 0x00, 0x06 }, 0, 2);
output.Write(segment6, 0, segment6.Length);

从这里,您可以使用MemoryStream.CopyTo()将其复制到另一个流,或MemoryStream.Read()将整个数据包读入一个新的字节数组,或MemoryStream.GetBuffer()获取底层缓冲区(尽管最后一个很少是您想要的——它包括未使用的填充字节)

于 2012-06-24T22:17:39.113 回答