How to read php socket connection response? - php

Following is my socket connection request and response order.
$socket = socket_create(AF_INET, SOCK_STREAM, 0);
$connection = socket_connect($socket, $Host, $Port);
$Md5CheckSum = md5($msg);
$WillWait = 'SOAP '. $Md5CheckSum. ' WILL_WAIT'."\n";
socket_write($socket,$WillWait);
socket_write($socket,$msg);
socket_write($socket, SoapSender::$TERM_CHAR);
sleep(1);
$buf = socket_read($socket, 2048);
//socket_write($socket,"&\r\n");
echo "$buf\n";
Please could somebody tell me how to read response that I receive after last socket_write request. I have been searching for this answer all day but have not been able to find any help through Google.
Thanks a lot for your time.

Two functions should be used:
stream_set_blocking($socket, true);
And
stream_get_contents($socket);
Setting a block on your stream requires the return of data before your application will continue execution of the script.
If you do not set a stream block, sometimes latency will cause your PHP script to think there was no response, causing you to not receive data.
Also, use stream_get_contents to pull from the socket. This will grab by default the full buffer.

The correct way is to use socket_read, not stream_get_contests as someone else suggested.
Here is an example:
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$result = socket_connect($sock, "10.197.24.40", "5000");
$request = '{ "request" : { "id" : "some_function_id", "data": "55555555-5"} }';
// We send the request
socket_write($sock,$request);
socket_read($sock,1000000);
socket_close($sock);
I have tested this code in a live environment and it works correctly.

Related

PHP/UDP: Can write via UDP, but recieving data seams not possible

I have this code which is running on php on my local mac:
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
$result = socket_connect($socket, $address, $port);
$msg = "i";
$len = strlen($msg);
socket_send($socket, $msg, $len, 0);
socket_recv($socket, $buf, 512, 0);
echo $buf;
socket_close($socket);
The code works up to "socket_recv". Actually, when running a udp test app on the computer, I can see the answer from the udp server on the terminal screen of the app. However, the script itself is running for ever (I assume that it is waiting for input which never comes through the socket for some reason).
I also tried to run the script on a local Webserver on a synology NAS. Same result.
(Same result with the UDP App obviously closed)
Problem solved by using this code. Apparently one has to close the socket after sending and open a new one for receiving. It seams to be a unique behaviour of this device (server):
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
$bytes = socket_sendto($socket, $message, strlen($message), 0, "192.168.0.37", 7090);
socket_close($socket);
$message="curr 7700";
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_bind($socket, '0.0.0.0', 7090);
$from = '';
$port = 0;
socket_recvfrom($socket, $buf, 512, 0, $from, $port);
echo $buf . PHP_EOL;

How i know a IP is connected/normal or disconnected from LAN in PHP?

I have a database where i have stored all IP address. Now i want to know these IP address is connected/normal or disconnected. I have tried:
$add = "example.com";
$result = checkdnsrr($add, "MX");
var_dump($result);
Its return boolean true or false. But i have IP address which is not connected dns. But how can i know the IP is active/normal/connected or disconnected?
LONG POLLING is BAD
As far as I have understood your question, you just want to check if the particular client is connected or not.
You will have to setup a cron job in PHP with a continuous loop which will be long polled by XHR (AJAX with Jquery etc) setting a status = true. So, when a user disconnects, the XHR will be broken and a status will be set = false. Thus you can check if a user is connected or not. However, please note that Long Polling is really resource intensive and is not appreciated.
I would highly suggest you to use go with Node and Websockets etc.
I could write a code for PHP Cron job and settle your problem but I don't appreciate Long Polling + Cron Job for it.
if you want to check if the website is alive then you can do it like this:
$add = "example.com";
$result = false;
if($fp = fsockopen($add, 80, $errno, $errstr, 10)){
fclose($fp);
$result = true;
}
var_dump($result);
// edit: so you want to know if the IP is present in your local network ? if so you can use ping like:
function ping($host, $timeout = 1) {
/* ICMP ping packet with a pre-calculated checksum */
$package = "\x08\x00\x7d\x4b\x00\x00\x00\x00PingHost";
$socket = socket_create(AF_INET, SOCK_RAW, 1);
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec' => $timeout, 'usec' => 0));
socket_connect($socket, $host, null);
$ts = microtime(true);
socket_send($socket, $package, strLen($package), 0);
if (socket_read($socket, 255))
$result = microtime(true) - $ts;
else $result = false;
socket_close($socket);
return $result;
}
$present = ping('192.168.0.100');

How to send data to a specific socket

I am newbie in using PHP Websocket.
Here is my problem:
I have already successful running PHP websocket and creating a simple chat application(web application of course). In receiving client data. All of the clients will receive the data. How could I send data to a specified client or maybe to a several clients(not all clients).
I learn it at here
<?php
// Create a new socket
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
// An example list of IP addresses owned by the computer
$sourceips['kevin'] = '127.0.0.1';
$sourceips['madcoder'] = '127.0.0.2';
// Bind the source address
socket_bind($sock, $sourceips['madcoder']);
// Connect to destination address
socket_connect($sock, '127.0.0.1', 80);
// Write
$request = 'GET / HTTP/1.1' . "\r\n" .
'Host: example.com' . "\r\n\r\n";
socket_write($sock, $request);
// Close
socket_close($sock);
?>
SOURCE: http://php.net/manual/en/function.socket-bind.php

socket_connect does not timeout

I am using sockets to send data to a server that may not be responding. So I am trying to define a timeout by using this solution in SO.
Make PHP socket_connect timeout
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec' => 1, 'usec' => 0));
socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array('sec' => 1, 'usec' => 0));
This works when the connection is made and the server takes too long to respond.
But when it can't create a connection socket_connect($socket, $addr, $port); the timeout is about 20 seconds.
Why is this 20 second timeout happening and how can I force the connection creation to timeout after 1 second too?
You can do this by switching to a non-blocking socket, looping until either a connection is gained or a timeout was reached, then back to blocking again.
// an unreachable address
$host = '10.0.0.1';
$port = 50000;
$timeout = 2;
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
// switch to non-blocking
socket_set_nonblock($sock);
// store the current time
$time = time();
// loop until a connection is gained or timeout reached
while (!#socket_connect($sock, $host, $port)) {
$err = socket_last_error($sock);
// success!
if($err === 56) {
print('connected ok');
break;
}
// if timeout reaches then call exit();
if ((time() - $time) >= $timeout) {
socket_close($sock);
print('timeout reached!');
exit();
}
// sleep for a bit
usleep(250000);
}
// re-block the socket if needed
socket_set_block($sock);
edit: see #letiagoalves answer for an neater solution if you are using sockets created with fsockopen() or stream_socket_client()
I changed my socket communication mechanism to use stream_socket_client ($remote_socket, &$errno, &$errstr, $timeout) function instead. This function allows to define the connect timeout unlike socket_connect ($socket, $address, $port) which doesn't.
To force a timeout using socket_connect see #bigtallbill answer.
I tried a lot of variants with sockets..
fsockopen the best for simple operations, ex. testing connections
The SO_RCVTIMEO/SO_SNDTIMEO options don't work for socket_connect on some platforms, but only for socket_recv/socket_send. I can see it works on Ubuntu, but not Mac OSX.

How do you get the HTTP status code for a remote domain in php?

I would like to create a batch script, to go through 20,000 links in a DB, and weed out all the 404s and such. How would I get the HTTP status code for a remote url?
Preferably not using curl, since I dont have it installed.
CURL would be perfect but since you don't have it, you'll have to get down and dirty with sockets. The technique is:
Open a socket to the server.
Send an HTTP HEAD request.
Parse the response.
Here is a quick example:
<?php
$url = parse_url('http://www.example.com/index.html');
$host = $url['host'];
$port = $url['port'];
$path = $url['path'];
$query = $url['query'];
if(!$port)
$port = 80;
$request = "HEAD $path?$query HTTP/1.1\r\n"
."Host: $host\r\n"
."Connection: close\r\n"
."\r\n";
$address = gethostbyname($host);
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($socket, $address, $port);
socket_write($socket, $request, strlen($request));
$response = split(' ', socket_read($socket, 1024));
print "<p>Response: ". $response[1] ."</p>\r\n";
socket_close($socket);
?>
UPDATE: I've added a few lines to parse the URL
If im not mistaken none of the php built-in functions return the http status of a remote url, so the best option would be to use sockets to open a connection to the server, send a request and parse the response status:
pseudo code:
parse url => $host, $port, $path
$http_request = "GET $path HTTP/1.0\nHhost: $host\n\n";
$fp = fsockopen($host, $port, $errno, $errstr, $timeout), check for any errors
fwrite($fp, $request)
while (!feof($fp)) {
$headers .= fgets($fp, 4096);
$status = <parse $headers >
if (<status read>)
break;
}
fclose($fp)
Another option is to use an already build http client class in php that can return the headers without fetching the full page content, there should be a few open source classes available on the net...
This page looks like it has a pretty good setup to download a page using either curl or fsockopen, and can get the HTTP headers using either method (which is what you want, really).
After using that method, you'd want to check $output['info']['http_code'] to get the data you want.
Hope that helps.
You can use PEAR's HTTP::head function.
http://pear.php.net/manual/en/package.http.http.head.php

Categories