Board index   FAQ   Search  
Register  Login
Board index php forum :: php coding PHP coding => General

stream_set_blocking fgets doesn't wait for data

Ask about general coding issues or problems here.

Moderators: macek, egami, gesf

stream_set_blocking fgets doesn't wait for data

Postby DaveKimble » Sat Jun 15, 2013 8:15 pm

I am writing 2 PHP scripts to run from the command line on Win7, a server and a client.

The server calls stream_socket_server() to create the socket, bind and listen.
A timer event invokes my monitorsocket() every second, which calls stream_socket_accept().
If successful, it then calls stream_set_blocking($client, 1) , reads the client's greeting using fgets() and writes the server's greeting using fwrite() - so far it works OK.

It then calls fgets() to get the client's first message and should wait for a response, but it doesn't - straight away it says it didn't get a response and goes into its fail routine. It clearly says in http://php.net/manual/en/function.strea ... ocking.php
In non-blocking mode an fgets() call will always return right away while in blocking mode it will wait for data to become available on the stream.

http://www.davekimble.org.au/monitorsocket.txt
http://www.davekimble.org.au/server.txt
DaveKimble
New php-forum User
New php-forum User
 
Posts: 11
Joined: Fri Jan 28, 2011 7:21 pm

Re: stream_set_blocking fgets doesn't wait for data

Postby johnj » Tue Jun 18, 2013 5:27 am

1). Are you sure that when you set stream_set_blocking , you are indeed using the blocking mode?
2). Did you check the return value fir stream_set_blocking()?
johnj
php-forum Super User
php-forum Super User
 
Posts: 1805
Joined: Thu Mar 10, 2011 5:07 pm

Re: stream_set_blocking fgets doesn't wait for data

Postby DaveKimble » Tue Jun 18, 2013 6:02 am

I wasn't testing stream_set_blocking(), but I've just added that now and it returns TRUE, and still fails on the fgets() .
I had wondered whether the resource parameter should be the value returned from stream_socket_accept() or from stream_socket_server(), so I tried both, and it didn't make any difference.
DaveKimble
New php-forum User
New php-forum User
 
Posts: 11
Joined: Fri Jan 28, 2011 7:21 pm

Re: stream_set_blocking fgets doesn't wait for data

Postby DaveKimble » Tue Jun 18, 2013 2:22 pm

The scripts use the wxPHP library, which has wrappers for wxWidgets, to create a GUI.
This imposes an object-oriented structure on the scripts.

In an attempt to focus on the stream_ functions, I extracted just the lines for the connection, dropping the GUI and structure, and that works!

So the GUI structure is having some kind of effect, although everything discussed here has been going on in the one function, monitorsocket() . If there was some problem during the fgets() wait for data, I could go looking for it, but fgets() doesn't wait - see the timestamps
Code: Select all
14-07-05   Listening on port 4000
14-07-11   Connection accepted from 192.168.0.4:61229
14-07-11   Dave: Calling
14-07-11   Server: Hello Dave, go ahead
14-07-11   Reading first message failed
14-07-11   Connection closed

There must be something wrong with that logic, but I can't imagine what.
DaveKimble
New php-forum User
New php-forum User
 
Posts: 11
Joined: Fri Jan 28, 2011 7:21 pm

Re: stream_set_blocking fgets doesn't wait for data

Postby DaveKimble » Tue Jun 18, 2013 8:46 pm

http://au1.php.net/manual/en/function.s ... t-line.php
This function is nearly identical to fgets() except in that it allows end of line delimiters other than the standard \n, \r, and \r\n, and does not return the delimiter itself.

Since this is actually a bit more convenient for me, I replaced all the fgets() with stream_get_line($client, 8192, "|"), and it still fails the same way.

Then I wondered if having the 2 scripts on the same machine was somehow to blame, so I moved the client to another machine on the LAN, and it didn't make any difference.

Updated version:
Code: Select all
function monitorsocket()
{   global $accepted, $caller, $client, $socket, $timer ;
   if ($accepted) { return 1 ; }    // already got a client
   $client = stream_socket_accept($socket, 1, $remote);
   if (!$client) { return 1 ; }   // 1 means keep timer loop going
   $accepted = true ;
   wlog("Connection accepted from $remote");
   $result = stream_set_blocking($client, 1);
   if (!$result) { wlog("Stream blocking failed"); }
   // get client's greeting
   $caller = stream_get_line($client, 8192, "|");
   if (!$caller)
   {   wlog("Reading greeting failed");
      fclose($client);
      wlog("Connection closed");
      $accepted = false ;
      return 1 ;
   }
   wlog("$caller: Calling");
   // send server's greeting
   $greeting = "Hello $caller, go ahead";
   wlog("DK: $greeting");
   $result = fwrite($client, $greeting."|" );
   if (!$result)
   {   wlog("Sending greeting failed");
      fclose ($client);
      wlog("Connection closed");
      $accepted = false ;
      return 1 ;
   }
   // get client's first message
   $message = stream_get_line($client, 8192, "|");
   if (!$message)
   {   wlog("Reading first message failed");
      fclose($client);
      wlog("Connection closed");
      $accepted = false ;
      return 1 ;
   }
   wlog("$caller: $message");
   //
   return 1 ;
}
DaveKimble
New php-forum User
New php-forum User
 
Posts: 11
Joined: Fri Jan 28, 2011 7:21 pm

Re: stream_set_blocking fgets doesn't wait for data

Postby johnj » Thu Jun 20, 2013 9:25 pm

use of global is not a good way to pass data, especially when you have a function and can pass these as parameters of the function.
johnj
php-forum Super User
php-forum Super User
 
Posts: 1805
Joined: Thu Mar 10, 2011 5:07 pm

Re: stream_set_blocking fgets doesn't wait for data

Postby johnj » Thu Jun 20, 2013 9:29 pm

What is $socket and $remote?. Please post the code for these two.
johnj
php-forum Super User
php-forum Super User
 
Posts: 1805
Joined: Thu Mar 10, 2011 5:07 pm

Re: stream_set_blocking fgets doesn't wait for data

Postby DaveKimble » Fri Jun 21, 2013 12:22 am

The functions are called as event handlers by the wxPHP "engine", so I don't have the ability to provide the parameters.

Why is global not a good way to do it, error-prone perhaps, but so is lining up parameter lists ?

$socket is the listening socket's resource handle.
$remote is the client's IP:port
DaveKimble
New php-forum User
New php-forum User
 
Posts: 11
Joined: Fri Jan 28, 2011 7:21 pm

Re: stream_set_blocking fgets doesn't wait for data

Postby johnj » Fri Jun 21, 2013 10:19 pm

In your code,
Code: Select all
....
$client = stream_socket_accept($socket, 1, $remote);


if you look into the documentation for stream_socket_accept, the second parameter for this function is timeout which is in seconds. Here you have given this as '1' second. Looks like this is getting timed out even before you receive any data.

What stream_socket_accept returns is a connection to the stream and not a client. So, it is better to change this return value from $client to $connection. And, the next line is just a "if"?. I think it should be "keep looping as long as there is a stream connection". So, i think this should be
Code: Select all
while ($connection = stream_socket_accept($socket, 5, $remote))
{
// try fread first and the try stream_get_line
$message = fread($connection, 1024);
echo "Message is: ".$message;
// do some thing
}
johnj
php-forum Super User
php-forum Super User
 
Posts: 1805
Joined: Thu Mar 10, 2011 5:07 pm

Re: stream_set_blocking fgets doesn't wait for data

Postby DaveKimble » Fri Jun 21, 2013 11:46 pm

Thanks for your perseverence.
The 1 second is the time the accept function will wait for a connection attempt.
When there isn't a connection attempt in that second, monitorsocket() returns 1 to the wxPHP timer that invoked it, and the timer provides the looping effect - 1 implies keep looping.

When there is a connection, the greetings are exchanged OK, (showing the connection hasn't timed out).
It is the "next message" that doesn't get through.

Update
I wonder if the error might be in the client script. Despite the text of the server's greeting getting through, perhaps the server's ownership of writing rights hasn't been released, so the client's attempt to write appears to go OK (isn't rejected straight away anyway) but the server isn't ready for it, so it fails in the server script.

Do you know how these stream functions operate under the skin? How does one get inside them and see what they're doing?
DaveKimble
New php-forum User
New php-forum User
 
Posts: 11
Joined: Fri Jan 28, 2011 7:21 pm

Re: stream_set_blocking fgets doesn't wait for data

Postby johnj » Sat Jun 22, 2013 4:36 am

There has to be a looping for this code irrespective of somebody else providing a looping
Code: Select all
   $message = stream_get_line($client, 8192, "|");
   if (!$message)
   {   wlog("Reading first message failed");
      fclose($client);
      wlog("Connection closed");
      $accepted = false ;
      return 1 ;
   }


When the control reaches this particular stream_get_line() it just passes to the next line without waiting.

Edit: my mistake - you don't need a "while" as you have only a single line of response.
Last edited by johnj on Sat Jun 22, 2013 5:02 am, edited 1 time in total.
johnj
php-forum Super User
php-forum Super User
 
Posts: 1805
Joined: Thu Mar 10, 2011 5:07 pm

Re: stream_set_blocking fgets doesn't wait for data

Postby johnj » Sat Jun 22, 2013 4:54 am

I hope the same port is used by the client and server.
johnj
php-forum Super User
php-forum Super User
 
Posts: 1805
Joined: Thu Mar 10, 2011 5:07 pm

Re: stream_set_blocking fgets doesn't wait for data

Postby johnj » Sat Jun 22, 2013 5:06 am

Another thing you can try is to use sleep(5) after stream_set_blocking()
johnj
php-forum Super User
php-forum Super User
 
Posts: 1805
Joined: Thu Mar 10, 2011 5:07 pm

Re: stream_set_blocking fgets doesn't wait for data

Postby johnj » Sat Jun 22, 2013 5:18 am

Some version of php does not support stream_set_blocking. What is your OS and what version of php are you using?

You can also try this irrespective of what I mentioned above: remove stream_set_blocking(). Replace stream_get_line() with fread().
johnj
php-forum Super User
php-forum Super User
 
Posts: 1805
Joined: Thu Mar 10, 2011 5:07 pm

Re: stream_set_blocking fgets doesn't wait for data

Postby DaveKimble » Mon Jun 24, 2013 7:02 am

After doing a rewrite of the server and client scripts, but using the stream functions in the same way, the problem has magically disappeared and its now working OK.

In case it helps anyone else, to clarify: stream_get_line() in blocking mode will wait for a response, while in non-blocking mode it will return straight away. This is not documented at http://au1.php.net/manual/en/function.s ... t-line.php . The same is true for fgets(), which is also not documented. stream_set_blocking() documents it for fgets().

Thanks johnj for your help.
DaveKimble
New php-forum User
New php-forum User
 
Posts: 11
Joined: Fri Jan 28, 2011 7:21 pm

Re: stream_set_blocking fgets doesn't wait for data

Postby jaysismyson » Fri Jul 05, 2013 1:55 am

Looks like this is getting timed out Aion Kinah even before you receive any data.
jaysismyson
New php-forum User
New php-forum User
 
Posts: 3
Joined: Fri Jul 05, 2013 1:49 am


Return to PHP coding => General

Who is online

Users browsing this forum: Yahoo [Bot] and 1 guest

Sponsored by Sitebuilder Web hosting and Traduzioni Italiano Rumeno and antispam for cPanel.