Socket & Http in Loop break - php

I'm trying to test the "best" solution to communicate to PHP with NodeJS, but I can't do the test because I make something wrong with the loops.
Here is my NodeJS Code:
var ENCODING = 'utf8';
// SOCKETS
var net = require('net'); // Load the TCP Library
// HTTP REQUEST
var http = require('http'); // Load the HTTP Library | WEBSOCKETS NEED THIS!!
var querystring = require('querystring'); // Load Query Library
// SOCKET SERVER
net.createServer(function (socket) {
socket.setEncoding(ENCODING);
socket.on('data', function (data) {
socket.end('TEXT FROM SOCKET', ENCODING);
});
socket.on('close', function () {
});
}).listen(5000);
// HTTP SERVER
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end("TEXT FROM HTTP");
}).listen(2525);
And here my PHP test:
set_time_limit(0);
$address = '127.0.0.1';
$response = null;
// METHOD: HTTP (2525)
$start = microtime();
for ($x=0; $x<1000; $x++) {
$response = getHttp($address);
}
echo "<br>METHOD 1: " . (microtime() - $start);
// METHOD: Open + Loop Send + Close (5000)
$start = microtime();
$sc = SockOpen($address);
for ($x=0; $x<1000; $x++) {
$response = SockWrite($sc, $address);
}
SockClose($sc);
echo "<br>METHOD 2: " . (microtime() - $start);
// MMETHOD: Loop (Open + Send + Close) (5000)
$start = microtime();
for ($x=0; $x<1000; $x++) {
$sc = SockOpen($address);
$response = SockWrite($sc, $address);
SockClose($sc);
}
echo "<br>METHOD 3: " . (microtime() - $start);
function SockOpen($address) {
ob_implicit_flush();
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
return false;
}
$result = socket_connect($socket, $address, 5000);
if ($result === false) {
echo "socket_connect() failed.\nReason: ($result) " . socket_strerror(socket_last_error($socket)) . "\n";
return false;
}
return $socket;
}
function SockWrite($socket, $address) {
$in = "HEAD / HTTP/1.1\r\n";
$in .= "Host: ".$address."\r\n";
$in .= "Connection: Close\r\n\r\n";
//$in = "key1:value1\n";
socket_write($socket, $in, strlen($in));
$buffer=null;
while ($out = socket_read($socket, 2048)) {
$buffer .= $buffer;
}
return $buffer;
}
function SockClose($socket) {
socket_close($socket); die();
}
function getHttp($address) {
$url = 'http://'.$address.':2525/';
$data = array('key1' => 'value1');
// use key 'http' even if you send the request to https://...
$options = array(
'http' => array(
'header' => "Content-type: text/plain\r\n",
'method' => 'POST',
'content' => http_build_query($data),
),
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
return $result;
}
One simple connection Work OK, but if i make a loop, the socket "break" the connection and loop fails. The fail occurs in the HTTP and Socket method.
Any idea how to solve this?
thanks

I update the code, searching for the errors, i found problems in server & client codes, here are the updateds:
Client:
set_time_limit(0);
$address = '127.0.0.1';
$response = null;
// METHOD: HTTP (2525)
$start = microtime();
$fails = 0;
for ($x=0; $x<1000; $x++) {
$response = getHttp($address);
if (empty($response)) {
$fails++;
}
}
echo "<br>METHOD 1: " . (microtime() - $start) . " errors: " . $fails;
// METHOD: Open + Loop Send + Close (5000)
$start = microtime();
$fails = 0;
$sc = SockOpen($address);
for ($x=0; $x<1000; $x++) {
$response = SockWrite($sc, $address);
if (empty($response)) {
$fails++;
}
}
SockClose($sc);
echo "<br>METHOD 2: " . (microtime() - $start) . " errors: " . $fails;
// MMETHOD: Loop (Open + Send + Close) (5000)
$start = microtime();
$fails = 0;
for ($x=0; $x<1000; $x++) {
$sc = SockOpen($address);
$response = SockWrite($sc, $address);
if (empty($response)) {
$fails++;
}
SockClose($sc);
}
echo "<br>METHOD 3: " . (microtime() - $start) . " errors: " . $fails;
function SockOpen($address) {
//ob_implicit_flush();
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
return false;
}
$result = socket_connect($socket, $address, 5000);
if ($result === false) {
echo "socket_connect() failed.\nReason: ($result) " . socket_strerror(socket_last_error($socket)) . "\n";
return false;
}
return $socket;
}
function SockWrite($socket, $address) {
//$in = "HEAD / HTTP/1.1\r\n";
//$in .= "Host: ".$address."\r\n";
//$in .= "Connection: Close\r\n\r\n";
$in = "key1:value1";
socket_write($socket, $in, strlen($in));
$buffer=null;
//while ($out = socket_read($socket, 1024, MSG_WAITALL)) {
while (socket_recv($socket, $buffer, 2048, MSG_WAITALL) === true) {
$buffer .= $buffer;
}
return $buffer;
}
function SockClose($socket) {
socket_shutdown($socket);
socket_close($socket);
}
function getHttp($address) {
$url = 'http://'.$address.':2525/';
$data = array('key1' => 'value1');
// use key 'http' even if you send the request to https://...
$options = array(
'http' => array(
'header' => "Content-type: text/plain\r\n",
'method' => 'POST',
'content' => http_build_query($data),
),
);
$context = stream_context_create($options);
try {
$result = #file_get_contents($url, false, $context);
} catch (Exception $e) {
return false;
}
return $result;
}
Server:
var ENCODING = 'utf8';
// SOCKETS
var net = require('net'); // Load the TCP Library
// HTTP REQUEST
var http = require('http'); // Load the HTTP Library | WEBSOCKETS NEED THIS!!
var querystring = require('querystring'); // Load Query Library
// SOCKET SERVER
net.createServer(function (socket) {
socket.setEncoding(ENCODING);
//socket.write("TEXT FROM SOCKET", ENCODING);
socket.on('data', function (data) {
socket.write("TEXT FROM SOCKET\n", ENCODING);
//socket.end();
});
socket.on('close', function () {
});
}).listen(5000);
// HTTP SERVER
http.createServer(function (req, response) {
var body = 'TEXT FROM HTTP';
response.writeHead(200, {
'Content-Length': body.length,
'Content-Type': 'text/plain' });
response.write(body);
response.end();
}).listen(2525);
And the results:
METHOD 1: 0.385564 errors: 26
METHOD 2: 0.062286 errors: 0
METHOD 3: 0.255954 errors: 0
I think the HTTP method errors are because of simult connections by the same client (PHP).
An as spected, the fast is open + loop + close, and the slowest is HTTP
PD: negatives for..?

Related

Websocket failed "1006" w/o reason on GCE

everyone
I'm a new learner with websocket.
I want to deploy my websocket server on GCE.
However, I got some problem.
environment:
Backend:server.php(use php socket function) run on 8080 port
fronend:client.html(simple javascript)
GCE: Ubuntu 18.04, PHP 7.3, apache 2.4.29
without any google cloud sdk (only 2 program and 1 GCE instance)
problem:
Server can work well at my local machine (windows 10), but on GCE websocket will show "1006" error code.
There is a interesting thing that is client.html can work on GCE when I run server.php at local machine.
Is it normal? What is the connection with my local machine and GCE.
Maybe it's not a firewall blocking problem.
I wonder my websocket doesn't run because of the firewall port blocking at first.
I have set the VPC firewall rule with following GCP document and I also disable ufw on GCE.
I change the apache's port from 80 to 8080 and run apache.
It works successfully and I check netstat -an | grep "LISTEN "
I use telnet GCE_IP 8080 at my local machine but it can't connect.
Here is my code:
server.php
<?php
error_reporting(E_ALL);
set_time_limit(0);
class WebSocket {
const LOG_PATH = '/tmp/';
const LISTEN_SOCKET_NUM = 9;
private $sockets = [];
private $master;
public function __construct($host, $port) {
try {
$this->master = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($this->master, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($this->master, $host, $port);
socket_listen($this->master, self::LISTEN_SOCKET_NUM);
} catch (\Exception $e) {
$err_code = socket_last_error();
$err_msg = socket_strerror($err_code);
}
$this->sockets[0] = ['resource' => $this->master];
$pid = posix_getpid();
while (true) {
try {
$this->doServer();
} catch (\Exception $e) {
}
}
}
private function doServer() {
$write = $except = NULL;
$sockets = array_column($this->sockets, 'resource');
$read_num = socket_select($sockets, $write, $except, NULL);
if (false === $read_num) {
return;
}
foreach ($sockets as $socket) {
if ($socket == $this->master) {
$client = socket_accept($this->master);
if (false === $client) {
continue;
} else {
self::connect($client);
continue;
}
} else {
$bytes = #socket_recv($socket, $buffer, 2048, 0);
if ($bytes < 9) {
$recv_msg = $this->disconnect($socket);
} else {
if (!$this->sockets[(int)$socket]['handshake']) {
self::handShake($socket, $buffer);
continue;
} else {
$recv_msg = self::parse($buffer);
}
}
array_unshift($recv_msg, 'receive_msg');
$msg = self::dealMsg($socket, $recv_msg);
$this->broadcast($msg);
}
}
}
public function connect($socket) {
socket_getpeername($socket, $ip, $port);
$socket_info = [
'resource' => $socket,
'uname' => '',
'handshake' => false,
'ip' => $ip,
'port' => $port,
];
$this->sockets[(int)$socket] = $socket_info;
}
private function disconnect($socket) {
$recv_msg = [
'type' => 'logout',
'content' => $this->sockets[(int)$socket]['uname'],
];
unset($this->sockets[(int)$socket]);
return $recv_msg;
}
public function handShake($socket, $buffer) {
$line_with_key = substr($buffer, strpos($buffer, 'Sec-WebSocket-Key:') + 18);
$key = trim(substr($line_with_key, 0, strpos($line_with_key, "\r\n")));
$upgrade_key = base64_encode(sha1($key . "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true));
$upgrade_message = "HTTP/1.1 101 Switching Protocols\r\n";
$upgrade_message .= "Upgrade: websocket\r\n";
$upgrade_message .= "Sec-WebSocket-Version: 13\r\n";
$upgrade_message .= "Connection: Upgrade\r\n";
$upgrade_message .= "Sec-WebSocket-Accept:" . $upgrade_key . "\r\n\r\n";
socket_write($socket, $upgrade_message, strlen($upgrade_message));
$this->sockets[(int)$socket]['handshake'] = true;
socket_getpeername($socket, $ip, $port);
$msg = [
'type' => 'handshake',
'content' => 'done',
];
$msg = $this->build(json_encode($msg));
socket_write($socket, $msg, strlen($msg));
return true;
}
private function parse($buffer) {
$decoded = '';
$len = ord($buffer[1]) & 127;
if ($len === 126) {
$masks = substr($buffer, 4, 4);
$data = substr($buffer, 8);
} else if ($len === 127) {
$masks = substr($buffer, 10, 4);
$data = substr($buffer, 14);
} else {
$masks = substr($buffer, 2, 4);
$data = substr($buffer, 6);
}
for ($index = 0; $index < strlen($data); $index++) {
$decoded .= $data[$index] ^ $masks[$index % 4];
}
return json_decode($decoded, true);
}
private function build($msg) {
$frame = [];
$frame[0] = '81';
$len = strlen($msg);
if ($len < 126) {
$frame[1] = $len < 16 ? '0' . dechex($len) : dechex($len);
} else if ($len < 65025) {
$s = dechex($len);
$frame[1] = '7e' . str_repeat('0', 4 - strlen($s)) . $s;
} else {
$s = dechex($len);
$frame[1] = '7f' . str_repeat('0', 16 - strlen($s)) . $s;
}
$data = '';
$l = strlen($msg);
for ($i = 0; $i < $l; $i++) {
$data .= dechex(ord($msg{$i}));
}
$frame[2] = $data;
$data = implode('', $frame);
return pack("H*", $data);
}
private function dealMsg($socket, $recv_msg) {
$msg_type = $recv_msg['type'];
$msg_content = $recv_msg['content'];
$response = [];
switch ($msg_type) {
case 'login':
$this->sockets[(int)$socket]['uname'] = $msg_content;
$user_list = array_column($this->sockets, 'uname');
$response['type'] = 'login';
$response['content'] = $msg_content;
$response['user_list'] = $user_list;
break;
case 'logout':
$user_list = array_column($this->sockets, 'uname');
$response['type'] = 'logout';
$response['content'] = $msg_content;
$response['user_list'] = $user_list;
break;
case 'user':
$uname = $this->sockets[(int)$socket]['uname'];
$response['type'] = 'user';
$response['from'] = $uname;
$response['content'] = $msg_content;
break;
}
return $this->build(json_encode($response));
}
private function broadcast($data) {
foreach ($this->sockets as $socket) {
if ($socket['resource'] == $this->master) {
continue;
}
socket_write($socket['resource'], $data, strlen($data));
}
}
}
$ws = new WebSocket("localhost", "8080");
client.html
<html>
<head>
<title></title>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<style>
p {
text-align: left;
padding-left: 20px;
}
</style>
</head>
<body>
<div style="width: 800px;height: 600px;margin: 30px auto;text-align: center">
<h1>chat room</h1>
<div style="width: 800px;border: 1px solid gray;height: 300px;">
<div style="width: 200px;height: 300px;float: left;text-align: left;">
<p><span>online:</span><span id="user_num">0</span></p>
<div id="user_list" style="overflow: auto;">
</div>
</div>
<div id="msg_list" style="width: 598px;border: 1px solid gray; height: 300px;overflow: scroll;float: left;">
</div>
</div>
<br>
<textarea id="msg_box" rows="6" cols="50" onkeydown="confirm(event)"></textarea><br>
<input type="button" value="send" onclick="send()">
</div>
</body>
</html>
<script type="text/javascript">
var uname = prompt('type your name', 'user');
var ws = new WebSocket("ws://127.0.0.1:8080");
ws.onopen = function () {
var data = "system:connect successfully";
listMsg(data);
};
ws.onmessage = function (e) {
var msg = JSON.parse(e.data);
var sender, user_name, name_list, change_type;
switch (msg.type) {
case 'system':
sender = 'system: ';
break;
case 'user':
sender = msg.from + ': ';
break;
case 'handshake':
var user_info = {'type': 'login', 'content': uname};
sendMsg(user_info);
return;
case 'login':
case 'logout':
user_name = msg.content;
name_list = msg.user_list;
change_type = msg.type;
dealUser(user_name, change_type, name_list);
return;
}
var data = sender + msg.content;
listMsg(data);
};
ws.onerror = function () {
var data = "system : something wrong";
listMsg(data);
};
function confirm(event) {
var key_num = event.keyCode;
if (13 == key_num) {
send();
} else {
return false;
}
}
function send() {
var msg_box = document.getElementById("msg_box");
var content = msg_box.value;
var reg = new RegExp("\r\n", "g");
content = content.replace(reg, "");
var msg = {'content': content.trim(), 'type': 'user'};
sendMsg(msg);
msg_box.value = '';
}
function listMsg(data) {
var msg_list = document.getElementById("msg_list");
var msg = document.createElement("p");
msg.innerHTML = data;
msg_list.appendChild(msg);
msg_list.scrollTop = msg_list.scrollHeight;
}
function dealUser(user_name, type, name_list) {
var user_list = document.getElementById("user_list");
var user_num = document.getElementById("user_num");
while(user_list.hasChildNodes()) {
user_list.removeChild(user_list.firstChild);
}
for (var index in name_list) {
var user = document.createElement("p");
user.innerHTML = name_list[index];
user_list.appendChild(user);
}
user_num.innerHTML = name_list.length;
user_list.scrollTop = user_list.scrollHeight;
var change = type == 'login' ? 'online' : 'offline';
var data = 'system:' + user_name + ' is' + change;
listMsg(data);
}
function sendMsg(msg) {
var data = JSON.stringify(msg);
ws.send(data);
}
</script>
on GCE VM:
update
internal IP: .3
external IP: .62
1.
netstat -an | grep "LISTEN " to check if you configured internal IP instead of localhost or/and 127.0.0.1
.
I change my internal IP in the server.php and run.
It looks like working perfectly.
2.
Connection check from the GCE VM to GCE_VM_INTERNAL_IP:8080.
.
Connect successfully!
3.
Connection check from you personal computer to
GCE_VM_EXTERNAL_IP:8080. Also, consider to use curl instead of
telnet
.
It seems that handshaking can work.
I can get websocket message from GCE with internal IP and PC with external IP.
So my problem is maybe like in javascript?
It doesn't send the handshaking frame.

How to get http response in php ratchet

I am going to build a system which will receive a streaming raw data form browser. Data will use websocket to transmit and receive, then system will keep going to send chunk data to HTTP server. Flowchart show below:
First, I separate websocket server and HTTP client into 2 program, both can work. websocket server use ratchet, HTTP client use stream_socket_client and stream_select.
Then, I try to combine websocket server and HTTP client together, I can receive data from browser but I cannot get any response from HTTP server. How can I get HTTP response in Ratchet? Many Thanks.
The following is my php code:
Chat.php
<?php
namespace MyApp;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
function read_response_code($response){
foreach (explode("\n", $response) as $a) {
if (strpos($a, 'HTTP/1.1') !== false) {
$arr = explode(" ", $a);
if ($arr[1] != "100")
{
return 0;
}
return 1;
}
}
return 0;
}
class Socket implements MessageComponentInterface {
protected $clients;
public function __construct(){
$this->clients = new \SplObjectStorage;
$this->SERVER = "tcp://192.168.0.1:80";
$this->socket = [];
$this->clients->connect = 0;
}
public function onOpen(ConnectionInterface $conn) {
// Store the new connection to send messages to later
$this->clients->attach($conn);
echo "New connection! ({$conn->resourceId})\n";
echo "Try to connect http server...\n";
$this->socket = stream_socket_client($this->SERVER, $errno, $errstr, 30);
if (!$this->socket){
//disconnect websocket
$conn->close();
}
else{
$header = "POST / HTTP/1.1\r\n"
. "Host: 192.168.0.1\r\n"
. "Accept: */*\r\n"
. "Content-Type: application/octet-stream\r\n"
. "Transfer-Encoding: chunked\r\n"
. "Expect: 100-continue\r\n\r\n";
$written = fwrite($this->socket, $header);
$response = fread($this->socket, 100);
$ret = read_response_code($response);
if ($ret == 0)
{
echo "Connect HTTP server fail.\n";
$conn->close();
}
else
{
echo "Connect success!!!!\n";
$this->clients->connect = 1;
}
}
}
public function onMessage(ConnectionInterface $from, $msg) {
//combine http client
if ($this->clients->connect == 1)
{
$read = array($this->socket);
$write = NULL;
$except = NULL;
$num = stream_select($read, $write, $except, 0, 400000);
if ($num === false) {
/* Error handling */
}
elseif ($num > 0) {
// cannot read any response
echo "xxxxxxxxxxxxxx";
}
else {
// send data to HTTP server
$size = strlen($msg);
$hex = dechex($size);
fwrite($this->socket, "$hex\r\n");
$written = fwrite($this->socket, $msg);
fwrite($this->socket, "\r\n");
}
}
}
public function onClose(ConnectionInterface $conn) {
// The connection is closed, remove from connection list
$this->clients->detach($conn);
echo "Connection {$conn->resourceId} has disconnected\n";
}
public function onError(ConnectionInterface $conn, \Exception $e) {
echo "An error has occurred: {$e->getMessage()}\n";
$conn->close();
}
}
Chat-server.php
<?php
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use MyApp\Chat;
require dirname(__DIR__) . '/vendor/autoload.php';
$loop = \React\EventLoop\Factory::create();
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Socket()
)
),
8080
);
$server->run();
HTTP_client.php
<?php
$SERVER = "tcp://192.168.0.1:80";
$SEND_STATUS = 0;
$file = fopen("test.raw", "rb");
$socket = stream_socket_client($SERVER, $errno, $errstr, 30);
$header = "POST / HTTP/1.1\r\n"
. "Host: 192.168.0.1\r\n"
. "Accept: */*\r\n"
. "Content-Type: application/octet-stream\r\n"
. "Transfer-Encoding: chunked\r\n"
. "Expect: 100-continue\r\n\r\n";
$written = fwrite($socket, $header);
$response = fread($socket, 100);
function send_data($file, $socket, $bytes) {
global $SEND_STATUS;
if ( feof($file) ) {
$SEND_STATUS = 1;
fwrite($socket, "0\r\n\r\n");
fclose($file);
return(false);
}
$buffer = fread($file, $bytes);
$size = strlen($buffer);
$hex = dechex($size);
fwrite($socket, "$hex\r\n");
$written = fwrite($socket, $buffer);
fwrite($socket, "\r\n");
}
while (true) {
$read = array($socket);
$write = NULL;
$except = NULL;
$num = stream_select($read, $write, $except, 0, 400000);
if ($num === false) {
/* Error handling */
}
elseif ($num > 0) {
foreach ($read as $r) {
echo "xxxxxxxxx";
}
}
else {
if ( $SEND_STATUS === 0 ) {
send_data($file, $socket, 16000);
}
}
}
?>

issue in web-socket php

I have used WebSocket in PHP. but somehow it will close after some time(so many requests).
Is it anyway to handle it?
We got following error when we try to run it after stop:
socket_bind(): unable to bind address [10013]: An attempt was made to
access a socket in a way forbidden by its access permissions.
in C:\wamp64\www\Websocket\server.php on line 52
Warning: socket_listen(): unable to listen on socket [10022]: An invalid argument was supplied.
in C:\wamp64\www\Websocket\server.php on line 55
Here is my code:
<?php
set_time_limit(0);
error_reporting(E_ALL);
//include 'Triangulate.php';
$filename = 'logs.txt';
class Values
{
public $distance;
public $rasp_id;
public $rssi;
}
$host = '10.37.54.167'; //host
$port = '9000'; //port
$null = null; //null var
$rasp = array(
47 => array(17, 0),
124 => array(1,6.4),
43 => array(1,0),
44 => array(4.6,2));
//Create TCP/IP sream socket
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
//reuseable port
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
//bind socket to specified host
socket_bind($socket, 0, $port);
//listen to port
socket_listen($socket);
//create & add listning socket to the list
$clients = array($socket);
$distance = array();
$totalbicken = array(array());
//start endless loop, so that our script doesn't stop
while (true) {
//manage multipal connections
$changed = $clients;
//returns the socket resources in $changed array
socket_select($changed, $null, $null, 0, 10);
$fp = fopen($filename, 'a+');
//check for new socket
if (in_array($socket, $changed)) {
$socket_new = socket_accept($socket); //accpet new socket
$clients[] = $socket_new; //add socket to client array
$header = socket_read($socket_new, 1024); //read data sent by the socket
perform_handshaking($header, $socket_new, $host, $port); //perform websocket handshake
socket_getpeername($socket_new, $ip); //get ip address of connected socket
$response = mask(json_encode(array('type' => 'system', 'message' => $ip . ' connected'))); //prepare json data
fwrite ($fp,$response . "\n");
// send_message($response); //notify all users about new connection
// send_message_socket($response, $socket_new);
//make room for new socket
$found_socket = array_search($socket, $changed);
unset($changed[$found_socket]);
}
//loop through all connected sockets
foreach ($changed as $changed_socket) {
//check for any incomming data
try {
while (socket_recv($changed_socket, $buf, 1024, 0) >= 1) {
$received_text = unmask($buf); //Unmask Recive data.
fwrite ($fp,"Text receive:" . $received_text . "\n");
$tst_msg = json_decode($received_text); //json decode.
fwrite ($fp,"Json Decord!". "\n");
if (!isset($tst_msg->action)) {
} else {
$user_action = $tst_msg->action; //sender name.
if ($user_action == "distance") { //If action is distance.
$rasp_id = $tst_msg->rasp_id; //get raspberry uniq id.
$beacon_id = $tst_msg->beacon_id; //get beacon id
$distance_temp = $tst_msg->distance; // get distance
$rssi = $tst_msg->rssi; //get RSSI.
fwrite ($fp,isset($distance[$beacon_id]). "\n");
fwrite ($fp,"Get all values!". "\n");
// echo mask(json_encode(array('type'=>'message', 'action'=>'distance', 'beacon_id'=>$beacon_id, 'rasp_id'=>$rasp_id, 'distance'=>$distance)));
if (isset($distance[$beacon_id])) {
$totalbicken[$beacon_id] = count($distance[$beacon_id]); //get total distance of sender beacon
} else {
$totalbicken[$beacon_id] = 0;
}
if (isset($rasp[$rasp_id])) {
echo "\nRequest from: " . $rasp_id;
$myVal = new Values();
$myVal->distance = $distance_temp;
$myVal->rasp_id = $rasp_id;
$myVal->rssi = $rssi;
$flag = false;
if (isset($distance[$beacon_id])) {
if (count($distance[$beacon_id]) > 0) {
for ($i = 0; $i < count($distance[$beacon_id]); $i++) {
$myTempVal = $distance[$beacon_id][$i];
if (($myTempVal->rasp_id) == $rasp_id) {
$flag = true;
$distance[$beacon_id][$i] = $myVal;
break;
}
}
if (!$flag) {
$distance[$beacon_id][$totalbicken[$beacon_id]] = $myVal;
}
} else {
$distance[$beacon_id][$totalbicken[$beacon_id]] = $myVal;
}
} else {
$distance[$beacon_id][$totalbicken[$beacon_id]] = $myVal;
}
if (count($distance[$beacon_id]) > 2) {
/*$data = triangulate($rasp[$distance[$beacon_id][0]->rasp_id], $distance[$beacon_id][0]->distance,
$rasp[$distance[$beacon_id][1]->rasp_id], $distance[$beacon_id][1]->distance,
$rasp[$distance[$beacon_id][2]->rasp_id], $distance[$beacon_id][2]->distance);*/
fwrite ($fp,"Before Triangulation!". "\n");
$data = getTrilateration($rasp[$distance[$beacon_id][0]->rasp_id], $distance[$beacon_id][0]->distance,
$rasp[$distance[$beacon_id][1]->rasp_id], $distance[$beacon_id][1]->distance,
$rasp[$distance[$beacon_id][2]->rasp_id], $distance[$beacon_id][2]->distance);
fwrite ($fp,"End Triangulation!". "\n");
$response_text = mask(json_encode(array('type' => 'message', 'action' => 'distance',
'beacon_id' => $beacon_id, 'distance' => $distance[$beacon_id], 'coordinates' => $data)));
fwrite ($fp,"Response: ". $response_text . "\n");
send_message($response_text);
}
}
}
fwrite ($fp,"Break!: ". "\n");
break 2; //exist this loop*/
}
}
} catch (Exception $e) {
fwrite ($fp,"Exception: done! \n");
fwrite ($fp,"Exception: ". $e->getMessage(). "\n");
echo "Exception:" . $e->getMessage();
}
$buf = #socket_read($changed_socket, 1024, PHP_NORMAL_READ);
if ($buf === false) { // check disconnected client
// remove client for $clients array
try {
$found_socket = array_search($changed_socket, $clients);
socket_getpeername($changed_socket, $ip);
unset($clients[$found_socket]);
//notify all users about disconnected connection
$response = mask(json_encode(array('type' => 'system', 'message' => $ip . ' disconnected')));
send_message($response);
} catch (Exception $e) {
echo "Exception:" . $e;
}
}
}
}
// close the listening socket
socket_close($socket);
$fclose ($fp);
function send_message($msg)
{
global $clients;
foreach ($clients as $changed_socket) {
#socket_write($changed_socket, $msg, strlen($msg));
}
return true;
}
function send_message_socket($msg, $changed_socket)
{
#socket_write($changed_socket, $msg, strlen($msg));
return true;
}
//Unmask incoming framed message
function unmask($text)
{
$length = ord($text[1]) & 127;
if ($length == 126) {
$masks = substr($text, 4, 4);
$data = substr($text, 8);
} elseif ($length == 127) {
$masks = substr($text, 10, 4);
$data = substr($text, 14);
} else {
$masks = substr($text, 2, 4);
$data = substr($text, 6);
}
$text = "";
for ($i = 0; $i < strlen($data); ++$i) {
$text .= $data[$i] ^ $masks[$i % 4];
}
return $text;
}
//Encode message for transfer to client.
function mask($text)
{
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($text);
if ($length <= 125) {
$header = pack('CC', $b1, $length);
} elseif ($length > 125 && $length < 65536) {
$header = pack('CCn', $b1, 126, $length);
} elseif ($length >= 65536) {
$header = pack('CCNN', $b1, 127, $length);
}
return $header . $text;
}
//handshake new client.
function perform_handshaking($receved_header, $client_conn, $host, $port)
{
$headers = array();
$lines = preg_split("/\r\n/", $receved_header);
foreach ($lines as $line) {
$line = chop($line);
if (preg_match('/\A(\S+): (.*)\z/', $line, $matches)) {
$headers[$matches[1]] = $matches[2];
}
}
$secKey = $headers['Sec-WebSocket-Key'];
$secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
//hand shaking header
$upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"WebSocket-Origin: $host\r\n" .
"WebSocket-Location: ws://$host:$port/Websocket/shout.php\r\n" .
"Sec-WebSocket-Accept:$secAccept\r\n\r\n";
socket_write($client_conn, $upgrade, strlen($upgrade));
}
Thanks in advance!
I have setup Linux environment and test. It is working fine. It might a firewall issue in windows.
As per my knowledge, the newer version of windows (after service pack-3) has some of the RPC rules for connection (Limit of HTTP requests and connection in second) so, that might be an issue.
Please read this.
As of now, change the operating system is the one of a solution.
Thanks & Regards
Jignesh M. Mehta

socket_select() not a valid socket

I got this error:
Warning: socket_select(): supplied argument is not a valid Socket resource in /volume1/web/is/xxxx/listen-new.php on line 12
PHP Warning: socket_select(): supplied argument is not a valid Socket resource in /volume1/web/is/xxxx/listen-new.php on line 12
this my snippet code
My code is:
$port = $this->port;
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($sock, 0, $port);
socket_listen($sock);
$this->clients[] = $sock;
$data = array();
while (true) {
$read = $this->clients;
$write = array(); //NULL
$except = array();//NULL
$sckt = socket_select($read, $write, $except, 0);
if($sckt === false){
echo "socket_select() failed, reason: " .
socket_strerror(socket_last_error()) . "\n";
}
elseif($sckt > 0) {
if (in_array($sock, $read)) {
$this->clients[] = $newsock = socket_accept($sock);
//var_dump($this->gps);
socket_write($newsock, "Connected\n");
//var_dump($this->gps);
/**try{
socket_getpeername($newsock, $ip); //error
echo "New client connected: {$ip}\n";
}
catch(Exception $e){
echo "error : $e->getMessage()\n";
}**/
$key = array_search($sock, $read);
unset($read[$key]);
}
foreach ($read as $read_sock) {
$data = #socket_read($read_sock, 2048);
if ($data === false) {
$gpsdisc = array_search($read_sock, array_column($this->gps, 'pid'));
$key = array_search($read_sock, $this->clients);
unset($this->clients[$key]);
unset($this->gps[$gpsdisc]);
echo "client disconnected.\n";
continue;
}
else{
$data = trim($data);
if (!empty($data)) {
var_dump($data);
$buf = bin2hex($data);
$start = substr($buf, 0,4);
if($start=="7878"){
$protocol = substr($buf, 6,2);
if($protocol=="01"){
$imei = substr($buf, 8,16);
$cariGPS = $this->cariGPS($imei);
if($cariGPS!=NULL){
$this->setGPS($imei,$read_sock,$cariGPS);
$reply = $this->authLogin($data);
$rep = hex2bin("$reply");
socket_write($read_sock, $rep, strlen($rep));
}
else
echo "$imei salah";
}
elseif($protocol=="15"){
//echo "$buf\n";
$this->reply($data);
}
elseif($protocol=="12"){
$hex12 = bin2hex($data);
//echo "$hex12\n";
}
else{
$hex12 = bin2hex($data);
echo "$hex12\n";
}
echo "$protocol\n";
}
else{
if($data=="where"){
//echo $data."\n";
$this->where($this->gps);
}
elseif($data=="quit"){
$gpsdisc = array_search($read_sock, array_column($this->gps, 'pid'));
unset($this->gps[$gpsdisc]);
socket_close($read_sock);
$key = array_search($read_sock, $this->clients);
unset($this->clients[$key]);
}
else{
echo "command not found\n";
}
}
}
}
}
}
}
socket_close($sock);
PS I also had to change $write = null and $except = null
Are there any solution for this?
It looks like you supplied only the server code but omitted the client code. Can you post the client code please? I guess the problem is there. With my test client (fyi I used socket_create) I cannot reproduce the problem you are reporting.
Also mine is php7 (if you are curious).
This may have some hints for you: Socket_read() says "not a valid resource"

Azure Notification Hubs REST API with PHP

I'm trying to create a SharedAccessSignature for the Azure Notifications Hubs API in PHP.
I keep getting the error "Invalid authorization token signature".
Anyone has an example of creating the SAS in PHP 5.4+?
There is some documentation of the API on: http://msdn.microsoft.com/en-us/library/dn170477.aspx, but some people say that the implementation differs from the documentation.
This is my failing implementation:
private static function get_authentication_header()
{
$uri = "https://x.servicebus.windows.net/x";
$expiry = time() + (60*60);
$string = utf8_encode(urlencode($uri) . "\n" . $expiry);
$keyname = "DefaultFullSharedAccessSignature";
$key = base64_decode(static::HUB_KEY);
$signature = base64_encode(hash_hmac('sha256', $string, $key));
$sas = 'SharedAccessSignature sig=' . $signature . '&se=' . $expiry . '&skn=' . $keyname . '&sr=' . urlencode($uri);
return $sas;
}
Here is a simple wrapper to send notifications to Notification Hubs with PHP.
<?php
include 'Notification.php';
class NotificationHub {
const API_VERSION = "?api-version=2013-10";
private $endpoint;
private $hubPath;
private $sasKeyName;
private $sasKeyValue;
function __construct($connectionString, $hubPath) {
$this->hubPath = $hubPath;
$this->parseConnectionString($connectionString);
}
private function parseConnectionString($connectionString) {
$parts = explode(";", $connectionString);
if (sizeof($parts) != 3) {
throw new Exception("Error parsing connection string: " . $connectionString);
}
foreach ($parts as $part) {
if (strpos($part, "Endpoint") === 0) {
$this->endpoint = "https" . substr($part, 11);
} else if (strpos($part, "SharedAccessKeyName") === 0) {
$this->sasKeyName = substr($part, 20);
} else if (strpos($part, "SharedAccessKey") === 0) {
$this->sasKeyValue = substr($part, 16);
}
}
}
private function generateSasToken($uri) {
$targetUri = strtolower(rawurlencode(strtolower($uri)));
$expires = time();
$expiresInMins = 60;
$expires = $expires + $expiresInMins * 60;
$toSign = $targetUri . "\n" . $expires;
$signature = rawurlencode(base64_encode(hash_hmac('sha256', $toSign, $this->sasKeyValue, TRUE)));
$token = "SharedAccessSignature sr=" . $targetUri . "&sig="
. $signature . "&se=" . $expires . "&skn=" . $this->sasKeyName;
return $token;
}
public function broadcastNotification($notification) {
$this->sendNotification($notification, "");
}
public function sendNotification($notification, $tagsOrTagExpression) {
echo $tagsOrTagExpression."<p>";
if (is_array($tagsOrTagExpression)) {
$tagExpression = implode(" || ", $tagsOrTagExpression);
} else {
$tagExpression = $tagsOrTagExpression;
}
# build uri
$uri = $this->endpoint . $this->hubPath . "/messages" . NotificationHub::API_VERSION;
echo $uri."<p>";
$ch = curl_init($uri);
if (in_array($notification->format, ["template", "apple", "gcm"])) {
$contentType = "application/json";
} else {
$contentType = "application/xml";
}
$token = $this->generateSasToken($uri);
$headers = [
'Authorization: '.$token,
'Content-Type: '.$contentType,
'ServiceBusNotification-Format: '.$notification->format
];
if ("" !== $tagExpression) {
$headers[] = 'ServiceBusNotification-Tags: '.$tagExpression;
}
# add headers for other platforms
if (is_array($notification->headers)) {
$headers = array_merge($headers, $notification->headers);
}
curl_setopt_array($ch, array(
CURLOPT_POST => TRUE,
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_SSL_VERIFYPEER => FALSE,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POSTFIELDS => $notification->payload
));
// Send the request
$response = curl_exec($ch);
// Check for errors
if($response === FALSE){
throw new Exception(curl_error($ch));
}
$info = curl_getinfo($ch);
if ($info['http_code'] <> 201) {
throw new Exception('Error sending notificaiton: '. $info['http_code'] . ' msg: ' . $response);
}
//print_r($info);
//echo $response;
}
}
?>
I do not know if you wanted to send pushes or to do registration management. It is not hard to modify the above to do registration management as shown in the NH REST APIs (remember the order in the xml documents matters!): http://msdn.microsoft.com/en-us/library/dn223264.aspx.
Let me know if you still run into problems.
Elio

Categories