我在PHP中通过UDP接收数据。
在通过PHP中的bin2hex函数传递缓冲区之后,我得到类似Raw Data
的内容,如下例所示
这是我的PHP代码:
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_bind($socket, "0.0.0.0" , 20500);
$from = '';
$port = 0;
socket_recvfrom($socket, $buf, 512, 0, $from, $port);
$file = 'testudp.txt';
// Open the file to get existing content
$current = file_get_contents($file);
// Append a new log line(s) to file
$current .= "New Connection " . date('Y-m-d H:i:s') . " \n" . bin2hex($buf) . "\n";
// Write the contents back to the file
file_put_contents($file, $current);
echo "Received connection from remote address $from and remote port $port" . PHP_EOL;
结果类似于83 05 01 02 03 04 05 01 01 01 02 00 01 4F B4 64 88 4F B4 64 88 13 BF 71 A8 BA 18 A5 06 00 00 1333 00 00 00 00 11 11 02 ...
但没有空格。
数据示例及应要转换为的内容:请注意,转换仅在前9个字节后开始,然后是地址2,然后再次跳过2。
Raw Data:
83 05 01 02 03 04 05 01 01 01 02 00 01 4F B4 64 88 4F B4 64
88 13 BF 71 A8 BA 18 A5 06 00 00 1333 00 00 00 00 11 11 02
33 44 44 55 55 66 77 88 99 10 11 ?? 00 ??
Decoded:
-------Message Header--------
01 Service Type, for this message 1 = Acknowledged Request
02 Message Type, for this message 2 = Event Report
-------Event Report----------
4FB46488 Update Time (5/17/12 @ 2:38pm)
4FB46488 Time of Fix (5/17/12 @ 2:38pm)
13BF71A8 Latitude (33.1313576)
BA18A506 Longitude (-117.2790010)
00001333 Altitude
00000000 Speed
1111 Heading
02 Satellites
33 Fix Status
4444 Carrier
5555 RSSI
66 Comm State
77 HDOP
88 Inputs
99 Unit Status
10 Event Index
11 Event Code
?? Accums (# of 4-byte Accum List values)
00 Spare
?? Accum List (Varies depending on the # of Accums reporting)
我已经尝试了各种解码器十六进制到ascii,我也试过在PHP中解压缩()都无济于事。
如何通过PHP将数据转换为类似于示例的内容?
即BA18A506
如何以人类可读的形式向我提供与Longitude (-117.2790010)
对应的数据(未格式化或未格式化)?
修改
文档指定Note that all bytes in multi-byte fields are transmitted in Net Endian format (Big Endian) where the most significant bits are transmitted first. For example, for a 32-bit field, bits 31-24 are transmitted first, 16-23 second, 8-15 third and 0-7 last
如果这有帮助的话。
答案 0 :(得分:2)
unpack()或unpack()每个substr()的二进制数据应该最终到达你想要的位置。但正如HamZa所提到的,你必须知道它是什么格式......
$test = "\x06\xA5\x18\xBA";
var_dump(unpack('l',$test));
结果:
-1172790010
只需添加。在正确的地方
解包第一部分的示例代码(在需要的地方扩展/更正)
更改您的代码以接收缓冲区而不是文件: socket_recv($ socket,$ buf,512,0);
然后你可以使用缓冲区$ buf(现在我输入你提供的样本数据)
// Now we use some test data
$buf = "\x83\x05\x01\x02\x03\x04\x05\x01\x01\x01\x02\x00\x01\x4F\xB4\x64\x88\x4F\xB4\x64\x88\x13\xBF\x71\xA8\xBA\x18\xA5\x06\x00\x00\x13\x33\x00\x00\x00\x00\x11\x11\x02\x33\x44\x44\x55\x55\x66\x77\x88\x99\x10\x11";
// field definition
$fields = array();
$fields['header'] = array(9, 'c*');
$fields['serviceType'] = array(1, 'c');
$fields['messageType'] = array(1, 'c');
$fields['skip'] = array(2, 'c');
$fields['updateTime'] = array(4, 'l');
$fields['fixTime'] = array(4, 'l');
$fields['longitude'] = array(4, 'l');
$fields['latitude'] = array(4, 'l');
$fields['altitude'] = array(4, 'l');
$fields['speed'] = array(4, 'l');
// etc.
$values = array();
$start = 0;
foreach($fields as $type=>$setting) {
list($len, $format) = $setting;
$values[$type] = unpack($format, strrev(substr($buf, $start, $len)));
$start += $len;
}
var_dump($values);
将输出如下内容:
["serviceType"]=>
array(1) {
[1]=>
int(1)
}
["messageType"]=>
array(1) {
[1]=>
int(2)
}
["skip"]=>
array(1) {
[1]=>
int(1)
}
["updateTime"]=>
array(1) {
[1]=>
int(1337222280)
}
["fixTime"]=>
array(1) {
[1]=>
int(1337222280)
}
["longitude"]=>
array(1) {
[1]=>
int(331313576)
}
["latitude"]=>
array(1) {
[1]=>
int(-1172790010)
}
["altitude"]=>
array(1) {
[1]=>
int(4915)
}
["speed"]=>
array(1) {
[1]=>
int(0)
}
将纬度和经度除以10000000(10M)以获得真实的经度和纬度