PHP write array of bytes to a tcp stream - php

I am trying to write some binary data (in an array of unsigned chars) to a tcp stream, the data looks like this:
array(44) {
[0]=>int(0)
[1]=>int(44)
[2]=>int(10)
[3]=>int(0)
[4]=>int(5)
[5]=>int(108)
[6]=>int(111)
[7]=>int(103)
...
And what I would like to get to is a string holding the same binary bytes, that I can throw into fwrite() to send these bytes down a TCP connection.
Everything I have tried using join etc, so far has ended up with the ascii equivalent (eg the first byte ends up as 0x30 , an ascii '0', instead of 0x00)
What I need to end up with is binary data in the string ie 0x00, 0x2C, 0x0A not an ascii representation of the data.
Ideas?

You just can use the function "decbin()" to convert your integer into a binary format.
After this you can send the binary code to your TCP connection.
Here is a code example:
<?php
$numbers = array(
0 => "0",
1 => "1",
2 => "2"
);
$bin = decbin($numbers[1]);
$bin = substr("00000000",0,8 - strlen($bin)) . $bin;
echo $bin;
?>
Output is 00000001 for Number 1.

Related

Unpack hex-encoded binary data in PHP

We're collecting data from a partner's IoT devices and the data comes encoded in a hex string like 1C000000010028 which contains binary data:
Byte 0 bit 0 Boolean
Byte 0 bit 1 Boolean
Byte 0 bit 2 Boolean
Byte 0 bit 3 Boolean
Byte 0 bits 4-7 UInt4
Bytes 1-2 bits 0-15 UInt16
Byte 3 bits 0-7 UInt8
Bytes 4-5 bits 0-15 UInt16
Byte 6 bits 0-7 UInt8
I have never worked with this kind of data and am wondering how to decode / unpack this in PHP. I was guessing that https://www.php.net/manual/de/function.unpack.php would be my friend but I just don't get it. Any help would be much appreciated, thanks!
They say that the input is a hex string like '1C000000010028'.
$code = '1C000000010028';
To use unpack() the data must be a string with binaryData. You can convert it with hex2bin.
$binaryData = hex2bin($code);
// "\x1c\x00\x00\x00\x01\x00\x28"
Now you could use unpack.
$arr = unpack('Cbyte_0/vUInt16_0/Cbyte_1/vUInt16_1/Cbyte_2',$binaryData);
/*
$arr = array (
'byte_0' => 28,
'UInt16_0' => 0,
'byte_1' => 0,
'UInt16_1' => 1,
'byte_2' => 40,
)
*/
Individual data types such as Boolean and UInt4 are not included in the pack/unpack formats. To get this data you have to work with the bit operators.
Just one example of this:
$byte_0bit2 = (bool)($arr['byte_0'] & 0b00000100);
This can lead to further questions, the answers of which can be found here on Stackoverflow.

PHP convert integer to 32 bit (4 Byte) hex for socket programming

I need to convert integer to a 4 byte (32 bit) hex for sending it as ACK to a device i am currently trying to integrate.
For example
3 = 00000003
15 = 0000000F
Check http://www.mathsisfun.com/binary-decimal-hexadecimal-converter.html
1. Select signed 32 bit from the dropdown
2. Enter the value in decomal text box
3. Check value in hex field.
I am using php pack function with this parameter but based on the response from the device, it does not seem to be the correct approach.
$reply = pack(L*,$num);
Is this the correct parameter or there is some other way.
Please suuggest.
i would do
$a = 15;
var_dump( sprintf("%08X", $a) );
$a = 3;
var_dump( sprintf("%08X", $a) );
this outputs
string(8) "0000000F"
string(8) "00000003
08X means make a 8 char string padded with 0 (if needed) with the argument being treated as hex. (Upper case letters)
so in your example
$reply = sprintf("%08X", $num)

Convert 64 bit Integer hex string to 64 bit decimal string on 32 bit system

What is a simple way to convert a 64 bit integer encoded as a hex string to a decimal string on a 32 bit system. It needs to be the full value, it can not be in scientific notation or truncated :/
"0c80000000000063" == "900719925474099299"
"0c80000000000063" != 9.007199254741E+17
PHP's base_convert() and hexdec() don't do the job right.
You need to use BC Math PHP extension (bundled).
First split your input string to get high and low bytes, next convert it to decimal and then do calculation via BC functions like this:
$input = "0C80000000000063";
$str_high = substr($input, 0, 8);
$str_low = substr($input, 8, 8);
$dec_high = hexdec($str_high);
$dec_low = hexdec($str_low);
//workaround for argument 0x100000000
$temp = bcmul ($dec_high, 0xffffffff);
$temp2 = bcadd ($temp, $dec_high);
$result = bcadd ($temp2, $dec_low);
echo $result;
/*
900719925474099299
*/
Have you seen the first comment to hexdec's help page on php.net?
When given large numbers, the hexdec function automatically converts
the value to scientific notation. So, "aa1233123124121241" as a
hexadecimal value will be converted to "3.13725790445E+21". If you're
converting a hexadecimal value that represents a hash value (md5 or
sha), then you need every single bit of that representation to make it
useful. By using the number_format function, you can do that
perfectly. For example :
<?php
// Author: holdoffhunger#gmail.com
// Example Hexadecimal
// ---------------------------------------------
$hexadecimal_string = "1234567890abcdef1234567890abcdef";
// Converted to Decimal
// ---------------------------------------------
$decimal_result = hexdec($hexadecimal_string);
// Print Pre-Formatted Results
// ---------------------------------------------
print($decimal_result);
// Output Here: "2.41978572002E+37"
// .....................................
// Format Results to View Whole All Digits in Integer
// ---------------------------------------------
// ( Note: All fractional value of the
// Hexadecimal variable are ignored
// in the conversion. )
$current_hashing_algorithm_decimal_result = number_format($decimal_result, 0, '', '');
// Print Formatted Results
// ---------------------------------------------
print($current_hashing_algorithm_decimal_result);
// Output Here: "24197857200151253041252346215207534592"
// .....................................
?>

How do you use the raw_output return value of md5() in PHP?

I'm pretty inexperienced in PHP so this may be obvious to some of you, but if I call md5($mystring,true) in PHP it says it returns a "raw binary format with a length of 16". So what is that? Is it an array? An array of what? How do I read the individual bits and bytes of that return value?
None of the examples I can find online use it without going straight into base64_encode() or something. I just want to be able to check the fifth bit, or the third byte, for example.
var_dump(md5("string", TRUE));
"Raw binary format" means a string (as strings are binary-safe in PHP):
string(16) "�\����= �(��^{!"
If you want to read a byte out of that, use the $string[5] offset syntax for that. Or to extract a single bit out of the fifth byte for example:
$bit4_from_5th_byte = ord($result[5]) & (1 << 4);
It returns it as a "string" with each Character being a byte of the output. What you might consider instead is using the hex output of md5() without the second parameter and converting substrings of it to numbers using intval() with 16 as the base parameter. Like so:
$hash = md5($raw);
$byte = intval(substr($hash, 0, 2), 16);
An MD5 hash is a 128bit number, e.g. 16 bytes of raw binary data. For legibility, PHP's md5() function defaults to outputting this as a human readable string, where those 16 binary bytes get converted into a 32 character alpha-numeric string.
When you specify that second true parameter for MD5, you're telling PHP to return that raw 128bit number instead of the human readable version.
The RAW output of MD5 is the plain binary string of the hash. You cannot print it to the screen since it's not encoded as actual ASCII characters but binary numbers. This is only useful if you need to store or transfer the hash in a binary format.
To get the individual bits:
$md5 = md5( "b", true );
$l = strlen( $md5 );
$bits = "";
for( $i = 0; $i < $l; ++$i ) {
$num = ord( $md5[$i] );
for( $j = 7; $j >= 0; --$j ) {
$bits .= ( $num & ( 1 << $j ) ) ? "1" : "0";
}
}
echo $bits."\n";
//10010010111010110101111111111110111001101010111000101111111011000011101011010111000111000111011101110101001100010101011110001111
echo asciibin2hex( $bits ) == md5("b"); // true
So we go byte by byte, and since it is in string form, we need to convert it to ASCII number by ord(). Now go through the byte, bit by bit and see which are turned on and which are turned off and concatenate to the bit string. Go to next byte and rinse and repeat until all 128 bits are read.
Read third bit ( from the left ) in third byte:
ord( $md5[2] ) & ( 1 << ( 8 - 3 ) )
returns 1 if the bit is turned on, 0 otherwise

PHP - read 8 bit integers

I have a binary file that is all 8 bit integers. I have tried to use the php unpack() functions but I cant get any of the arguments to work for 1 byte integers. I have tried to combine the data with a dummy byte so that I can use the 'n'/'v' arguments. I am working with a windows machine to do this. Ultimately I would like a function to return an array of integers based on a string of 8 bit binary integers. The code I have tried is below -
$dat_handle = "intergers.dat";
$dat_file = fopen($dat_handle, "rb");
$dat_data = fread($dat_file, 1);
$dummy = decbin(0);
$combined = $dummy.$dat_data;
$result = unpack("n", $combined);
What your looking for is the char datatype. Now there are two version of this, signed (lowercase c) and unsigned (uppercase C). Just use the one that's correct for your data.
<?php
$byte = unpack('c', $byte);
?>
Also, if the data file is just a bunch of bytes and nothing else, and you know it's length, you can do this. (If the length is 16 signed chars in a row.)
<?php
$bytes = unpack('c16', $byte);
?>
If you don't know how many bytes will be in the file, but you know there is only going to be bytes you can use the asterisk code to read until EOF.
<?php
$bytes = unpack('c*', $byte);
?>
The following should do what you want (ord):
$dat_handle = "intergers.dat";
$dat_file = fopen($dat_handle, "rb");
$dat_data = ord(fread($dat_file, 1));
What you are trying to do is retrieve the integer value of the single byte. Because you are reading in single bytes at a time, you will always have exactly one valid ASCII character. ord returns the binary value of that one character.

Categories