Creating buffers in PHP

4

Personally I need to create a buffer (string) of a dataset (array) to send via socket. In this buffer I want all the attributes of the set that are stored in it, obey its size.

Example: If I am going to store an integer value of the data set in buffer , it will have to occupy 4 bytes within that buffer .

Code:

// Cria array
$bMsg3 = array (
    $at1 = 1,  
    $at2 = 2,
    $at3 = 3,
    $at4 = 4,
    $at5 = 5,
    $at6 = 6,
);

    $buffer[$at1]   = 32768;           /* Inteiro  = 4 bytes  */
    $buffer[$at2]   = 'HelloWorld';    /* String   = 10 bytes */
    $buffer[$at3]   = 123456;          /* Inteiro  = 4 bytes  */
    $buffer[$at4]   = 789101;          /* Inteiro  = 4 bytets */
    $buffer[$at5]   = 123852;          /* Float    = 4 bytes  */
    $buffer[$at6]   = 'teste';         /* String   = 5 bytes  */
                                      /* Total: 31 bytes     */

// Converte para string
$str = implode('', $buffer);

print "String: $str";

In this code, I create an array with several attributes, and convert it to string and store it in the variable $str , giving a print in $str looks like this: 132768HelloWorld123456789101123852teste . In this case the size in bytes of the string is 39 bytes, while it should be 31 bytes, how could I fix it?

    
asked by anonymous 27.07.2015 / 16:37

2 answers

4

As I mentioned in the comments the solution to use string to mount the package is wrong, because if you convert a number to string it will be treated as a string by PHP so the int (40) that should occupy 4 bytes in memory will occupy 2 bytes as string '4' and '0'

You can use PHP's pack / unpack functions to convert information into a byte array. You will see the array elements in int 's and if you put them all together it will not be the result you are looking for either.

<?php

$bMsg3 = array (
    $at1 = 1,  
    $at2 = 2,
    $at3 = 3,
    $at4 = 4,
    $at5 = 5,
    $at6 = 6,
);

    $bMsg3[$at1]   = 32768;           /* Inteiro  = 4 bytes  */
    $bMsg3[$at2]   = 'HelloWorld';    /* String   = 10 bytes */
    $bMsg3[$at3]   = 123456;          /* Inteiro  = 4 bytes  */
    $bMsg3[$at4]   = 789101;          /* Inteiro  = 4 bytets */
    $bMsg3[$at5]   = 123852;          /* Float    = 4 bytes  */
    $bMsg3[$at6]   = 'teste';         /* String   = 5 bytes  */
                                      /* Total: 31 bytes     */

echo "<pre>";
var_dump(unpack("C*", pack("i", $bMsg3[$at1])));
var_dump(unpack("C*", $bMsg3[$at2]));
var_dump(unpack("C*", pack("i", $bMsg3[$at3])));
var_dump(unpack("C*", pack("i", $bMsg3[$at4])));
var_dump(unpack("C*", pack("i", $bMsg3[$at5])));
var_dump(unpack("C*", $bMsg3[$at6]));

Result:

array(4) {
  [1]=>
  int(0)
  [2]=>
  int(128)
  [3]=>
  int(0)
  [4]=>
  int(0)
}
array(10) {
  [1]=>
  int(72)
  [2]=>
  int(101)
  [3]=>
  int(108)
  [4]=>
  int(108)
  [5]=>
  int(111)
  [6]=>
  int(87)
  [7]=>
  int(111)
  [8]=>
  int(114)
  [9]=>
  int(108)
  [10]=>
  int(100)
}
array(4) {
  [1]=>
  int(64)
  [2]=>
  int(226)
  [3]=>
  int(1)
  [4]=>
  int(0)
}
array(4) {
  [1]=>
  int(109)
  [2]=>
  int(10)
  [3]=>
  int(12)
  [4]=>
  int(0)
}
array(4) {
  [1]=>
  int(204)
  [2]=>
  int(227)
  [3]=>
  int(1)
  [4]=>
  int(0)
}
array(5) {
  [1]=>
  int(116)
  [2]=>
  int(101)
  [3]=>
  int(115)
  [4]=>
  int(116)
  [5]=>
  int(101)
}

So one of the possible solutions is to convert everything to hex and send that packet to the network.

<?php

$bMsg3 = array (
    $at1 = 1,  
    $at2 = 2,
    $at3 = 3,
    $at4 = 4,
    $at5 = 5,
    $at6 = 6,
);

    $bMsg3[$at1]   = 32768;           /* Inteiro  = 4 bytes  */
    $bMsg3[$at2]   = 'HelloWorld';    /* String   = 10 bytes */
    $bMsg3[$at3]   = 123456;          /* Inteiro  = 4 bytes  */
    $bMsg3[$at4]   = 789101;          /* Inteiro  = 4 bytets */
    $bMsg3[$at5]   = 123852;          /* Float    = 4 bytes  */
    $bMsg3[$at6]   = 'teste';         /* String   = 5 bytes  */
                                      /* Total: 31 bytes     */

echo "<pre>";
var_dump(unpack("H*", pack("i", $bMsg3[$at1])));
var_dump(unpack("H*", $bMsg3[$at2]));
var_dump(unpack("H*", pack("i", $bMsg3[$at3])));
var_dump(unpack("H*", pack("i", $bMsg3[$at4])));
var_dump(unpack("H*", pack("i", $bMsg3[$at5])));
var_dump(unpack("H*", $bMsg3[$at6]));

That will work, but to send you can put them together in a single string.

array(1) {
  [1]=>
  string(8) "00800000"
}
array(1) {
  [1]=>
  string(20) "48656c6c6f576f726c64"
}
array(1) {
  [1]=>
  string(8) "40e20100"
}
array(1) {
  [1]=>
  string(8) "6d0a0c00"
}
array(1) {
  [1]=>
  string(8) "cce30100"
}
array(1) {
  [1]=>
  string(10) "7465737465"
}

In C the package comes as an unsigned char, so we can have this example here to print the data. (using a small piece of the package)

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(void) {

    unsigned char pacote[] = { 0x00, 0x80, 0x00, 0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x57, 0x6f, 0x72, 0x6c, 0x64 };

    struct pckt {
        int a;
        char b[10];
    };


    struct pckt *meu_pckt = (struct pckt*) pacote;
    char n[11];
    memcpy(n, meu_pckt->b, 10);
    n[10] = '
32768
HelloWorld
'; printf("%d\n", meu_pckt->a); printf("%s\n", n); return 0; }

You should print:

<?php

$bMsg3 = array (
    $at1 = 1,  
    $at2 = 2,
    $at3 = 3,
    $at4 = 4,
    $at5 = 5,
    $at6 = 6,
);

    $bMsg3[$at1]   = 32768;           /* Inteiro  = 4 bytes  */
    $bMsg3[$at2]   = 'HelloWorld';    /* String   = 10 bytes */
    $bMsg3[$at3]   = 123456;          /* Inteiro  = 4 bytes  */
    $bMsg3[$at4]   = 789101;          /* Inteiro  = 4 bytets */
    $bMsg3[$at5]   = 123852;          /* Float    = 4 bytes  */
    $bMsg3[$at6]   = 'teste';         /* String   = 5 bytes  */
                                      /* Total: 31 bytes     */

echo "<pre>";
var_dump(unpack("C*", pack("i", $bMsg3[$at1])));
var_dump(unpack("C*", $bMsg3[$at2]));
var_dump(unpack("C*", pack("i", $bMsg3[$at3])));
var_dump(unpack("C*", pack("i", $bMsg3[$at4])));
var_dump(unpack("C*", pack("i", $bMsg3[$at5])));
var_dump(unpack("C*", $bMsg3[$at6]));
    
28.07.2015 / 17:18
1

I do not know if it's a good solution, but that should work.

    $array = array(
        (int)substr($str, 0, 4),
        substr($str, 4, 10),
        (int)substr($str, 10, 4),
        (int)substr($str, 14, 4),
        (float)substr($str, 18, 4),
        substr($str, 22, 5),            
    );
    
28.07.2015 / 16:01