socket_select() not a valid socket - php

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"

Related

How to reject duplicate PHP socket connection from the same client?

I want to reject duplicate socket connection when the same connected client try to connect again.
The below code I tried to store gamerId into an array then later check the array if new gamerId already exist or not. But seems the duplicate connection already made but I don't want to make any duplicate connection.
$address = '127.0.0.5';
$port = 8085;
$sock = socket_create(AF_INET, SOCK_STREAM, 0) or die('Not Created');
$bind = socket_bind($sock, $address, $port) or die("Not Binded");
$listen = socket_listen($sock, 1) or die("Didnot listen");
$accept = socket_accept($sock) or die("Not Accepted");
$readData = trim(socket_read($accept, 1024));
$gamerId = array();
$errHandler = array();
$gamerIdlen = count($gamerId);
function checkDuplicate($gamerId, $gamerIdLen, $readData, $errHandler)
{
for ($i = 0; $i < $gamerIdLen; $i++) {
if ($gamerId[$i] === $readData) {
return 1;
}
}
}
if (checkDuplicate($gamerId, $gamerIdlen, $readData, $errHandler) == 1) {
array_push($errHandler, "exist");
} else if (checkDuplicate($gamerId, $gamerIdlen, $readData, $errHandler) != 1) {
array_push($gamerId, $readData);
}
do {
global $accept;
$accept = socket_accept($sock) or die("Not Accepted");
print_r($errHandler);
print_r($gamerId);
} while (true);
Keep a map of sockets to identities and close a (new) socket after identifying, when an identity is already in the map.
$map = [
[socket1] => User(123),
[socket1] => User(124),
];
<?php
$address = '127.0.0.5';
$port = 8085;
$server = socket_create(AF_INET, SOCK_STREAM, 0) or die('Not Created');
socket_bind($server, $address, $port) or die("Not Binded");
socket_listen($server, 10) or die("Did not listen");
// clients before checking gamerId
$pending = [];
// accepted clients
$clients = [];
// gamerId list
$gamerIds = [];
// gamerId for socket
$clientsIds = new WeakMap();
echo "Listening...\n";
do {
// wait for new client and new data on sockets
$read = [$server, ...$pending, ...$clients];
$write = null;
$error = null;
if(socket_select($read, $write, $error)){
foreach($read as $socket){
if($socket === $server){
// new connection
$pending[] = socket_accept($server);
printf("New Socket connected\n");
} else if(in_array($socket, $pending, true)) {
// data for pending connection
$readData = socket_read($accept, 1024);
// remove key from pending
if (($key = array_search($socket, $pending, true)) !== false) {
array_splice($pending, $key, 1);
}
// client disconnected already
if($readData === false){
printf("Pending client disconnected #%d\n", (int)$socket);
socket_close($socket);
unset($socket);
continue;
}
// here should be something to extract gamerId (e.g. make sure it is X characters)
$readData = trim($readData);
if(in_array($readData, $gamerIds, true)){
printf("Pending client already connected #%d, blocked...\n", (int)$socket);
// close connection
socket_close($socket);
unset($socket);
} else {
printf("Pending client accepted #%d\n", (int)$socket);
// accept client
$clients[] = $socket;
$gamerIds[] = $readData;
$clientsIds[$socket] = $readData;
}
} else {
// client communication
$readData = socket_read($accept, 1024);
if($readData === false){
printf("Client disconnected #%d\n", (int)$socket);
// remove client
if (($key = array_search($socket, $clients, true)) !== false) {
array_splice($clients, $key, 1);
}
// remove gamerId from the list
if(isset($clientsIds[$socket])){
if (($key = array_search($clientsIds[$socket], $gamerIds, true)) !== false) {
array_splice($gamerIds, $key, 1);
}
}
socket_close($socket);
unset($socket);
} else {
// handle data...
printf("Data received from socket #%d\n", (int)$socket);
}
}
}
}
} while (true);

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

How to avoid my script to freeze

I have socket server script that continuously running listening for the GPS device that runs in PHP CLI,my problem is that my socket will freeze if it executes long time,how do I prevent this so that my script will not freeze.I have no idea on this socket.this is the first time that I use socket connection.I created variable to check if it lapses to 5 mins,then I break the loop and start it over.I don't know if this is the correct to handle this or to prevent freezing.
I appreciate someone can help my problem.
I updated my code
<?php
error_reporting(-1);
ini_set('display_errors', 1);
set_time_limit (0);
for(;;){
$FIVE_MINUTES = 300000000;
$TIME_TO_EXIT = 0;
$address_server = 'xxx.xxx.xx.xx';
$port_server = xxxx;
$isTrue = true;
socketfunction($address_server,$port_server,$isTrue,$TIME_TO_EXIT, $FIVE_MINUTES);
}
function socketfunction($address,$port,$done){
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($sock, $address, $port);
socket_listen($sock);
$clients = array($sock);
while ($done ) {
$file = fopen('txt.log','a');
$read = $clients;
$write = NULL;
$except = NULL;
$tv_sec = 0;
$TIME_TO_EXIT++;
if(TIME_TO_EXIT>$FIVE_MINUTES){
$done =false;
break 2;//exit while loop
}
if (socket_select($read, $write , $except, $tv_sec) < 1){
continue;
}
// checking client
if (in_array($sock, $read)) {
$clients[] = $newsock = socket_accept($sock);
$key = array_search($sock, $read);
unset($read[$key]);
}
//handle client for reading
foreach ($read as $read_sock) {
$data = #socket_read($read_sock, 1024, PHP_NORMAL_READ);
if ($data === false) {
$key = array_search($read_sock, $clients);
unset($clients[$key]);
echo "client disconnected.\n";
echo "Remaining ".(count($clients) - 1)."client(s) connected\r\n";
continue;
}
$data = trim($data);
if (!empty($data)) {
echo("Returning stripped input\n");
fwrite($file,$data."\n");
}
} // end of reading foreach
fclose($file);
}//end while
socket_close($sock);
}
?>
Thank you in advance.
From what I see in the code that you have included in your question, you never change the value of $done so your while-loop will run forever.
So what to do is to change the value of $done to false when you have achieved what you wanted with your call. So for example after fwrite() you write:
$done = false;

how to accept multiple connection to the device

I am creating a socket script that will listen to our 3 devices.and the device is setup in one server ip and one port only.
$file = fopen('txt.log','a+');
$server = stream_socket_server('tcp://'.$ipserver.':'.$port, $errno, $errorMessage);
if(!$server) {
echo "$errorMessage ($errno)<br />\n";
}
else{
while($client = #stream_socket_accept($server,$timeout)) {
stream_copy_to_stream($client, $file);
fclose($file);
fclose($client);
}
}
but the problem is that if one device is connected,the two devices cannot connect anymore.I appreciate some one can help me how to get this work.or give me some idea
Thank you in advance.
$file = fopen('txt.log', 'a+');
$server = stream_socket_server("tcp://$ipserver:$port", $errno, $errorMessage);
if (!$server)
echo "$errorMessage ($errno)<br />\n";
else
{
$s = array($server);
$t = $timeout == -1 ? NULL : $timeout;
while ($r = $s and stream_select($r, $n=NULL, $n=NULL, $t))
foreach ($r as $stream)
if ($stream == $server) // new client
$s[] = stream_socket_accept($server, -1);
else
if (!fputs($file, fgets($stream)))
{
fclose($stream);
array_splice($s, array_search($stream, $s), 1);
}
}

stream_select error:Strict Standards

I create some socket with stream_socket_client(), and put them in a array named $sockets.
When I run the code, an error is coming:
Strict Standards: Only variables should be passed by reference in
D:\www\study\cl\s.php on line 63
Code:
while (count($sockets)) {
$read = $write = $sockets;
stream_select($read, $write, $e = null, $timeout); //line 63
if (count($read)) {
foreach ($read as $r) {
$id = array_search($r, $sockets);
$data = fgets($r, 1024);
echo $data;
if (strlen($data) == 0) {
if ($status[$id] == "in progress") {
$status[$id] = "failed to connect";
}
fclose($r);
unset($sockets[$id]);
} else {
$status[$id] .= $data;
}
}
foreach ($write as $w) {
$id = array_search($w, $sockets);
fwrite($w, "HEAD / HTTP/1.0rnHost: " . $host . "rnrn");
$status[$id] = "waiting for response";
}
} else {
foreach ($sockets as $id => $s) {
$status[$id] = "timed out " . $status[$id];
}
break;
}
}
This line:
stream_select($read, $write, $e = null, $timeout);
should be:
$e=null;
stream_select($read, $write, $e, $timeout);
While the first code will work, PHP will throw the E_STRICT message. I'm not sure why the PHP developers decided so.
However, you should check the return type of stream_select():
$ret = stream_select($read, $write, $e, $timeout);
if($ret === FALSE) {
die('Error: stream_select');
}
Once you are checking the return type, you can also use the silence operator #:
$ret = #stream_select($read, $write, $e = NULL, $timeout);
if($ret === FALSE) {
die('Error: stream_select');
}

Categories