New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IO::Socket::INET: a way to read 1 packet #4637
Comments
From tokuhirom@gmail.comWhen I'm implementing a http client, I need to read 1 packet data without expecting size. In socket programming context, this case is generic requirement. In rakudo's src/core/IO/Socket.pm. It calls nqp::readfh. method recv (Cool $chars = Inf, :$bin? = False) { It's mapped to read_fhb on MoarVM. QAST::MASTOperations.add_core_moarop_mapping('readfh', 'read_fhb', 1); see src/vm/moar/QAST/QASTOperationsMAST.nqp. And then, it calls MVM_io_syncstream_read_bytes(scrc/io/syncstream.c). If there's no enough bytes in the buffer, MoarVM calls read_to_buffer, that calls uv_read_start -> uv_read_stop async. Main thread goes to MVM_string_decodestream_bytes_to_buf(src/strings/decode_stream.c). It will do a busy loop to read bytes to buffering the requested bytes. I request to implement a way to read 1 packet. |
From @geekosaurOn Fri, Oct 9, 2015 at 7:51 PM, Tokuhiro Matsuno <
In TCP there is no such thing as 1 packet; TCP is a stream, you *cannot* -- |
The RT System itself - Status changed from 'new' to 'open' |
From @moritzOn Fri Oct 09 18:41:11 2015, allbery.b@gmail.com wrote:
Probably "read everything that's in the buffer right now, and if nothing is in there, wait until something is". Which is what recv should actually do, IMHO. And the limit passed to recv is traditionally an upper limit, not an "at least". |
From @jnthnOn Fri Oct 09 16:51:39 2015, tokuhirom wrote:
This is what recv does.
Correct so far. Note that unlike the implementation of read, there is no loop here.
/* See if we've already enough; if not, try and grab more. */ /* Read as many as we can, up to the limit. */ Note that there is no loop here. At most we issue one read_to_buffer, which does not contain a loop either. We wait until libuv gives us data exactly once.
Structurally, a decode stream of itself cannot cause another I/O request to be made. It doesn't hold any I/O handles, just a linked list of byte buffers it can decode if it needs to. The loop inside of the decode stream you refer to looks like this: while (taken < bytes && ds->bytes_head) { The first part of the condition is about not handing back data beyond the limit. The second is making sure we terminate the loop when we've consumed all of the byte buffers already in the decode stream. Further, we can see the only calls in this function are to memcpy and MVM_free, so it certainly can't be causing more I/O. In summary, I think recv is already doing what you want. To be sure, I wrote tests in S32-io/socket-recv-vs-read.t to make sure recv does not block, which also pass. Thanks, /jnthn |
@jnthn - Status changed from 'open' to 'resolved' |
Migrated from rt.perl.org#126315 (status was 'resolved')
Searchable as RT126315$
The text was updated successfully, but these errors were encountered: