Re: Sockets (reading)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Aug 26, 2009, at 2:47 PM, Bob McConnell wrote:

From: Philip Thompson
On Aug 26, 2009, at 11:56 AM, Bob McConnell wrote:
From: Philip Thompson

During a socket read, why would all the requested number of bytes
not
get sent? For example, I request 1000 bytes:

<?php
$data = @socket_read ($socket, 2048, PHP_BINARY_READ);
?>

This is actually in a loop, so I can get all the data if split up.
So,
for example, here's how the data split up in 3 iterations (for 1000
bytes):

650 bytes
200 bytes
150 bytes

But if I can accept up to 2048 bytes per socket read, why would it
not
pull all 1000 bytes initially in 1 step? Any thoughts on this would

be
greatly appreciated!

Because that's the way TCP/IP works, by design. TCP is a stream
protocol. It guarantees all of the bytes written to one end of the
pipe
will come out the other end in the same order, but not necessarily in
the same groupings. There are a number of buffers along the way that
might split them up, as well as limits on packet sizes in the various
networks it passed through. So you get what is available in the last
buffer when a timer expires, no more, and no less.

If you have serialized data that needs to be grouped in specific
blocks,
your application will need to keep track of those blocks,
reassembling
or splitting the streamed data as necessary. You could use UDP which
does guarantee that packets will be kept together, but that protocol
doesn't guarantee delivery.

Thank you for your input.

Is it guaranteed that at least 1 byte will be sent each time? For
example, if I know the data length...

<?php
$input = '';

for ($i=0; $i<$dataLength; $i++) {
    // Read 1 byte at a time
    if (($data = @socket_read ($socket, 1, PHP_BINARY_READ)) !==
false) {
        $input .= $data;
    }
}

return $input;
?>

Or is this a completely unreasonable and unnecessary way to get the
data?

While I have written a lot of code to manage sockets over the years, and coded a UDP/IP stack, I have never done it in PHP. And unfortunately, I don't have time to experiment right now. My boss is waiting for the next
product release from me.

Getting one byte at a time is somewhat wasteful, as it requires more
system calls than necessary. That's a lot of wasted overhead.

Whether you always get one or more bytes depends on a number of factors, including whether the calls PHP uses are blocking or non-blocking, plus
there may be ways to switch the socket back and forth.

Have you tried doing a Google search on the group of PHP functions you
expect to use. That should come up with some sample code to look at.

Bob McConnell

I agree that one byte at a time is wasteful. I'm sure others haven't implemented something along these lines, but I wrote a much more efficient way to make sure I grab all the data of a known length...

<?php
function readSocketForDataLength ($socket, $len)
{
    $offset = 0;
    $socketData = '';

    while ($offset < $len) {
if (($data = @socket_read ($socket, $len - $offset, PHP_BINARY_READ)) === false) {
            return false;
        }

        $offset += strlen ($data);
        $socketData .= $data;
    }

    return $socketData;
}
?>

If not all the data is obtained on a read, it will loop until the amount of data is the same as the length requested. This is working quite well.

Thanks Bob and the others!

~Philip

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php


[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux