On Wed, Aug 26, 2009 at 5:36 PM, Philip Thompson <philthathril@xxxxxxxxx>wrote: > 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 > > socket related: Does this solution work on both, blocking and non-blocking sockets ? And what about different read method? solution related: Does strlen works fine with binary data? Does this snippet work for sending/receiving multibytes strings? -- Martin Scotta