2010-02-13 38 views
5

Tôi muốn biết cách đọc cấu trúc trong cấu trúc thông qua hàm unpack của php. Khi tôi nhận được một gói IS_MCI, tôi kiểm tra đó là Type để chắc chắn rằng nó bằng ISP_MCI, và sau đó tôi kiểm tra NumC để tìm hiểu xem có bao nhiêu cấu trúc CompCar có trong gói này. Vấn đề là cố gắng giải nén các nội dung này thành một mảng thông qua một hàm duy nhất. Tôi luôn luôn nhận được một bù đắp không xác định. Vì vậy, tôi đang tìm kiếm một số mắt mới về vấn đề này.Đọc một cấu trúc bên trong một cấu trúc thông qua chức năng giải nén của PHP

Bạn xử lý gói này như thế nào?

Các struct trong câu hỏi là thế này:

struct IS_MCI // Multi Car Info - if more than 8 in race then more than one of these is sent 
{ 
    byte Size;  // 4 + NumC * 28 
    byte Type;  // ISP_MCI 
    byte ReqI;  // 0 unless this is a reply to an TINY_MCI request 
    byte NumC;  // number of valid CompCar structs in this packet 

    CompCar Info[8]; // car info for each player, 1 to 8 of these (NumC) 
}; 

struct CompCar // Car info in 28 bytes - there is an array of these in the MCI (below) 
{ 
    word Node;  // current path node 
    word Lap;  // current lap 
    byte PLID;  // player's unique id 
    byte Position; // current race position : 0 = unknown, 1 = leader, etc... 
    byte Info;  // flags and other info - see below 
    byte Sp3; 
    int  X;   // X map (65536 = 1 metre) 
    int  Y;   // Y map (65536 = 1 metre) 
    int  Z;   // Z alt (65536 = 1 metre) 
    word Speed;  // speed (32768 = 100 m/s) 
    word Direction; // direction of car's motion : 0 = world y direction, 32768 = 180 deg 
    word Heading; // direction of forward axis : 0 = world y direction, 32768 = 180 deg 
    short AngVel;  // signed, rate of change of heading : (16384 = 360 deg/s) 
}; 
+1

Bạn có thể đăng chức năng cung cấp cho bạn khoản bù đắp không hợp lệ không? – Eineki

+0

Đó rõ ràng là khái niệm mà tôi không nắm bắt được. VolkerK giải thích khá rõ ràng trong câu trả lời của anh. Cảm ơn bạn đã tìm kiếm @ câu hỏi của tôi. –

Trả lời

2
$msg = 
    chr(0x20) // Size = 32 (4+1*28) 
    . chr(0x1) // Type = 1 
    . chr(0x0) // ReqI=0 
    . chr(0x1) // NumC=1 
    . chr(0x1) . chr(0x0) // node=1 
    . chr(0x2) . chr(0x0) // lap=2 
    . chr(0x3) // puid=3 
    . chr(0x5) // pos=5 
    . chr(0x10) // info=16 
    . chr(0x0) //sp3=0 
    . chr(0x0) . chr(0x0) . chr(0x1) . chr(0x0) // x=65536 
    . chr(0x0) . chr(0x0) . chr(0x2) . chr(0x0) // y=65536*2 
    . chr(0x0) . chr(0x0) . chr(0x3) . chr(0x0) // z=65536*3 
    . chr(0x0) . chr(0x20) // speed=8192 
    . chr(0x0) . chr(0x10) // dir=4096 
    . chr(0x0) . chr(0x8) // heading=2048 
    . chr(0x0) . chr(0x4) // AngVel=1024 
; 

$IS_MCI = unpack('CSize', $msg); 
if (strlen($msg) < $IS_MCI['Size']) { 
    die("not enough data"); 
} 
$IS_MCI += unpack('CType/CReqI/CNumC', substr($msg, 1)); 
$IS_MCI['Info'] = array(); 

for($i=0; $i<$IS_MCI['NumC']; $i++) { 
    $data = substr($msg, 4+($i*28), 28); 
    $IS_MCI['Info'][] = unpack('vNode/vLap/CPLID/CPosition/CInfo/CSp3/lX/lY/lZ/vSpeed/vDirection/vHeading/sAngVel', $data); 
} 
print_r($IS_MCI); 

in

Array 
(
    [Size] => 32 
    [Type] => 1 
    [ReqI] => 0 
    [NumC] => 1 
    [Info] => Array 
     (
      [0] => Array 
       (
        [Node] => 1 
        [Lap] => 2 
        [PLID] => 3 
        [Position] => 5 
        [Info] => 16 
        [Sp3] => 0 
        [X] => 65536 
        [Y] => 131072 
        [Z] => 196608 
        [Speed] => 8192 
        [Direction] => 4096 
        [Heading] => 2048 
        [AngVel] => 1024 
       ) 

     ) 

) 

Bây giờ, mã mà làm cho một số giả định rằng bạn có thể không muốn đưa cho các cấp (tức là thêm rất nhiều xử lý lỗi/đọc nhiều hơn).

  • Giả định gói ($ msg) đã được đọc hoàn toàn trước khi mã chạy. Bạn có thể muốn chỉ đọc những phần bạn cần (không cần đến substr()). Hoặc ít nhất là chuẩn bị rằng thông điệp có thể đến trong một số khối.
  • Nó cũng có các tham số kích thước/num được cấp, nghĩa là nó không kiểm tra xem các giá trị có khả thi hay không và có đủ dữ liệu. Đó chắc chắn là điều bạn phải thay đổi. Size phải nằm trong khoảng từ 0 ... 228, NumC phải nằm trong khoảng từ 0 ... 8 và cả hai giá trị phải phù hợp với nhau và v.v.
  • Ngoài ra hãy xem xét kỹ hơn các định danh định dạng mà tôi đã sử dụng trong giải nén(). Đối với word Tôi đã sử dụng v viết tắt của "unsigned ngắn (luôn luôn 16 bit, little endian byte để) Nhưng đối với int Tôi đã sử dụng l:. "Ký dài (luôn luôn 32 bit, máy byte để)" . Đó là ok trên máy tính của tôi. Nhưng tìm kiếm tài liệu của giao thức cho endianness của dữ liệu.

các TestData trong $ msg đã được lấy từ kết quả của

__declspec(align(1)) struct CompCar // Car info in 28 bytes - there is an array of these in the MCI (below) 
{ 
    word Node;  // current path node 
    word Lap;  // current lap 
    byte PLID;  // player's unique id 
    byte Position; // current race position : 0 = unknown, 1 = leader, etc... 
    byte Info;  // flags and other info - see below 
    byte Sp3; 
    int  X;   // X map (65536 = 1 metre) 
    int  Y;   // Y map (65536 = 1 metre) 
    int  Z;   // Z alt (65536 = 1 metre) 
    word Speed;  // speed (32768 = 100 m/s) 
    word Direction; // direction of car's motion : 0 = world y direction, 32768 = 180 deg 
    word Heading; // direction of forward axis : 0 = world y direction, 32768 = 180 deg 
    short AngVel;  // signed, rate of change of heading : (16384 = 360 deg/s) 
}; 

__declspec(align(1)) struct IS_MCI // Multi Car Info - if more than 8 in race then more than one of these is sent 
{ 
    byte Size;  // 4 + NumC * 28 
    byte Type;  // ISP_MCI 
    byte ReqI;  // 0 unless this is a reply to an TINY_MCI request 
    byte NumC;  // number of valid CompCar structs in this packet 

    CompCar Info[1]; // example: one element, fixed 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    struct IS_MCI mci = { 
    32, 1, 0, 1, 
    { 1, 2, 3, 5, 16, 0, 65536, 65536*2, 65536*3, 8192, 4096, 2048, 1024 } 
    }; 

    WSADATA wsaData; 
    WORD wVersionRequested = MAKEWORD(2, 2); 
    int err = WSAStartup(wVersionRequested, &wsaData); 
    if (err != 0) { 
     /* Tell the user that we could not find a usable */ 
     /* WinSock DLL.         */ 
     return 1; 
    } 

    SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    sockaddr_in addr; 
    addr.sin_family = AF_INET; 
    addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    addr.sin_port = htons(8081); 
    if (0!=connect(s, (SOCKADDR*) &addr, sizeof(addr))) { 
    printf("%X ", WSAGetLastError()); 
    return 0; 
    } 
    send(s, (const char*)&mci, sizeof(mci), 0); 
    shutdown(s, SD_BOTH); 
    closesocket(s); 
    return 0; 
} 
+0

Cảm ơn bạn, tôi sẽ kiểm tra và liên hệ lại với bạn. Cảm ơn ngài. –

1

Tôi đang sử dụng này:


class IS_MCI extends ISP { 
     public $Size; 
     public $Type = ISP_MCI; 
     public $ReqI; 
     public $NumC; 

     public function IS_MCI($data, &$CompCar) { 
       $up = unpack('CSize/CType/CReqI/CNumC', $data); 
       $this->Size = $up['Size']; 
       $this->ReqI = $up['ReqI']; 
       $this->NumC = $up['NumC']; 

       $temp = array(); 

       $p = 4; 
       for ($i = 0; $i NumC; $i++) { 
         $up2 = unpack('SNode/SLap/CPLID/CPosition/CInfo/CSp3/IX/IY/IZ/SSpeed/SDirection/SHeading/sAngVel', substr($data, $p, 28)); 
         $temp[] = new CompCar($up2['Node'],$up2['Lap'],$up2['PLID'],$up2['Position'],$up2['Info'],$up2['Sp3'],$up2['X'],$up2['Y'],$up2['Z'],$ 
         $p += 28; 
       } 
       $CompCar = $temp; 
     } 
} 

Và lớp CompCar:


class CompCar { 
     public $xNode;   // current path node 
     public $Lap;   // current lap 
     public $PLID;   // player's unique id 
     public $Position;  // current race position : 0 = unknown, 1 = leader, etc... 
     public $Info;   // flags and other info - see below 
     public $Sp3; 
     public $X;    // X map (65536 = 1 metre) 
     public $Y;    // Y map (65536 = 1 metre) 
     public $Z;    // Z alt (65536 = 1 metre) 
     public $Speed;   // speed (32768 = 100 m/s) 
     public $Direction;  // direction of car's motion : 0 = world y direction, 32768 = 180 deg 
     public $Heading;  // direction of forward axis : 0 = world y direction, 32768 = 180 deg 
     public $AngVel;   // signed, rate of change of heading : (16384 = 360 deg/s) 

     public $SpeedKPH;  // speed in kph 
     public $SpeedMPH;  // speed in mph 
     public $DirectionC;  // Direction calculated to degrees 
     public $HeadingC;  // Heading calculated to degrees 
     public $AngVelC;  // Calculated 

     // ADDED: 
     public $SpeedMS;    // speed in mps 

     public function __construct($xNode,$Lap,$PLID,$Position,$Info,$Sp3,$X,$Y,$Z,$Speed,$Direction,$Heading,$AngVel) { 
       $this->xNode = $xNode; 
       $this->Lap = $Lap; 
       $this->PLID = $PLID; 
       $this->Position = $Position; 
       $this->Info = $Info; 
       $this->Sp3 = $Sp3; 
       $this->X = $X; 
       $this->Y = $Y; 
       $this->Z = $Z; 
       $this->Speed = $Speed; 
       $this->Direction = $Direction; 
       $this->Heading = $Heading; 
       $this->AngVel = $AngVel; 

       $this->doCalcs(); 
     } 

     private function doCalcs() { 
       // Speed Calc 
       $old = $this->Speed; 
       $this->SpeedKPH = ($old * (100/32768)) * 3.6; 
       $this->SpeedMPH = $this->SpeedKPH * 0.6215; 

       $this->SpeedKPH = floor($this->SpeedKPH); 
       $this->SpeedMPH = floor($this->SpeedMPH); 
       $this->SpeedMS = $this->SpeedKPH/3.6; 

       // Direction 
       $this->DirectionC = CompCar::degrees($this->Direction); 

       // Heading 
       $this->HeadingC = CompCar::degrees($this->Heading); 

       // Angle Calcs 
       $this->AngVelC = $this->AngVel * 180/8192; 
     } 

     public static function degrees($input) { 
       $input = $input/65535 * 360; 
       //$input = 360 - floor($input); 
       $input = floor(360 - $input); 
       return $input; 
     } 

} 

Và tất cả những gì nó làm việc tốt!

+0

Tôi đang sử dụng một tuyến đường hơi khác, nhưng tôi chấp thuận bài đăng này! +1. –

Các vấn đề liên quan