PHP - 为 TCP 套接字准备数据包

问题描述 投票:0回答:1

我正在尝试编写一个 PHP TCP 客户端来连接到 Unreal Engine 5 RCON 服务器。我正在使用 GitHub 上的现有 C# 项目作为参考,但在准备要发送的数据包时遇到了困难。 GitHub 项目准备一个

byte
数组,然后将其发送到服务器。我尝试用 PHP 重写该函数,但不确定是否正确。但更大的问题是
socket_write()
socket_send()
fwrite()
都想要一个
string
而我现在有一个
array
。我相信我可以使用
pack()
将数组格式化为字符串来表示字节,但我不确定如何操作。

这是来自 https://github.com/Sp1rit/ArkRcon/blob/master/Rcon/RconPacket.cs 的 C# 函数 所以这显示了我需要发送的内容。

    public static implicit operator byte[](RconPacket packet)
    {
        byte[] buffer = new byte[packet.Size + 4];

        packet.Size.ToLittleEndian().CopyTo(buffer, 0);
        packet.Id.ToLittleEndian().CopyTo(buffer, 4);
        ((int)packet.Type).ToLittleEndian().CopyTo(buffer, 8);
        Encoding.ASCII.GetBytes(packet.Body).CopyTo(buffer, 12);

        return buffer;
    }

这是我尝试转换它的方法(参见下面的

ConvertToArray()
)。我确实使用了
__invoke
但因为还有一个反向功能,它不会让我使用
__invoke
两次。我提供了整个课程,以便您可以看到完整的图片,并且可以看到一些注释代码,其中我尝试了不同的操作。

class RconPacket
{

    private static int $idCounter = 1;

    public $Id;
    public int $Type;
    public $Body;

    public function GetSize()
    {
        return (!empty($Body) ? strlen($Body) + 10 : 0);
    }

    public function __construct($type, $body)
    {
        $this->Id = RconPacket::$idCounter++;
        $this->Type = $type;
        $this->Body = $body;
    }

    public function ConvertToArray(): array
    {
        $buffer = array(); //array_fill(0, $this->GetSize() + 4, 0);
        $buffer[] = pack('V', $this->GetSize() + 4); //->copy($buffer, 0);
        $buffer[] = pack('V', $this->Id); //->copy($buffer, 4);
        $buffer[] = pack('V', (int)$this->Type); //->copy($buffer, 8);
        $buffer = array_merge($buffer, array_map(fn($c) => ord($c), str_split($this->Body)));
    
        //$buffer[] = str_split($this->Body)->map(fn($c, $i) => ord($c)); //->copy($buffer, 12);

        return $buffer;
    }

    public static function ConvertToRconPacket(string $data): RconPacket
    {
        $size = unpack('V', $data)[1];
        $id = unpack('V', $data, 4)[1];
        $type = unpack('V', $data, 8)[1];
        $body = substr($data, 12, $size - 10);

        return new RconPacket($id, $type, $body);
    }
}

我尝试使用

pack("a", $buffer);
将数组转换为字符串,但是
pack()
还需要
string

php sockets raw-sockets
1个回答
0
投票

基础知识:PHP中的

string
实际上是一个二进制数组(例如
$str[3]
是第4个字节),所以你不必使用PHP数组,你可以直接使用
pack
打包的字符串功能。

$data = pack('V3a*',
             $this->GetSize(),
             $this->Id,
             (int)$this->Type,
             $this->Body);
fwrite($fp, $data);
© www.soinside.com 2019 - 2024. All rights reserved.