From: Simon Wright <simon@pushface.org>
Subject: Re: "broken pipe" while reading/writing stream-based sockets
Date: Fri, 20 May 2005 21:02:49 +0100
Date: 2005-05-20T21:02:49+01:00 [thread overview]
Message-ID: <m264xdvf6e.fsf@grendel.local> (raw)
In-Reply-To: 1116601288.424625.176760@g14g2000cwa.googlegroups.com
"fabio de francesco" <fmdf@tiscali.it> writes:
> Florian Weimer wrote:
>> * fabio de francesco:
>>
>> > 1) Why does this server sometimes crash with "Broken Pipe"?
>>
>> This usually indicates that the client closed its end of the
>> connection while the server was still sending data. Maybe this
>> happens because your code does not deal with partial reads/writes.
>>
>> > 2) It seems that using Input/Output instead of Read/Write never
> causes
>> > "Broken Pipe". Why?
>>
>> The stream implementation provided by GNAT.Sockets deals with partial
>> reads and writes.
>
> In C I know how to read() in a loop and increment a pointer to a buffer
> (a C string) while receiving characters until there are no more of
> them. It is sufficient that read() returns how many characters has
> already read and some little math involving buffer size.
>
> In Ada I don't know how to do it... Can you please give me any
> suggestions?
I'm sure there's a better way .. but this is what I did
function Read_Request (From : Socket_Type) return String is
Tmp : Stream_Element_Array (1 .. 2048);
Last : Stream_Element_Offset := Tmp'First - 1;
Next : Stream_Element_Offset;
Termination : constant Stream_Element_Array :=
(Character'Pos (CR),
Character'Pos (LF),
Character'Pos (CR),
Character'Pos (LF));
S : Stream_Access := Stream (From);
begin
-- We need to read the whole request from the client. Of course
-- we don't know how long it is. We can't just issue an
-- Ada.Streams.Read for a large buffer, because the client may
-- not have sent that much and if she hasn't we'll block until
-- she gives up and closes the socket. So we read a character
-- at a time until we've got the CR/LF/CR/LF which terminates
-- the line.
loop
Ada.Streams.Read (Stream => S.all,
Item => Tmp (Last + 1 .. Last + 1),
Last => Next);
exit when Next = Last;
Last := Last + 1;
exit when Last >= Termination'Length
and then Tmp (Last - 3 .. Last) = Termination;
exit when Last = Tmp'Last;
end loop;
Free_Stream (S);
declare
Result : String (1 .. Natural (Last));
pragma Import (Ada, Result);
for Result'Address use Tmp'Address;
begin
return Result;
end;
end Read_Request;
prev parent reply other threads:[~2005-05-20 20:02 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-05-10 23:02 "broken pipe" while reading/writing stream-based sockets fabio de francesco
2005-05-11 10:46 ` Adrien Plisson
2005-05-11 15:01 ` fabio de francesco
2005-05-11 21:18 ` Simon Wright
2005-05-11 23:30 ` fabio de francesco
2005-05-13 20:18 ` fabio de francesco
2005-05-13 20:25 ` fabio de francesco
2005-05-14 20:39 ` Jeffrey Carter
2005-05-14 21:27 ` Florian Weimer
2005-05-20 15:01 ` fabio de francesco
2005-05-20 17:52 ` tmoran
2005-05-20 20:02 ` Simon Wright [this message]
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox