H
H
Horzerus2011-10-26 18:40:23
PHP
Horzerus, 2011-10-26 18:40:23

How to make pfsockopen() in php not spawn connections?

Task: learn how to use persistent socket connections to a TCP server. those. so that the repeated launch of the php script does not create a new connection, but tries to use the previous still open connection.
But there is no way to do that.

My experimental php (ver 5.3.3) script:

<?php<br>
$fp = pfsockopen("tcp://127.0.0.1", "1337", $errno, $errstr, 60); <br>
if ($fp) { <br>
    var_dump($fp); // выводит "resource(1..2) of type (persistent stream)"<br>
    echo "ftell(): " . ftell($fp) . "\n"; // выводит всегда "0"<br>
    fputs($fp, time() . "\n"); <br>
    echo "readed data: '" . fread($fp, 10) . "'\n"; // выводит 10 принятых байт<br>
    fclose($fp); <br>
} <br>

People on the Internet usually ask about pfsockopen, saying “how to save the socket handle so that they can use it later”, to which they are told that of course this is impossible. And pfsockopen(), called with the same attributes, supposedly should itself return the handle of an already open socket.

The php manual pfsockopen() has a note:
To see if it's really a new connection, or a reused one, you can use ftell() — and see if ther's been any traffic on the connection. If it's more than 0, then it's a reused connection.
However, my ftell() stubbornly returns zero, i.e. connection is created new.

If you run netstat in the terminal, you can also see that connections are added with each run of the script:
$ netstat -t -a --numeric-hosts | grep 1337<br/>
tcp 0 0 127.0.0.1:1337 0.0.0.0:* LISTEN <br/>
tcp 0 0 127.0.0.1:51754 127.0.0.1:1337 TIME_WAIT <br/>
tcp 1 0 127.0.0.1:51648 127.0.0.1:1337 CLOSE_WAIT <br/>
tcp 1 0 127.0.0.1:51652 127.0.0.1:1337 CLOSE_WAIT <br/>
tcp 1 0 127.0.0.1:51654 127.0.0.1:1337 CLOSE_WAIT <br/>
tcp 1 0 127.0.0.1:51650 127.0.0.1:1337 CLOSE_WAIT <br/>
tcp 1 0 127.0.0.1:51646 127.0.0.1:1337 CLOSE_WAIT <br/>
tcp 0 0 127.0.0.1:51752 127.0.0.1:1337 TIME_WAIT <br/>
tcp 1 0 127.0.0.1:51644 127.0.0.1:1337 CLOSE_WAIT <br/>
tcp 0 0 127.0.0.1:51756 127.0.0.1:1337 TIME_WAIT <br/>
tcp 1 0 127.0.0.1:51656 127.0.0.1:1337 CLOSE_WAIT <br/>

As a server I use nodejs (ver 0.4.10) script:
var net = require('net'),<br>
    server;<br>
<br>
server = net.createServer({allowHalfOpen: false});<br>
server.on('connection', function(socket) {<br>
    console.log('connection opened\n', socket);<br>
<br>
    socket.on("data", function(str) {<br>
        console.log("data: " + str + "\n");<br>
        socket.write("response\n");<br>
    });<br>
});<br>
<br>
server.on('close', function() {<br>
    console.log('connection closed\n');<br>
});<br>
<br>
server.listen(1337, "127.0.0.1");<br>

Switching the allowHalfOpen parameter has no effect.

How do I run a php script
The script works instantly, then I run it again. Tried with:
  1. Through a commandline call (google suggests that it should not work)
  2. Module for Apache 2.2.16 (libphp5.so)
  3. php5-fpm as fastcgi in nginx

The result is the same.

Tell me where to dig further?
Thank you!

Answer the question

In order to leave comments, you need to log in

1 answer(s)
P
p4s8x, 2011-10-27
@p4s8x

There is clearly a mystic here!
To find out which specific connection is used, you need to use
stream_socket_get_name ($fp,false) ; // or true depending on the side
But this did not help me much)
ftell should return something like position, but it always gave me 0 regardless of whether something was written to the socket or not.
It was empirically found that if the connection is not touched for (approximately) 5 seconds, then a new one is used, if the connection is reopened too quickly, then it either creates a new one or uses one of the already created ones, but if this one of the created ones has not been used for 5 seconds, then he following the "rule" creates a new one. and those 5 seconds is not a timeout value.
If, for example, one character is written to the socket, then the sniffer will show that the same connection was written several times.
Digging further)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question