Miloš Đakonović
Miloš Đakonović

Reputation: 3871

Make stream_socket_server to stay functional after first received data package

I'm trying to make tcp socket server to create and maintain persistent bidirectional communications, via PHP's stream_socket_server().

Short version of question:

how to have tcp server created with stream_socket_server() staying alive - not failing to receive data after first successful data reception which is in my case one single character typed in terminal after telnet command?

Long version - what exactly I expect to achieve

Just for illustration, look at communication type when telneting some host with smtp server. You type in terminal telnet somehost 25 and get welcome response and (usually) smtp banner. And connection persists. Than you type hello command, and you get, again, response with option to proceed issuing further commands. Again, connection persists, you got response and option to continue. This is exact communication type I'm after.

What have I done so far

this code:

<?php

$server = stream_socket_server("tcp://0.0.0.0:4444", $errno, $errorMessage);

if ($server === false) throw new UnexpectedValueException("Could not bind to socket: $errorMessage");

for (;;)  {
    $client = stream_socket_accept($server);

    if ($client) 
    {
        echo 'Connection accepted from ' . stream_socket_get_name($client, false) . "\n";
        echo "Received Out-Of-Band: " . fread($client, 1500) . "\n";
        #fclose($client);
    } 

}

which works fine if you are just trying to send data (once per shot) via another PHP script i.e. stream_socket_client().

Server created by this script fails to maintain connection type I have described. After doing telnet localhost 4444 I'm switched into terminal mode to write message. When I do so, on the server side I got first typed character caught up and - nothing more. Whatever I've tried, I couldn't catch new packages sent from client side by typing. Like stream_socket_accept() blocks or ignores all after first character-data package received. So, what am I doing wrong - how to solve this issue?

Upvotes: 3

Views: 1071

Answers (1)

Brian White
Brian White

Reputation: 8756

Your program is only doing a single read before it loops back to accept another incoming connection.

The documentation for fread states that it will return as soon as a packet has been received. That is, it won't wait for the full 1500 bytes.

Given the slow speed of human typing, you end up sending a packet with a single character to your server which is returned and then it goes on to accept another incoming connection.

Put a loop around your read as such:

for (;;)  {
    $client = stream_socket_accept($server);

    if ($client) {
        echo 'Connection accepted from ' . stream_socket_get_name($client, false) . "\n";
        for (;;) {
            $data = fread($client, 1500);
            if ($data == '') break;
            echo "Received Out-Of-Band: " . $data . "\n";
        }
        fclose($client);
    } 
}

Upvotes: 1

Related Questions