From: Andrew Shvets <andrew.shvets@gmail.com>
Subject: Re: Finding the end of a stream from a socket
Date: Sat, 21 Oct 2017 06:45:22 -0700 (PDT)
Date: 2017-10-21T06:45:22-07:00 [thread overview]
Message-ID: <9e50578f-d646-4b86-88f9-68a123959ea1@googlegroups.com> (raw)
In-Reply-To: <osf1dm$e8h$1@gioia.aioe.org>
On Saturday, October 21, 2017 at 4:44:42 AM UTC-4, Dmitry A. Kazakov wrote:
> On 2017-10-21 04:05, Andrew Shvets wrote:
>
> > I've been recently trying to make a small TCP server (a toy.) I have
> > a channel that reads Characters and was trying to find the end of
> > the stream. Reading the documentation, I came across the following
> > in g-socket.ads:
> >
> > type Stream_Access is access all Ada.Streams.Root_Stream_Type'Class;
> > -- Same interface as Ada.Streams.Stream_IO
> >
> > I was trying to have a way to find out when the last Character was
> > read from the stream. I could catch the Ada.IO_Exceptions.End_Error
> > exception, but I'm wondering if there is a better way.
>
> End_Error is the best possible way, when applied. GNAT socket streams do
> not raise End_Error, AFAIK.
>
> > while not Ada.Streams.Stream_IO.End_Of_File(Channel) loop
> > Character'Read(Channel, Received_Char);
> > Ada.Text_IO.Put(Received_Char);
> > end loop;
>
> This is a bad idea even when if it can work. In the case of sockets
> there is no file end. When the connection is closed by the peer the
> stream will stop both returning data and blocking. I suppose that will
> cause Constraint_Error in Character'Read.
>
> In practice there is a higher level protocol on top of the socket
> stream, so that it is always known how many octets to read next.
>
> Regarding your case, try this:
>
> Buffer : Stream_Element_Array (1..Buffer_Size);
> Last : Stream_Element_Offset;
> begin
> loop
> Receive_Socket (Socket, Buffer, Last);
> exit when Last < Buffer'First; -- Connection is closed by the peer
> for Octet in Buffer'First..Last loop -- Dump octets as-is
> Put (Character'Val (Buffer (Octet)));
> end loop;
> end loop;
>
> --
> Regards,
> Dmitry A. Kazakov
> http://www.dmitry-kazakov.de
Thanks for your reply. I did what you recommended.
loop
begin
GNAT.Sockets.Receive_Socket(Receiver, Buffer, Last);
-- the connection was reset by peer.
exit when Last < Buffer'First;
for Octet in Buffer'First .. Last loop
Ada.Text_IO.Put(Character'Val(Buffer(Octet)));
end loop;
exception
when Ada.IO_Exceptions.End_Error =>
Ada.Text_IO.Put_Line(Ada.Text_IO.Standard_Error, " ERROR: Issue encountered while receiving data from user.");
end;
end loop;
I get the following error when I make the Receive_Socket procedure call:
raised GNAT.SOCKETS.SOCKET_ERROR : [107] Transport endpoint is not connected
next prev parent reply other threads:[~2017-10-21 13:45 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-10-21 2:05 Finding the end of a stream from a socket Andrew Shvets
2017-10-21 8:44 ` Dmitry A. Kazakov
2017-10-21 13:45 ` Andrew Shvets [this message]
2017-10-21 18:11 ` Dennis Lee Bieber
2017-10-21 19:19 ` Dmitry A. Kazakov
2017-10-21 19:46 ` Andrew Shvets
2017-10-22 12:26 ` Andrew Shvets
2017-10-22 12:28 ` Andrew Shvets
2017-10-22 13:28 ` Dmitry A. Kazakov
2017-10-21 17:34 ` Andrew Shvets
2017-10-21 19:18 ` Andrew Shvets
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox