#28141 [Bgs]: socket_read return type: false vs "", when PHP_NORMAL_READ
| From: | php at richardneill dot org | Date: | Mon, 14 Feb 2005 16:30:03 +0000 |
| Subject: | #28141 [Bgs]: socket_read return type: false vs "", when PHP_NORMAL_READ | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-74039@lists.php.net to get a copy of this message | ||
ID: 28141
User updated by: php at richardneill dot org
Reported By: php at richardneill dot org
Status: Bogus
Bug Type: Sockets related
Operating System: Linux
PHP Version: 4CVS, 5CVS (2005-02-14)
Assigned To: andrey
New Comment:
Thanks. That makes sense. However, it still leaves a few problems,
essentially with wrong documentation.
-------------------
1)The documentation for socket_read
http://uk.php.net/manual/en/function.socket-read.php
claims:
"Note: socket_read() may return a zero length string ("") indicating
the end of communication (i.e. the remote end point has closed the
connection)."
which is obviously not true.
---------------------
2)Example 1 on the sockets page
http://uk.php.net/manual/en/ref.sockets.php
also supports the interpretation that
False => error; null => connection closed
if (false === ($buf = socket_read($msgsock, 2048,
PHP_NORMAL_READ))) {
echo "socket_read() failed: reason: " .
socket_strerror($ret) . "\n";
break 2;
}
if (!$buf = trim($buf)) {
continue;
}
----------------------
3)How is one to determine the difference between
i)the other side closing the connection normally
and
ii)something going very wrong with the function?
According to the documentation,
"" => (i)
false => (ii)
In fact, it seems that
false => (i) or (ii), with no way to tell
"" => never actually happens
Thanks for your help,
Richard
Previous Comments:
------------------------------------------------------------------------
[2005-02-14 09:10:12] sniper@php.net
There is no bug to fix here. You're actually getting "Connection reset
by peer" (ECONNRESET) and that makes recv() to return -1 -> PHP
socket_read() returns an error and FALSE.
Here's simplified WORKING script:
#!/usr/local/bin/php
<?php
error_reporting(E_ALL);
/* Allow the script to hang around waiting for connections. */
set_time_limit(0);
/* Turn on implicit output flushing so we see what we're getting as it
comes in. */
ob_implicit_flush();
$address = '127.0.0.1';
$port = 1111;
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($sock, $address, $port);
socket_listen($sock, 5);
do {
$msgsock = socket_accept($sock);
do {
$buf = socket_read($msgsock, 2048, PHP_NORMAL_READ);
var_dump($buf);
} while ($buf !== FALSE && $buf !== '');
echo socket_strerror(socket_last_error($msgsock));
socket_close($msgsock);
echo "Closed msgsocket; waiting for another connection\n";
} while (true);
socket_close($sock);
echo "Closed main socket, exiting\n";
?>
------------------------------------------------------------------------
[2004-07-28 21:04:13] andrey@php.net
Assigning to myself (to get notification if i forget), changing the
version.
------------------------------------------------------------------------
[2004-07-26 10:37:34] php at hristov dot com
I will take a look later today or these days. But for now, the code in
the function is :
if (type == PHP_NORMAL_READ) {
retval = php_read(php_sock->bsd_socket, tmpbuf, length, 0);
} else {
retval = recv(php_sock->bsd_socket, tmpbuf, length, 0);
}
if (retval == -1) {
PHP_SOCKET_ERROR(php_sock, "unable to read from socket", errno);
efree(tmpbuf);
RETURN_FALSE;
}
------------------------------------------------------------------------
[2004-07-18 17:13:56] php2 at richardneill dot org
I've still got the same thing happening in PHP5.0.0(final)
I'm having some trouble with your example, so I'm using the attached
instead. It's basically copied from the php-sockets manual, but
slightly modified.
The key point: according to the documentation, when
(socket_read()===false), it means something has gone very wrong, i.e.
a fatal error. However, in practice, all this means is that the other
side has closed the connection.
I'm running this code as ./testsock.php
and the client is simply: netcat localhost 1111
The problem is that, if netcat is killed with Ctrl-C, then the server
suffers a fatal error. I don't think that it should.
I've tried it under both version php-cli-4.3.7-4mdk (the current devel
version from Mandrake cooker) and php-5.0.0-cli which I just compiled.
In both cases, the same thing happens.
Regards
Richard
-------------------------------------
#!/usr/local/bin/php
<?php
error_reporting(E_ALL);
/* Allow the script to hang around waiting for connections. */
set_time_limit(0);
/* Turn on implicit output flushing so we see what we're getting as it
comes in. */
ob_implicit_flush();
$address = '127.0.0.1';
$port = 1111;
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) < 0) {
echo "socket_create() failed: reason: " . socket_strerror($sock) .
"\n";
}else{
echo "Created socket $sock\n";
}
if (($ret = socket_bind($sock, $address, $port)) < 0) {
echo "socket_bind() failed: reason: " . socket_strerror($ret) .
"\n";
}else{
echo "Bound socket $sock to port $port on address $address\n";
}
if (($ret = socket_listen($sock, 5)) < 0) {
echo "socket_listen() failed: reason: " . socket_strerror($ret) .
"\n";
}else{
echo "listening...\n";
}
do {
if (($msgsock = socket_accept($sock)) < 0) {
echo "socket_accept() failed: reason: " .
socket_strerror($msgsock) . "\n";
break;
}
/* Send instructions. */
$msg = "Welcome to the PHP Test Server.\nTo quit, type 'quit'. To
shut down the server type 'shutdown'.\n".
"To crash this server, quit netcat with Ctrl-C\n";
socket_write($msgsock, $msg, strlen($msg));
do {
$buf = socket_read($msgsock, 2048, PHP_NORMAL_READ);
if ($buf==''){
echo "Socket received an empty string.\n";
}
if ($buf ===false){
echo "socket_read() failed: reason: " .
socket_strerror($ret) . ". This shouldn't happen. Fatal exit.\n";
break 2;
}
/* According to the documentation, testing for socket_read being
false is a sign of a fatal error, whereas an empty string
is means the remote side has closed the connection. Actually both
"" and false indicate the remote side has closed the connection.
the socket_strerror isn't very helpful - it says "operation not
permitted" */
$buf=trim($buf); #Trim whitespace.
if ($buf == 'quit') {
echo "Quit command received\n";
break;
}
if ($buf == 'shutdown') {
socket_close($msgsock);
echo "Shutdown command received\n";
break 2;
}
$talkback = "PHP: You said '$buf'.\n";
socket_write($msgsock, $talkback, strlen($talkback));
echo "$buf\n";
} while (true);
socket_close($msgsock);
echo "Closed msgsocket; waiting for another connection\n";
} while (true);
socket_close($sock);
echo "Closed main socket, exiting\n";
?>
------------------------------------------------------------------------
[2004-07-18 14:29:51] andrey@php.net
I cannot reproduce the problem with latest PHP5. Can you provide a
*full* reproducing case.
My scripts are :
server:
<?php
error_reporting(E_ALL);
set_time_limit(0);
ob_implicit_flush();
$address = '127.0.0.1';
$port = 4322;
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) < 0) {
echo "socket_create() failed: reason: " . socket_strerror($sock) .
"\n";
}
if (($ret = socket_bind($sock, $address, $port)) < 0) {
echo "socket_bind() failed: reason: " . socket_strerror($ret) .
"\n";
}
if (($ret = socket_listen($sock, 5)) < 0) {
echo "socket_listen() failed: reason: " . socket_strerror($ret) .
"\n";
}
do {
if (($msgsock = socket_accept($sock)) < 0) {
echo "socket_accept() failed: reason: " .
socket_strerror($msgsock) . "\n";
break;
}
$buffer=socket_read($msgsock,2048,PHP_NORMAL_READ);
$buffer2=socket_read($msgsock,2048,PHP_NORMAL_READ);
var_dump($buffer, $buffer2);
if ($buffer===false){
echo "Error: socket_read() failed: reason:
".socket_strerror(socket_last_error())." \n";
break;
} else if ($buffer=='') {
echo "Socket $socket returned an empty string. Closing
connection\n";
socket_close($socket);
} else {
echo "Received data".trim($buffer)."\n";
}
socket_close($msgsock);
} while (true);
socket_close($sock);
?>
client:
<?php
error_reporting(E_ALL);
echo "TCP/IP Connection\n";
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket < 0) {
echo "socket_create() failed: reason:
".socket_strerror($socket)."\n";
} else {
echo "OK.\n";
}
echo "Attempting to connect to '127.0.0.1' on port '4322'...";
$result = socket_connect($socket, "127.0.0.1", 4322);
if ($result < 0) {
echo "socket_connect() failed.\nReason: ($result)
".socket_strerror($result) . "\n";
} else {
echo "OK.\n";
}
$s = "ALA\n";
socket_write($socket, $s);
echo "Closing socket...";sleep(5);
socket_close($socket);
echo "OK.\n\n";
?>
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
http://bugs.php.net/28141
--
Edit this bug report at http://bugs.php.net/?id=28141&edit=1