I've been having some issues with my Internet connection and I was wondering what is the fastest, error-less and most reliable way to check if the host computer is connected to the Internet.
I'm looking for something like is_online() that returns true when online and false when not.
I've benchmarked some solutions: file_get_contents with HEAD request, gethostbynamel, checkdnsrr and the following solution seems to be more than 100 faster than all the others:
function is_online()
{
return (checkdnsrr('google.com', 'ANY') && checkdnsrr('yahoo.com', 'ANY') && checkdnsrr('microsoft.com', 'ANY'));
}
Takes about one microsecond per each host, while file_get_contents for instance takes more than one second per each host (when offline).
You could send a ping to a host that is probably up (e.g. Google).
There seems to be no PHP built-in for this, so you'd have to resort to shell commands. The return value of ping on *nix can tell you whether a reply was received.
Update: ping -c1 -q -w1 should be the right command on Linux. This will give you exit code 0 if a reply was received, something else otherwise, and it times out after one second.
Hence, something like this (warning, my PHP is rusty) should do the trick:
function is_online() {
$retval = 0;
system("ping -c1 -q -w1", $retval);
return $retval == 0;
}
Why don't you do a number of HTTP GET (or better still HTTP HEAD for speed) requests on popular web sites? Use majority voting to decide on the answer.
You can sometimes rely on ping too (through a system call in PHP) but note that not all web sites respond to ICMP (ping) requests.
Note that by increasing the number of ping/http requests you make before drawing a conclusion helps with the confidence level of the answer but can't be error free in the worst of cases.
Don't forget this assumes that your server will respond to ICMP requests. If that's the case then I agree, Net_Ping is probably the way to go. Failing that you could use the Net_Socket package, also on PEAR, to attempt a connection to some port that you know will get a response from - perhaps port 7 or port 80 depending on what services you have running.
Related
I have to connect to a FTPES server to retrieve data. Connecting and logging in works just fine, but my call with ftp_rawlist always fails and returns "false".
I am using this code for debugging purposes:
$ftp = ftp_ssl_connect($ftp_host);
if (ftp_login($ftp, $ftp_user, $ftp_pass)) {
$p = ftp_pasv($ftp, true);
var_dump($p);
$r = ftp_rawlist($ftp, '/', true);
var_dump($r);
} else {
echo 'Could not login';
}
$p is always true, $r always false.
When I connect to the server through Filezilla everything works fine and I can list directory content and more.
Update #1: Tried to not only list '/' but various subfolders on the server, they all fail through the script.
Update #2: Also tried to use ftp_raw with the commands to get a list, but the LIST command runs for some time and then does not return any result at all. But HELP lists LIST as a valid command for the server... Strange...
Update #3: I tried phpseclib now, but while I can connect, I can't login with the user/password combination. Support from the maintainer of the FTPES server is not happening ("works fine for $somebody else..."), so I need to figure this out another way... :-)
To come to an end with this: As the deadline for this project came closer a solution had to be found. And although this is no real answer in the sense of a question, I'd like to show what I have done to have this fixed. Maybe someone stumbles upon this through googling.
Next to the things mentioned in the OP, I also tried connecting to FTPS using PHP and certificate as auth which didn't work either. As nothing works as it is supposed to, I wonder if the FTPS server is really configured correctly after all.
The people who run the server told me that everything is fine and their CLI CURL-call works fine for them, so they have no need to further investigate issues.
As a result of this I set up a sandbox account on a server which has shell_exec() enabled. There is now a script running which gets a file listing via CURL and then downloads the files via CURL with the commands provided by the server provider. That server can be accessed through normal SFTP and therefore acts as a "Proxy FTP" which regularly mirrors the remote FTPS server file structure.
Although I find this "solution" quite "hacky" it seems to run robust, stable and fast for the moment. We will therefore be able to have the operation running this way in this year (it only runs around three months before christmas) and will have a look into it in the new year and develop a more stable solution.
Maybe the server guys are also less stressed then and willing to help... ;-)
Add the following call to ftp_set_option() in a line before the call to ftp_pasv
ftp_set_option($ftp, FTP_USEPASVADDRESS, false);
ftp_pasv($ftp, true);
I am trying to implement the following chat-html5 from git hub:
https://github.com/ivanph/Chat-HTML5
I have uploaded everything to my ISP but I have found that the ISP blocks exec for security reasons.
The file I am calling is :
<?php
/**
* Main Script of phpWebSockets
*
* Run this file in a shell or windows cmd to start the socket server.
* Sorry for calling this daemon but the goal is that this server run
* as daemon in near future.
*
* #author Moritz Wutz <moritzwutz#gmail.com>
* #version 0.1
* #package phpWebSockets
*/
ob_implicit_flush(true);
require 'socket.class.php';
require 'socketWebSocket.class.php';
require 'socketWebSocketTrigger.class.php';
$ip = exec ("ifconfig|grep 'inet:'|grep -v '127.0.0.1' |cut -d: -f2 |awk '{ print $1}'");
$WebSocket = new socketWebSocket($ip,8000);
?>
Is there an alternative way to do this ? Do all Isp's block this ?
What can I do?
Hi Guys
thanks for the responses.
I got a response from the script developer.
I have changed the $ip to the ip address of our web site. I now get the following error:
--2013-08-13 12:07:01-- http://www.wilsea.com/websockets2/startDaemon.php
Resolving www.wilsea.com... 188.64.188.21
Connecting to www.wilsea.com|188.64.188.21|:80... connected.
HTTP request sent, awaiting response... 500 Internal Server Error
2013-08-13 12:07:12 ERROR 500: Internal Server Error.
The developer says this means that the port (8000) is in use so I tried 80 - 443 - 8080 but got the same error.
I have emailed the ISP and asked if websockets are blocked or if I need a port opening.
Anyone else had this issue or any insights into this problem?
Is there an alternative way to do this ?
There also are system and shell_exec, but I'd assume this to be disabled for the same reasons.
Like pointed out in the comments, you could also just provide your server's static IP instead of having the script determine it. However, chances are sockets are disabled as well, so don't put your hopes too high.
Do all Isp's block this ?
Most Hosting Providers do. Obviously a hosting service doesn't want you to run arbitrary commands on the shell that could potentially reconfigure the machine.
What can I do?
Get paid hosting that allows you to exec. A VPS or a dedicated server comes to mind.
I could try to find a way to detect a good listening address in PHP to avoid this monstrosity. (The workaround would probably be $ip = '0';) Your next question would be: Fatal error: Call to undefined function socket_create() why is my ISP so mean?. exec() is blocked for good reasons on a shared hosting and you won't be allowed to create a socket with create_socket().
No hoster will want something like this on their shared server. You'll have to get your own system but then you wouldn't want this code to run on it. This is because you don't want to run this code anywhere unless you were trying to improve on it. But then you'd be improving on a solution which builds on the sand that is PHP. And that would be sad.
Get a cheap virtual server if you really want to use this. I don't recommend it. Looks like somebody is trying to use PHP for a task it's not designed to do. If you've gotten this far without understanding the issues involved I recommend you to stay far away from it. Try it on localhost if you must, so you're not harming other people.
The issue was the ISP blocks all port. They have now opened the port for me.
Cheers
SteveW
I want to check if another machine is generally responding with PHP.
Most approaches are to ping some service running on the target machine, but I want to check if the machine is online generally.
I've found http://birk-jensen.dk/2010/09/php-ping/ which supposedly sends an ICMP Ping package. The problem is, somehow one is required to be root to perform a socket_create(AF_INET, SOCK_RAW, 1). The workaround via posix_seteuid(0) doesn't work either, since elevated permissions are required for that too.
Any functions that would let me run the ping program are not available in my scenario either.
So how do I check if a server is online using php?
You can always use Net_Ping to ping from php
http://pear.php.net/package/Net_Ping/redirected
for this you might want to try, this is highly unlikely to give meaningful data, but is something to grok over.
if you open a tcp socket to a random port and instead of timing out it closes immediately. then the machine is "up", however this does not mean much more then that. it could be in a kernel panic.
and a timeout does not mean that the machine is down. just that instead of rejecting the tcp handshake it dropped it.
you wont be able to get any kind of meaningful timing data with this, but will give more of an educated guess if the machine in question is on or off.
<?php
$sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
socket_connect ( $sock , string $address,22 ) === true) {
switch(socket_last_error($sock)) {
case 110:
case 112:
case 113:
echo 'Machine may be down';
break;
case 111:
echo 'Machine may be up';
break;
case 115:
echo 'Machine is up';
break;
default:
echo 'Machine in unknown state.';
break;
}
you already stated that you can't use the ping command so Net_Ping will not work as it is just a fancy interface to the ping command in the operating system
Well. I read some topics in SO but I not found a very specific answer.
I need to check with PHP if a PHP code is running in local or remote host. Currently I check with $_SERVER['SERVER_NAME'] but it is inconsistent. In this case, if I run PHP with listed IPs like 127.0.0.1 or localhost it'll consider local, otherwise remote. If I share my IP with a friend, my code still local, but it consider remote because the shared IP isn't listed.
Well, I think that check IP for localhost is not a good idea (except if you know a good method). I tried methods like gethostbyaddr() and gethostbyname() but don't work correctly too.
I don't have a PHP code to show, but my code is basically that:
// true = localhost
return $_SERVER['SERVER_NAME'] === '127.0.0.1';
The fundamental question is: what can determine that PHP is running local? What is "local" for PHP? I think that it can solve the problem.
Obs.: I don't have access to CMD/Shell with PHP.
You could do what most PHP frameworks do and set a flag during your app's bootstrap phase that defines which environment the code is running in. In it's simplest form:
// the setting when run on a dev machine
define('ENV', 'local');
Then it's a simple case of:
if ( ENV == 'local' )
{
// do stuff
}
This is how I do it, which I find more reliable than trying to detect for 127.0.0.1:
if( strpos(gethostname(), '.local') !== false ) { }
Basically, the hostname's on my workstations all have .local appended to it. You can change this to match your workstation's hostname entirely.
Check $_SERVER['REMOTE_ADDR']=='127.0.0.1'. This will only be true if running locally. Be aware that this means local to the server as well. So if you have any scripts running on the server which make requests to your PHP pages, they will satisfy this condition too.
If someone is visiting your site via the web, the IP address you see will never be 127.0.0.1 (or ::1 for IPV6), regardless of the usage of a proxy. (Unless of course you're running the proxy yourself on the same server ;)
As far as I know, only you will be able to know what addresses are local or not. Your network could be set up with IP addresses that don't look local at all. PHP cannot as far as I know determine this by itself.
I'm on a Linux system where I am not allowed to use the 'ping' application (ping: icmp open socket: Operation not permitted). However, the script that I am writing (PHP, but I can use an exec() call to any script/program if needed) needs to determine if a host is 'alive'. How can I go about this without using 'ping'?
If ping can't do it, you can't do it in a different language. Here is an analogy that may help you understand why. Let's say there is a file on the file system and you want to its contents. You run cat filename and it says cat: filename: Permission denied. Do you think Perl (or any other language) will fair better than C did here? Let's try:
#!/usr/bin/perl
use strict;
use warnings;
die "usage: $0 filename" unless #ARGV == 1;
my $filename = shift;
open my $fh, "<", $filename
or die "could not open $filename: $!\n";
print while <$fh>;
When run against the file it says could not open filename: Permission denied. No matter what language you try to use, you are going to get Operation not permitted.
That said, there are other methods of determining if a machine is alive. If there is a server that is known to always be running on the machine, you could try to connect to it. Note that you don't need to finish the connection (e.g. log in), just the fact that you can successfully initiate the connection is enough to know that box is up.
To do a ping (ICMP) you need root access.
The only way you have is to do a TCP or UDP ping.
If you want an example check the code of Cacti or you can use hping to do it for you
Or you can set SUID bit on "ping" program on unix ;)
http://us2.php.net/manual-lookup.php?pattern=socket
But if you can't open a socket with ping, it's unlikely that you can use any of these. Talk to your hosting provider.
The PHP Manual gives user supplied code for an implementation of a ping in PHP. Unfortunately, it requires root access so it's not likely you'll be able to use that either. One alternative is to use curl and look at the values returned by curl_getinfo():
c = curl_init('http://www.site.com/');
curl_exec($c);
$info = curl_getinfo($ch);
It is nowhere near being equivalent to ping, but still maybe suitable for your needs.