将PHP转换为C#

3

我已经花了大约一个小时的时间在这个问题上,但是我无法在C#中以正确的格式获取uint16。

PHP:

$data = "\x00"; //packet id
$data .= "\x04"; //protocol version
$data .= pack('c', strlen($server_address)) . $server_address; //server address
$data .= pack('n', $server_port); //server port
$data .= "\x01"; //next state

$data = pack('c', strlen($data)) . $data;

return $data;

C#:

string packet_id = "\x00";
string protocol_version = "\x04";
string server_address = new string(new char[] { Convert.ToChar(this.server_address.Length) }) + this.server_address;
//byte[] port_array = BitConverter.GetBytes((ushort)this.server_port);
//Array.Reverse(port_array);
string server_port = Convert.ToString((ushort)this.server_port);
string next_state = "\x01";

string final = packet_id + protocol_version + server_address + server_port + next_state;
final = new string(new char[] { Convert.ToChar(final.Length) }) + final;

结果的十六进制表示如下: PHP:
12 00 04 0C 31 39 38 2E 32 37 2E 38 33 2E 33 35 63 DE 01

C#:

15 00 04 0C 31 39 38 2E 32 37 2E 38 33 2E 33 35 32 35 35 36 36 01

如您所见,服务器端口(25566)在 PHP 中为 63 DE,而在 C# 中为 32 35 35 36 36。


"\x01" 转义的是 x 的值吗?应该改成 @"\x01" 吧?(其他包含 x 的字符串同理) - DotNetRussell
C# 将服务器端口写成字符串,应该将其写成数字。 - Dmitriy Finozhenok
这是一个字符串,我将要发送到一个套接字,服务器对格式非常挑剔,所以它必须精确无误,我无法正确地模拟 PHP 的 pack("n", "..") 函数。 - John Dong
3个回答

2
最简单的方法是使用字节数组和位运算:
byte[] data = new byte[] {
    (byte) (((ushort) this.server_port) >> 8),
    (byte) ((ushort) this.server_port)
};
string server_port = (string) data;

值得注意的是,你的PHP输出实际上显示的是25565,而不是25566。正如你可以在这里看到的那样,25566实际上是十六进制中的63DE

我认为你不能将字节数组强制转换为字符串。 - John Dong
所以从技术上讲,我正在使用C#模拟php的pack("n", ..)函数,这意味着uint16采用大端格式。 - John Dong

0
我建议你使用这段代码来转换端口:
this.server_port.ToString("X")

它将把您提供的数字转换为字符串中的十六进制表示形式


这样做可以产生正确的输出,但它会将其作为文本而不是十六进制数值输出。 - John Dong

0
你想要ping一个服务器吗?我建议使用Craft.Net,而不是自己尝试实现。

那对我学习套接字毫无帮助,不过还是谢谢你的建议。 - John Dong
你从没说过你在尝试学习 sockets。这个答案解决了你的问题。 - Drew DeVault

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接