php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #34851 SO_RECVTIMEO and SO_SNDTIMEO socket options expect integer parameter on windows
Submitted: 2005-10-13 11:38 UTC Modified: 2005-11-03 16:02 UTC
From: khayll at motoros dot hu Assigned: mike
Status: Closed Package: Sockets related
PHP Version: * OS: win32 only
Private report: No CVE-ID:
 [2005-10-13 11:38 UTC] khayll at motoros dot hu
Description:
------------
I tried to set a receive timeout for a socket, but found out that sec is used as usec, and usec is in fact ignored!


Reproduce code:
---------------
using a modbus device  with "address" address, sorry i cannot make it available on the net

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec"=>0, "usec"=>500));
socket_connect($socket, "address", "502");
socket_write($this->socket, $data, strlen($data));
socket_read($this->socket, 512, PHP_BINARY_READ);



Expected result:
----------------
expected to read some data or give a timeout error.


Actual result:
--------------
code hangs, so i figured out, that usec has no effect, then i tried 1 sec as timeout, code began to work, but kept reporting timeout, so i figured out if i try a value like 500000 as sec it works. Seems like sec is used as usec, and usec has no effect.


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-10-13 12:31 UTC] tony2001@php.net
Thank you for this bug report. To properly diagnose the problem, we
need a short but complete example script to be able to reproduce
this bug ourselves. 

A proper reproducing script starts with <?php and ends with ?>,
is max. 10-20 lines long and does not require any external 
resources such as databases, etc.

If possible, make the script source available online and provide
an URL to it here. Try to avoid embedding huge scripts into the report.


 [2005-10-13 14:36 UTC] khayll at motoros dot hu
<?php

	$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
	socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec"=>5, "usec"=>0));
	socket_connect($socket, "81.182.13.109", "502");

	$pdu = "";
	$pdu .= chr(0x03).chr(floor(16000 / 256)).chr(16000 % 256).chr(floor(10 / 256)).chr(10 % 256);

	$rand = mt_rand(1,65535); //generate random adu id
	$adu = "";
	$adu .= chr(floor($rand / 256)).chr($rand % 256).chr(0).chr(0).chr(floor(6 / 256)).chr(6 % 256).chr(1);
	
	socket_write($socket, $data, strlen($data));

	$result = socket_read($socket, 512, PHP_BINARY_READ);

	echo socket_strerror(socket_last_error());

	socket_shutdown($socket, 2);
	socket_close($socket);

?>
 [2005-10-13 16:16 UTC] tony2001@php.net
And actual/expected results please?
 [2005-10-13 17:38 UTC] khayll at motoros dot hu
Actual: Script gives timeout error but it does not wait for 5 seconds for the answer, as set in SO_RCVTIMEO.

Expeted: to wait max. 5 second for remote host to answer, but script executes much faster. I tried to increase second to 500000 and then it works ok.
 [2005-10-13 17:41 UTC] khayll at motoros dot hu
And if I set sec=0 usec=500000 (or 5 for a shorter timeout) it hangs, meaning to me, that usec has no effect.
 [2005-10-13 17:52 UTC] khayll at motoros dot hu
sorry I forgot a line from the code:

I also decreased the sec param to 1 because for me the remote host is quite fast.

<?php

	$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
	socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec"=>1, "usec"=>0));
	socket_connect($socket, "81.182.13.109", "502");

	$pdu = "";
	$pdu .= chr(0x03).chr(floor(16000 / 256)).chr(16000 % 256).chr(floor(10 / 256)).chr(10 % 256);

	$rand = mt_rand(1,65535); //generate random adu id
	$adu = "";
	$adu .= chr(floor($rand / 256)).chr($rand % 256).chr(0).chr(0).chr(floor(6 / 256)).chr(6 % 256).chr(1);
	
	$data = $adu.$pdu;

	socket_write($socket, $data, strlen($data));

	$result = socket_read($socket, 512, PHP_BINARY_READ);

	echo socket_strerror(socket_last_error());

	socket_shutdown($socket, 2);
	socket_close($socket);

?>
 [2005-10-13 17:52 UTC] tony2001@php.net
Well, that's because USEC are *microseconds*, not milliseconds.
Try to use sec=0 usec=5000000 instead.
 [2005-10-13 18:18 UTC] khayll at motoros dot hu
Please read carefully what I wrote...

If I use 0 sec and 500 usec, the script HANGS when there's no response (which means usec has NO EFFECT)! (Sorry I cannot reproduce remote machine not sending a response, but accepting connections) and with a setting of 1 sec 0 usec which is pretty much for a response I get a timeout error.

here execute this script and it will show you the script execution time is less than 1 sec at all giving a timeout:

<?php

	echo microtime()."<br>\n";

	$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
	socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec"=>1, "usec"=>0));
	socket_connect($socket, "81.182.13.109", "502");

	$pdu = "";
	$pdu .= chr(0x03).chr(floor(16000 / 256)).chr(16000 % 256).chr(floor(10 / 256)).chr(10 % 256);

	$rand = mt_rand(1,65535); //generate random adu id
	$adu = "";
	$adu .= chr(floor($rand / 256)).chr($rand % 256).chr(0).chr(0).chr(floor(6 / 256)).chr(6 % 256).chr(1);
	
	$data = $adu.$pdu;

	socket_write($socket, $data, strlen($data));

	$result = socket_read($socket, 512, PHP_BINARY_READ);

	if($result===false)	echo socket_strerror(socket_last_error())."<br>\n";

	socket_shutdown($socket, 2);
	socket_close($socket);

	echo microtime()."<br>\n";

?>

result:

0.32968200 1129220264

Warning: socket_read() unable to read from socket [0]: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. in c:\data\web\rtu\rtu_web\phpbug.php on line 20
A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. 
0.89507800 1129220264
 [2005-10-14 14:36 UTC] mike@php.net
Winsock implementation does not support all BSD options for setsockopt, SO_RCVTIMEO is within these.



 [2005-10-14 15:08 UTC] mike@php.net
But I cannot reproduce either, here's what I receive (base64),
without warnings (on Win2k):

PHP-4.3.8: "UukAAAAXAQMUcmV2LjIuMiAgIAAAAgFQMUVSSyA="
PHP-5-CVS: "/AoAAAAXAQMUcmV2LjIuMiAgIAAAAgFQMUVSSyA="

 [2005-10-14 15:24 UTC] mike@php.net
Ok, ok, my last comment :)

The real problem seems to be that windows expects a DWORD and not a timeval as parameter.

 [2005-10-25 20:09 UTC] mike@php.net
Target for 4.4.2
 [2005-11-03 16:02 UTC] mike@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Mon Apr 21 00:02:04 2014 UTC