I need to get the atomic time in php.
$fp = #fsockopen( "time-a.nist.gov", 37, $errno, $errstr, 10 );
if ( !$fp )
{
echo $errstr;
}
else
{
fputs($fp, "\n");
$time_info = fread($fp, 49);
fclose($fp);
}
/*** create the timestamp ***/
$atomic_time = (abs(hexdec('7fffffff') - hexdec(bin2hex($time_info)) - hexdec('7fffffff')) - 2208988800);
echo $errstr;`
But I only get connection timeouts with every server I try to connect.
I have tested different server, but all with the same error. Now I am wondering what is wrong with my code.
Is there a better way to ensure atomic time? My boss doesnt want us to use servertime.
Related
I'm trying to use fsockopen to communicate with a game server, which responds with some basic stats. It works perfectly when the server is online, but if the server is ever offline, the following code causes php to stop displaying the page that reads the data.
try {
$socket = fsockopen($host, $port, $errno, $errstr, 10);
if ($socket !== false) {
fwrite($socket, "\xFE");
$data = "";
$data = fread($socket, 1024);
fclose($socket);
if ($data !== false && substr($data, 0, 1) == "\xFF") {
// get into
} else {
// Server did not send back proper data, or reading from socket failed.
print "Server not available.";
}
} else {
// ...
}
} catch(Exception $e){
// ...
}
I've tried the try/catch, I've tried adding a custom handler to the exception. My only idea is to run this outside of the web requests and store the response so that the web request isn't initiating it.
Any thoughts?
First, I'd add a couple of echo commands, either side of the fsockopen call:
echo date("Y-m-d H:i:s")."Before open\n";
$socket = fsockopen($host, $port, $errno, $errstr, 10);
echo date("Y-m-d H:i:s")."After open (socket=".($socket===false?"Bad":"OK")."\n";
This is to confirm the 10 second timeout is working. If you never see the second message then the timeout is not working, and the problem is more obscure.
Anyway, if you are getting a valid $socket, but the lock-up happens later, then try:
if ($socket !== false) {
stream_set_timeout($socket,2); //2 second timeout
stream_set_blocking($socket,false); //no blocking
fwrite($socket, "\xFE");
...
P.S. If adding those two commands solves the problem, then experiment to see if just one of them solves it. That would give a big clue what the real problem is.
It seems that by moving the logic outside the html generation worked. The lookup happens before any html is rendered, so if it fails it doesn't interrupt the html output.
Here is the code that I am using:
if (!($fp = fsockopen('ssl://imap.gmail.com', '993', $errno, $errstr, 15)))
echo "Could not connect to host";
$server_response = fread($fp, 256);
echo $server_response;
fwrite($fp, "C01 CAPABILITY"."\r\n");
while (!feof($fp)) {
echo fgets($fp, 256);
}
I get the first response:
OK Gimap ready for requests from xx.xx.xx.xx v3if9968808ibd.15
but then the page times out. I have searched through stream_set_blocking, stream_set_timeout, stream_select, fread, etc. but could not get it to work. I need to read all the data that the server sends and then proceed with other commands (I would be retrieving emails using imap).
Thanks
Your script is hanging in the while loop at the end. This is because you have used !feof() as the condition for the loop, and the server is not closing the connection. This means the feof() will always return false and the loop will continue forever.
This will not be problem when your write a full implementation, as you will be looking for response codes and can break out of the loop accordingly, for example:
<?php
// Open a socket
if (!($fp = fsockopen('ssl://imap.gmail.com', 993, $errno, $errstr, 15))) {
die("Could not connect to host");
}
// Set timout to 1 second
if (!stream_set_timeout($fp, 1)) die("Could not set timeout");
// Fetch first line of response and echo it
echo fgets($fp);
// Send data to server
echo "Writing data...";
fwrite($fp, "C01 CAPABILITY\r\n");
echo " Done\r\n";
// Keep fetching lines until response code is correct
while ($line = fgets($fp)) {
echo $line;
$line = preg_split('/\s+/', $line, 0, PREG_SPLIT_NO_EMPTY);
$code = $line[0];
if (strtoupper($code) == 'C01') {
break;
}
}
echo "I've finished!";
Your script should be working. In fact, it is working.
See the results below on my pc when I ran your code:
* OK Gimap ready for requests from xx.xx.xx.xx l5if4585958ebb.20
* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XOAUTH
C01 OK Thats all she wrote! l5if4585958ebb.20
Since gmail doesn't disconnect you. No end of file occurs. And the page loading simply times out.
In other words: Your script will just keep waiting and waiting until gmail does disconnect, which unfortunately happens after your page load has already timed out.
Im using VCL to broadcast to my localhost, 127.0.0.1 with UDP (legacy) method. To catch the traffic, I use this code:
$address = '127.0.0.1';
$port = 1234;
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_bind($sock, $address, $port) or die('Could not bind to address');
$f = fopen ('output', 'w');
fclose ($f);
$sock = stream_socket_server('udp://127.0.0.1:1234', $errno, $errstr, STREAM_SERVER_BIND);
while(1)
{
$a = stream_socket_recvfrom($sock, 65536);
$f = fopen('output', 'a');
fwrite ($f, $a);
fclose ($f);
#ob_flush();
}
this logs the packets and saves, I rename it to .MP4 and open - well, the result is a little messy. I can recognize the output, the top screen is visible, the lower part is not good. I tried to capture it with another VCL player, and there were no problem.
Here is your code with a lot of useless stuff removed and a few efficiency improvements. Try it out and see what happens. It may or may not fix the problem, but report back with what happens and we'll take it from there.
// Settings
$address = '127.0.0.1';
$port = 1234;
$outfile = "output.mp4";
// Open pointers
if (!$ofp = fopen($outfile, 'w'))
exit("Could not open output file for writing");
if (!$ifp = stream_socket_server("udp://$address:$port", $errno, $errstr, STREAM_SERVER_BIND))
exit("Could not create listen socket ($errno: $errstr)");
// Loop and fetch data
// This method of looping is flawed and will cause problems because you are using
// UDP. The socket will never be "closed", so the loop will never exit. But you
// were looping infinitely before, so this is no different - we can address this
// later
while (!feof($ifp)) {
if (!strlen($chunk = fread($ifp, 8192))) continue;
fwrite($ofp, $chunk);
}
// Close file pointers
fclose($ofp);
#fclose($ifp);
I'm fetching data from a socket that pumps data at unknown intervals. There could be nothing for minutes (or even hours) and then tens of thousands of rows can be queued ready for reading.
Because I don't know what to expect, I was hoping to build something that connects for 2-5 seconds slurping in however much it can, irrespective of how much is queued up at the server end.
This is what I have at the moment.
<?php
set_time_limit(2);
ini_set('max_input_time', 2);
$timeout = 3;
$host = 'data.host.com';
$port = 6543;
$fp = fsockopen($host, $port, $errno, $errstr, $timeout);
stream_set_timeout($fp, 2);
if( !$fp ){
echo "Connection to '$host' failed.\n$errstr ($errno)\n";
exit;
}
while( !feof($fp) ){
$xml = trim(fgets($fp));
if(empty($xml)) continue;
echo "XML=$xml\n";
}
echo "DONE\n";
function shutdown(){
echo "SHUTDOWN!\n";
}
register_shutdown_function('shutdown');
However this never finishes at all. The while loop appears to be as infinite as one might expect (out of context). How do I put in and capture some exit/break/kill?
This may not be the best/correct way to do it, but it should work (untested)
$startTime = time();
$executionTime = 180; //180 Seconds - 2 Minutes
while( !feof($fp) ){
if ((time() - $startTime) > $executionTime) {
//If time has been longer than the execution time, break
//out of loop
break;
}
$xml = trim(fgets($fp));
if(empty($xml)) continue;
echo "XML=$xml\n";
}
I believe this is a mysql connection, if so use the default port. Restricting the socket connection is not advisable unless you can store all transaction in a temp db and push else where at the time alloted.
$start_time = time();
while( !feof($fp) ){
$xml = trim(fgets($fp));
if(empty($xml)) continue;
echo "XML=$xml\n";
if ( time() - $star_time > 320 ) break;
}
I am using streaming sockets in PHP to read from a remote server. When the remote server goes away after connection, stream_select continues to show a changed stream on the read portion of the stream, but the data being read in is a blank string.
Here is a small case that reproduces the bug. It is two components, a server and client component.
In order to replicate the bug you will need to do the following using php from the command line:
1. Start up server.php
2. Start up client.php
At this point the server should show 'Press return to continue.... or CTRL-C' and the client should show 'Kill your server. Press return to continue....'
Ctrl-c server.php
Press enter on client.php
At this point you should see debugging output from client.php showing the issue (you will want to ctrl-c pretty quickly, it prints a lot of repeating information very quickly)
I am unsure why the stream_select continues to show the read stream as having changes after the server component is no longer running.
server.php
<?php
$socket = stream_socket_server("tcp://0.0.0.0:51111", $errno, $errstr);
$s = stream_socket_accept($socket);
print("Press return to continue.... or CTRL-C me");
fread(STDIN,1); // Wait for one character to be pressed.
fwrite($s, "Yep here's some stuff for you\0");
?>
client.php
<?php
$url = "localhost";
$port = 51111;
$errno = 0;
$errstr = "";
$fp = #stream_socket_client("tcp://".$url.":".$port, $errno, $errstr, 5);
if (!$fp)
{
print( "Unable to open socket: $errstr ($errno)\n" );
throw new Exception( "Unable to open socket : $errstr ($errno)" );
}
//WAIT HERE.
print("Kill your server. ");
print("Press return to continue....\n\n");
fread(STDIN,1); // Wait for one character to be pressed.
stream_set_blocking($fp,0);
$buffer = "";
while ( true )
{
$read = array($fp);
$write = NULL;
$except = array($fp);
//Wait for up to 5 second to get something from the server
if (false === ($num_changed_streams = stream_select($read, $write, $except, 5)))
{
// It timed out!
fclose($fp);
print( "Socket internal error\n" );
throw new Exception( "Socket internal error" );
}
if( empty($read) ) //It must be an excecption instead...
{
// We got a socket error
fclose($fp);
print("Socket error\n");
throw new Exception( "Socket Error" );
}
print( var_export( array( $read, $write, $except), true )."\n" );
print( "Num changed streams: $num_changed_streams\n" );
if ( $num_changed_streams == 0 )
{
// nothing changed int he stream, we hit a timeout!
fclose( $fp );
print( "Socket timeout\n" );
throw new Exception( "Socket timeout" );
}
//We're ready to read.
$chunk = fread($fp, 1024);
if( $chunk === FALSE )
{
print("fread failed\n");
throw new Exception("fread failed");
}
print( "Chnk: ".var_export( $chunk, true )."\n" );
$buffer.= $chunk;
if ( (strlen($chunk)>0) && (ord($chunk[strlen($chunk)-1])==0) ) break;
}
fclose($fp);
Worked this one out. As per the php documentation at http://au.php.net/manual/en/function.stream-select.php
The streams listed in the read array
will be watched to see if characters
become available for reading (more
precisely, to see if a read will not
block - in particular, a stream
resource is also ready on end-of-file,
in which case an fread() will return a
zero length string).
This 0 length string return case was being triggered when the remote end went away, but was not being caught in the break check.
Fix is to test the length of the return from fread, and if it is 0 then break out of the loop.