Socket_set_nonblock error - php

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).

Related

How do I force reconnecting to my database in php?

I wanted my web system to automatically reconnect to the database if it reaches to maximum user connection. Or is there anyway i could reload the page automatically till it is connected to the database
$conn = new mysqli(DB_HOST,DB_USER,DB_PSWD,DB_NAME);
if($conn->connect_error)
die("Failed to connect database ".$conn->connect_error );
You can setting the retry variable($retry) as a flag to mark the DB connection status with default value you want. While connect DB , if it's ok then update retry flag = 0($retry=0) , else reduce the retry one unit ($retry--). Also you don't die process when have error exception.
You can enclose the connection in a function and call it many times you want to retry the connection:
function connectDB(DB_HOST,DB_USER,DB_PSWD,DB_NAME)
{
return $conn = new mysqli(DB_HOST,DB_USER,DB_PSWD,DB_NAME);
}
if(connectDB()->connect_error)
{
sleep(1);
if(connectDB()->connect_error)
{
die("Failed to connect database ".$conn->connect_error );
}
}
With sleep(1) you delay the script to retry the connection after 1 second.
Anyway, you should find the cause of the connection error and solve it; this solution may help you in the case the server is sometimes slow to respond.

mysql_connect doesn't work second time

duplicate of unanswered: How to reconnect in php adodb after exceptions: Mysql server gone away or Lost connection to MySQL server during query
mysql_connect works the first time, but never works after that...
$connectDb = mysql_connect(secret, secret, secret);
mysql_select_db("secret", $connectDb);
$sleepPeriod = 1800;
sleep($sleepPeriod);
while (true) {
$result = mysql_query("good query", $connectDb);
if (!$result) {
if (mysql_error()=='MySQL server has gone away') {
echo "MySql connection was disconnected... reconecting...\n";
$connectDb = mysql_connect(secret, secret, secret);
mysql_select_db("secret", $connectDb);
continue;
} else {
die("Invalid Query: ".__FILE__.':'.__LINE__.' '.mysql_error()."\n");
}
}
//DO STUFF
sleep($sleepPeriod);
}
if a timeout or disconnect happens mysql_connect seems to fail and mysql_error continually returns "MySQL server has gone away", which results in an infinite loop that can go for days. is there some other way to clear the error response of mysql_error or to make mysql_connect run a second time without having to restart this program manually or resorting to cron.
I just noticed that mysql_connect has a strange(stupid?) parameter called new_link, however it would be an outrageous design if php's mysql code purposefully disables reconnects on timeout by default... I'll test regardless and get back.
mysql_connect doesn't care if the connection has disconnected or timed-out it will never connect a second time unless you call it with the parameter new_link with the value true.
mysql_connect($server,$username,$password,true);

"Could not connect. Too many connections" Error in MySQLi

I have the following code
function openDBConn($params){
$conn_mode = $params['conn_mode'];
$db_conn = $params['db_conn'];
//create connections
if(empty($db_conn->info)) {
$db_conn = new mysqli("localhost", $user, $password, "database");
$db_conn->set_charset('UTF8');
$mysqli_error = $db_conn->connect_error;
}
if($mysqli_error !== NULL){
die('Could not connect <br/>'. $mysqli_error);
}else{
return $db_conn;
}
}
//close db connection
function closeDBConn( $params ){
$db_conn = $params['db_conn'];
$db_conn->close;
}
//used as below
$db_conn = openDBConn();
save_new_post( $post_txt, $db_conn );
closeDBConn( array('db_conn'=>$db_conn));
From time to time, I get the "Could not connect. Too many connections" error.
This tends to happen when I have Google bot scanning my website.
This problem seems to have started ever since upgrading to MySQLi from MySQL.
Is there any advice on how ensure all connections are closed?
Thanks
You need to increase the number of connections to your MySQL server (the default is only 100 and typically each page load consumes one connection)
Edit /etc/my.cnf
max_connections = 250
Then restart MySQL
service mysqld restart
http://major.io/2007/01/24/increase-mysql-connection-limit/
Some hosters have a hard limit how many open database connections your are allowed to have. Maybe you want to contact your hoster to know how many you are allowed to open. For websites with hight traffic load more connections can be helpful.
Do you have access to the server directly or is it a hosted solution?
If you have direct access you can check the mySQL config files to see how many connections are allowed and increase it.
If you don't you might want to contact your webhost about increasing the limit and see if they will comply.

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

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.

Best approach to see if a MySQL Server is up and running

I have a Master - Slave setup for a web application written in PHP. I have a pool of slaves I use for reading, and a Master that is used for writes (and reads if a write has been sent this request). I would like to incorporate an automated system for removed crashed servers from the read pool. Currently I am using:
foreach($readers as $reader)
{
$fp = #fsockopen($reader['host'],3306,$errno,$errstr,1);
if(!$fp)
{
//Remove from pool
}
unset($fp);
}
My primary question is there a more reliable method. I have had quite a few false positives, and vice versa because it is not actually checking for a MySQL server, but rather just a connection on port 3306. Is there a way to check for a MySQL server without raising an exception, which is the behaviour of the PDO and MySQLi extensions in PHP.
You could just use mysql_connect() and check the result for false, and close the connection right away on success. You can make a dummy account with no privileges for that if you like.
That's really the only reliable way, especially if you want to distinguish a running MySQL server from any other random process listening on port 3306.
You could use mysql_ping() to check if a current DB Connection you have open is still alive
Here is the example posted at http://www.php.net/manual/en/function.mysql-ping.php
<?php
set_time_limit(0);
$conn = mysql_connect('localhost', 'mysqluser', 'mypass');
$db = mysql_select_db('mydb');
/* Assuming this query will take a long time */
$result = mysql_query($sql);
if (!$result) {
echo 'Query #1 failed, exiting.';
exit;
}
/* Make sure the connection is still alive, if not, try to reconnect */
if (!mysql_ping($conn)) {
echo 'Lost connection, exiting after query #1';
exit;
}
mysql_free_result($result);
/* So the connection is still alive, let's run another query */
$result2 = mysql_query($sql2);
?>
The best way to check if any service is alive is to actually use it. So for MySQL try to connect and execute some fast query, for web server try to fetch some file, for PHP try to fetch some simple script...
For MySQL master/slave setup, one of the solutions is to actually check the state of replication. You can check how many transactions is the slave behind master and decide to stop using that slave when/while it has old data. (I don't do the replication myself, but I think you need to compare the variables Read_Master_Log_Pos and Relay_Log_Pos)

Categories