Make persistent connection in php socket to avoid too many apache instances - php

I have a page that contains a picture. The picture should refresh every second. I have a socket.php file that creates a link to a c++ program and asks for a picture and then put it as output. I have a js code that asks socket.php for an image every second.
So
every second my js code in clients browser, asks socket.php on my server to send the user a new picture and socket.php asks my c++ code for a picture, receive the picture and pass it to the client browser.
every thing is ok.
but when I change the interval from 1 second to 50 miliseconds, the number of "apache2" processes on my server goes really up. I mean about 200 apache2 processes and this uses too much ram memory on my server.
My question is: what should I do to make a have a persistent connection between php and c++ , so for every query from user, a new connection doesn't create? Does a persistent connection help to avoid this number of apache processes?
This is my socket.php file:
if(isset($_GET['message']))
$message = $_GET['message'];
else $message = "-1";
$host = "127.0.0.1";
$port = 12345;
$socket = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n");
$result = socket_connect($socket, $host, $port) or die("Could not connect to server\n");
socket_write($socket, $message, strlen($message)) or die("Could not send data to server\n");
$b= '';
$buf = '';
while(true)
{
$bytes = socket_recv($socket, $buf, 2048, 0);
if($bytes==0) break;
$b .= $buf;
}
$im = imagecreatefromstring($b);
header('Content-Type: image/jpeg');
imagejpeg($im);
imagedestroy($im);
This is my js code:
function updateImage()
{
if(!isPaused)
{
if(newImage.complete) {
document.getElementById("myimg").src = newImage.src;
newImage = new Image();
newImage.src = "socket.php?message=0&image" + count++ + ".jpg";
}
setTimeout(updateImage, 50);
}
}

60 calls in a min it's nothing and 200 too. I think problem is you don't close socket.
the best approach is make you c++ update mysql DB every second and page should ask for updated image from DB, like this you will gain flexibility.
At that point you also can do cashing of the image
Also you can attach as much image users as you want without opening the new sockets and without C++ application calling.

As far as I can tell, one really cannot persist a connection from an Apache instance of PHP (e.g. mod_php) to another service, except for database connections (e.g. all of those supported by PDO). #volkinc's link to how PHP executes is a pretty good example which illustrates where such a persistent link would have to cached/stored by PHP, but is not.

Related

PHP sockets multiple clients read/write

I would have a question about parallel socket connections in PHP.
I'm not a socket expert, that's why I'm asking this question here.
I created a library which is capable to persist data (string/int/float/array/object or anything that is losslessly serializable), like a cache, in PHP. I provided a part of my code, which I think causes the problem, but if you need additional info, visit: https://github.com/dude920228/php-cache
The concept was:
Create a TCP socket server
Accept connections
Read a serialized PHP array from the connecting client
Call the action handler of the action that is received from the client and do some stuff with the data is sent if necessary or write back to the client
Close the connection on the client side
It works like a charm with like 25 parallel connections, but for some reason, the clients do not receive the data they should get. At 100 parallel connections, only kinda half of the clients get the data. The program does not emit any errors and the only error control operator I use is at the socket_accept call in the main loop. The main loop looks like this:
public function run()
{
$this->socket = $this->ioHandler->createServerSocket();
while ($this->running) {
$this->maintainer->checkBackup(time(), $this->bucket);
$this->maintainer->maintainBucket($this->bucket);
if (($connection = #socket_accept($this->socket))) {
$clientId = uniqid();
socket_set_nonblock($connection);
$this->clients[$clientId] = $connection;
$read = $this->clients;
$write = array();
$except = array();
socket_select($read, $write, $except, null);
$dataString = $this->ioHandler->readFromSocket($connection);
$data = unserialize($dataString);
($this->actionHandler)($data, $this->bucket, $this->ioHandler, $connection);
$this->ioHandler->closeSocket($connection);
unset($this->clients[$clientId]);
}
}
$this->close();
}
Am I misusing the socket_select call there? Or is the problem in an other class? Thanks in advance for the answers!

Is there a way to ping MSSQL database before connecting to it

The connection to the database is very fragile, so I try to test the connection before make a link to it. I found pg_connect and mysql_ping and how-do-i-ping-the-mysql-db-and-reconnect-using-pdo, but none has anything to do with MSSQL or function that I can use.
Is there a way I can test the database before I connect to it?
You might set the timeout to a very small number and call something like
SELECT 1;
or
SELECT GETDATE();
and see, if there is some result coming back...
If the connection is broken, such tiny requests should break as well.
In case fragile does not mean broken, you might measure a standard call and compare the execution speed...
You could try to ping the server + corresponding port to see if server accepts connections.
$host = '127.0.0.1'; // ip address, could be localhost
$port = 1433; // your mssql port
$timeout = 1; //time to wait in seconds for response
if($fp = fsockopen($host,$port,$errCode,$errStr,$timeout))
{
// Server is OK - responding
} else {
// Server not respoded on given port in given time limit
}
fclose($fp);

How to redirect to another localhost when "Unable to connect Firefox can't establish a connection to the server at ''some ip

I have created a webservice with php for my android application, in the header of the php I have given the code
header("Location: http://123.123.123.123/Main/sub.php?details=".$rawdata);
Please note that this is a closed network ip, this ip can only be accessed from the same network so when I change the WIFI network to another, I need to change the above code as
header("Location: http://123.123.123.124/Main/sub.php?details=".$rawdata);
If dont change it I will get the error message as "Unable to connect Firefox can't establish a connection to the server at 123.123.123.123"
What I want is that when I switch network from A to B, instead of the above error page I want the page to be redirected to the location specified in the second code. Somebody please help
I am using apache2 in ubuntu.
You can do it by putting simple check for checking weather host is accessible or not.
$host = 'http://123.123.123.123';
// Number of seconds to wait for a response from remote host
$timeout = 2;
// TCP port to connect to
$port = 80;
// Try and connect
if ($sock = fsockopen($host, $port, $errNo, $errStr, $timeout)) {
// Connected successfully
$up = TRUE;
fclose($sock); // Drop connection immediately for tidiness
} else {
// Connection failed
$up = FALSE;
}
if ($up) {
header("Location: http://123.123.123.123/Main/sub.php?details=".$rawdata);
}
else {
header("Location: http://123.123.123.124/Main/sub.php?details=".$rawdata);
}
by this check you can easily redirect the location accordingly. you can change the timeout as per your script execution time.
You can use $_SERVER["REMOTE_ADDR"] to determine IP address of the client. This should let you perform the redirect as needed. ip2long is quite useful in this context, e.g.:
if ((ip2long($_SERVER['REMOTE_ADDR']) & 0xffffff00) == ip2long('123.123.123.0')) {
header("Location: http://123.123.123.124/Main/sub.php?details=".$rawdata);
} else {
header("Location: http://123.123.123.123/Main/sub.php?details=".$rawdata);
}
ip2long converts the IP address from dotted notation into long. This will let you perform bitwise operations which make subnet matching very straight-forward.
Of course I'd suggest you avoid hardcoding any IP ranges or addresses into your code. Have them stored in a database or somewhere else where they can be easily maintained when things changes.

Notifications of new messages. Long polling

Help me please to realise notifications of new messages for users.
Now i have this client code:
function getmess(){
$.ajax({
url:"notif.php",
data:{"id":id},
type:"GET",
success:function(result){
$("#count").html(result);
setTimeout('getmess',10000);
}
});
}
and this server code:
$mysqli = new mysqli('localhost', 'root', '', 'test');
if (mysqli_connect_errno()) {
printf("error: %s\n", mysqli_connect_error());
exit;
}
session_start();
$MY_ID = $_SESSION['id'];
while (true) {
$result = $mysqli->query("SELECT COUNT(*) FROM messages WHERE user_get='$MY_ID'");
if (mysqli_num_rows($result)) {
while ($row = mysqli_fetch_array($result)) {
echo $row[0]."";
}
flush();
exit;
}
sleep(5);
}
I have the problem that this script is not updating in real time when new message was added to database. But if I press button with onclick="getmess();" it works.
First, you check your database every 5 seconds, so you can't achieve real time - you have at least 5 seconds delay.
And second, there is no way you can achieve real-time by polling.
The way to deliver notifications nearly real time is to send the message by the same code that inserts into the database, e.g. you should not query the database for new records, but when there is a new record to send the data to the client. Even with a long-polling as a transport protocol.
How to achieve this? Unfortunately PHP is not a good choice. You need a non-blocking server to hold the connection, you need to know which connection waits for what data and you need a way from PHP (your backend) to notify this connection.
You can use the tornado-web server, node.js or nginx to handle the connections. You assign an identifier to each connection (probably you already have one - the userid), and when there is a new record added - the PHP script performs HTTP request to the notification server (tornado, node.js, nginx) saying what data to which user does this.
For nginx, take a look at nginx push stream

Socket_set_nonblock error

Ok so i have a class that uses while(true) and it connects using a socket. Now my problem is that when i use socket_set_nonblock it doesn't connect it dies with "Could not connect.". When i put it after sending a packet, it goes from the start and re does everything.
Here is my connect function:
function connect($ip, $port) {
if($this->soc!=null) socket_close($this->soc);
$this->soc = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
if(!$this->soc) die(socket_strerror(socket_last_error($this->soc)));
if(!socket_connect($this->soc,$ip,$port)) die("Could not connect.");
}
Heres the function when attempting to use socket_set_nonblock
function connect($ip, $port) {
if($this->soc!=null) socket_close($this->soc);
$this->soc = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
socket_set_nonblock($this->soc);
if(!$this->soc) die(socket_strerror(socket_last_error($this->soc)));
if(!socket_connect($this->soc,$ip,$port)) die("Could not connect.");
}
First of all, you need to tell us why you want to put the socket in non-blocking mode. There are two main reasons for that:
To multiplex several file descriptors/sockets (depending on language/platform) on a single thread.
To set a timeout for operations.
Anyway, there are two phases to a non-blocking connect():
Initiate a connection. In php, done with socket_connect(), which will typically fail with SOCKET_EINPROGRESS; in which case you'll need phase two:
Wait for the connection to complete, and check the status. The waiting part is done with socket_select(), where you can multiplex several sockets you are waiting events for. When it returns, you need to iterate over the sockets it returns; when you get to a socket that is waiting for a successful connection, you check the result of the connection with socket_get_option($socket, SOL_SOCKET, SO_ERROR).

Categories