2

I have a Sail Timer wind vane that transmits data via UDP over a WiFi network created by the wind vane hardware. The system works fine, and I can read the data via 3rd party INavX navigation software. But I want to be able to read the UDP stream directly via PHP for testing, and I can't get my script to run. I have no prior experience with UDP.

I know the hardware and network are work properly because the aforementioned software works fine. Also, I can see the network traffic in wireshark. I tried asking the vendor for help, but they said they are phasing my model out, they won't help me with the model I have, and I should buy a new one. But the guy who wrote the navigation software said it's a simple network connection with no initiation strings or anything, "Just connect to the port and you should see data."

What makes this a bit different from other UDP examples I've seen is this is essentially "listen only" (is that what broadcasting is?). If I try to write data to the socket, I get a "permission denied" error, which is why I'm specifying the ip and port in the socket_recvfrom function.

Here's my client code in PHP:

<?php

# based on from http://www.binarytides.com/udp-socket-programming-in-php/

/*
    Simple php udp socket client
*/

//Reduce errors
error_reporting(~E_WARNING);

// network settings for the wind vane
$server = '255.255.255.255';
$port = 55554;
if( isset($argv[1]) ) $server = $argv[1];
if( isset($argv[2]) ) $port   = $argv[2];

if(!($sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)))
{
    $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, "127.0.0.1" , 55554) )
{
    $errorcode = socket_last_error();
    $errormsg = socket_strerror($errorcode);

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


//Communication loop
while(1)
{

    //Now receive reply from server and print it
    if( ($bytesRead = socket_recvfrom ( $sock , $reply , 2045 , 0 , $server, $port )) === FALSE)
    {
        $errorcode = socket_last_error();
        $errormsg = socket_strerror($errorcode);

    if( ! in_array($errorcode, array(35) ) )
      die("Could not receive data: [$errorcode] $errormsg \n");
    }

    if( $bytesRead > 0 ) {
      echo "Reply : $reply";
    }
    usleep(500000);
}
Tim Herzog
  • 505
  • 1
  • 5
  • 11

2 Answers2

2

Give this a try:

//Create socket.
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
if (!$socket) { die("socket_create failed.\n"); }

//Set socket options.
socket_set_nonblock($socket);
socket_set_option($socket, SOL_SOCKET, SO_BROADCAST, 1);
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
if (defined('SO_REUSEPORT'))
    socket_set_option($socket, SOL_SOCKET, SO_REUSEPORT, 1);

//Bind to any address & port 55554.
if(!socket_bind($socket, '0.0.0.0', 55554))
    die("socket_bind failed.\n");

//Wait for data.
$read = array($socket); $write = NULL; $except = NULL;
while(socket_select($read, $write, $except, NULL)) {

    //Read received packets with a maximum size of 5120 bytes.
    while(is_string($data = socket_read($socket, 5120))) {
        echo $data;
    }

}
  • Thanks, I'll give it a shot in a few days when have access to the wind vane. Do I not have to specify an IP address? – Tim Herzog May 16 '15 at 18:29
  • You shouldn't have to specify an IP for broadcasts but there are some posts out there that [suggest otherwise](http://stackoverflow.com/questions/13666789/receiving-udp-broadcast-packets-on-linux). I only have an OS X machine to test with right now and it works fine there. `SO_BROADCAST` is probably unnecessary as well, but I included it [just in case](http://linux.die.net/man/7/ip). –  May 16 '15 at 23:09
-2

The above scenarios did not worked for me, always came with invalid protocol some kind of error:

Though this worked fine:

C++ receiver:

unlink("/tmp/mysock");
socklen_t address_length = sizeof(struct sockaddr_un);
int_socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if(_socket_fd<=0){
    perror("socket error socket()");
    return false;
}
struct sockaddr_un server_address = {0};
server_address.sun_family = AF_UNIX;
strcpy(server_address.sun_path, "/tmp/mysock");
if(bind(_socket_fd, (const struct sockaddr *) &server_address, 
        sizeof(server_address)) < 0)
{
    perror("bind ()");
    close(_socket_fd);
    _socket_fd=0;
    return false;
}
system("chmod 777 /tmp/mysock");

PHP: sender

$sock = socket_create (AF_UNIX, SOCK_DGRAM, 0 );//
if($sock!=null)
{
    socket_sendto($sock, "ls\n", 3, 0, "/tmpmysock", 0);
    fclose($sock);
}
user2195463
  • 321
  • 5
  • 8