$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;
}
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
Đó 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. –