[Haskell-beginners] Network client - reading and writing to a socket

David McBride dmcbride at neondsl.com
Mon Aug 1 00:21:07 CEST 2011


It seems you are expected to fetch until you have the entire thing.
You can't just fetch 40000 and hope you get it all.  If you do it
blocking, it will be almost guaranteed to block unless there were
40000 to fetch.  If you do it non blocking, you have to keep fetching
until you are sure you have the entire message.

If you are doing this as simply as possible, that means you have to
fetch, and then repeatedly check the string until you are sure you
have the whole thing.  You'll do that by fetching once, checking the
beginning of the string for the {342} in the following example from
the rfc:

C:    a004 fetch 12 body[header]
S:    * 12 FETCH (BODY[HEADER] {342}
S:    Date: Wed, 17 Jul 1996 02:23:25 -0700 (PDT)
S:    From: Terry Gray <gray at cac.washington.edu>
S:    Subject: IMAP4rev1 WG mtg summary and minutes
S:    To: imap at cac.washington.edu
S:    cc: minutes at CNRI.Reston.VA.US, John Klensin <KLENSIN at MIT.EDU>
S:    Message-Id: <B27397-0100000 at cac.washington.edu>
S:    MIME-Version: 1.0
S:    Content-Type: TEXT/PLAIN; CHARSET=US-ASCII
S:
S:    )

And then fetching until you have the next 342 characters.  This is
pretty tedious in any language, not just haskell, but that's how this
protocol is.

If you want to do this the haskell way, which I highly recommend, I
would pull out the network-attoparsec library.  You should be able to
use parseWith and pass it a recv function that returns bytestrings.
Write a simple parser which will look for "* <num> FETCH
([a-zA-Z]+\[[a-zA-Z]+\] {[0-9]+} and then use that last number to take
(take is an attoparsec function) that last byte count.  If you wire
this up to your network socket, it will parse and slurp up the
response and it will pull the exact number of bytes needed and your
code will be very elegant.  Attoparsec is a little hard to use at
first, but it is well worth if if you have a mind to parse internet
protocols.

On Sun, Jul 31, 2011 at 3:14 PM, Patrick LeBoutillier
<patrick.leboutillier at gmail.com> wrote:
> Manfred,
>
>> The problem is that the message itself is some 30K big and I only
>> get some 16K of the message.
>>
>> How could I force to get the whole message?
>
> My guess is that you can't. This call:
>
> c' <- B.hGetNonBlocking h 40000
>
> tries to read as much as it can (up to 40000 bytes) but it won't block
> to wait for data. Perhaps the rest of your message is in a different
> TCP packet or delayed or whatever, but I think you have to keep on
> reading (and maybe block) until you know you have read the entire
> message. The IMAP specs will tell you how to identify the "end of the
> message".
>
> BTW: This issue is not Haskell specific. If you implement the same
> code in C, Perl or Java you will have to deal with the same problem.
> When you read from a socket, there is no general way of knowing that
> the other side has sent everything.
>
>
> Patrick
>
>>
>> --
>> Manfred
>>
>>
>>
>> _______________________________________________
>> Beginners mailing list
>> Beginners at haskell.org
>> http://www.haskell.org/mailman/listinfo/beginners
>>
>
>
>
> --
> =====================
> Patrick LeBoutillier
> Rosemère, Québec, Canada
>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
>



More information about the Beginners mailing list