Receive UDP packet datagrams in PHP

dslauter picture dslauter · Dec 17, 2013 · Viewed 13.1k times · Source

I am working in php to build a listening server for a GPS tracking system. The GPS sends data through UDP packets, which I can display by running the below script. However the actual data comes out in symbols so I am guessing I am missing a conversion

    //Reduce errors
    error_reporting(~E_WARNING);

    //Create a UDP socket
    if(!($sock = socket_create(AF_INET, SOCK_DGRAM, 0)))
    {
        $errorcode = socket_last_error();
        $errormsg = socket_strerror($errorcode);

        die("Couldn't create socket: [$errorcode] $errormsg \n");
    }

    echo "Socket created \n";

    // Bind the source address
    if( !socket_bind($sock, "192.168.1.29" , 1731) )
    {
        $errorcode = socket_last_error();
        $errormsg = socket_strerror($errorcode);

        die("Could not bind socket : [$errorcode] $errormsg \n");
    }

    echo "Socket bind OK \n";

    //Do some communication, this loop can handle multiple clients
    while(1)
    {
        echo "\n Waiting for data ... \n";

        //Receive some data
        $r = socket_recvfrom($sock, $buf, 512, 0, $remote_ip, $remote_port);
        echo "$remote_ip : $remote_port -- " . $buf;

            //Send back the data to the client
        //socket_sendto($sock, "OK " . $buf , 100 , 0 , $remote_ip , $remote_port);

    }

    socket_close($sock);

Answer

Geekman picture Geekman · Dec 17, 2013

I've not done this with PHP before, but my first guess would be that you are getting a binary string back, which you'll need to convert into ASCII (or whatever character set you're using).

It looks like you should be able to use PHP's unpack for this.

It's hard to know exactly what format to provide pack without knowing what data you're getting back. It looks like unpack would at least be able to give back an array of decimal values (assuming you're getting characters back), which you could then convert into ASCII, with chr. It might be something like this:

//Receive some data
$r = socket_recvfrom($sock, $buf, 512, 0, $remote_ip, $remote_port);
//Convert to array of decimal values
$array = unpack("c*chars", $buf);
//Convert decimal values to ASCII characters:
$chr_array = array();
for ($i = 0; $i < count($array); $i++)
{
    $chr_array[] = chr($array[$i]);
}

It depends on the protocol design as to how complex your parsing of the binary data needs to be (That is, are you just sending string data, or a mix of integers and strings, etc... You need to parse the binary data accordingly).

EDIT: I've updated the format string to match an indefinite number of characters, using the array element name 'chars' as per the format listed here.

EDIT: Added some elementary ASCII conversion to code example.