检索后从套接字流中读取阻塞

Reading from Socket Stream Blocking After Retrieval

我目前正在尝试从客户端套接字读取传入消息,该消息在执行以下过程之前已经连接到服务器套接字。下面的过程在从流中检索消息时输出消息,一次一个字符。

问题是,当流中没有信息时,对 Ada.Streams.Read 的调用会阻塞,并完全停止应用程序流。根据某些示例,似乎 Offset 应该在流结束时自动设置为 0,但这种情况从未发生过。相反,应用程序在调用 Read.

时停止
procedure Read_From (Channel : Sockets.Stream_Access) is

    use Ada.Text_IO;
    use Ada.Streams;

    Data   : Stream_Element_Array (1 .. 1);
    Offset : Stream_Element_Offset;
begin
    loop
        Read (Channel.All, Data, Offset);
        exit when Offset = 0;
        Put (Character'Val (Data (1)));
    end loop;

    -- The application never reaches this point.

    New_Line;
    Put_Line ("Finished reading from client!");
end Read_From;
-- @param Channel `GNAT.Sockets.Stream (Client_Socket)`

我也尝试过 GNAT.Sockets.Receive_Socket 的相同过程,但同样的问题仍然存在:应用程序流已完全停止,可能正在等待来自流的更多信息,即使没有更多信息可检索。

任何正确方向的指示都将不胜感激!

基本上这就是 Ada 流的工作方式。只有当您到达流的最后一端时,流才会结束,而不仅仅是缓冲区的当前末尾。

如果你想能够中断阅读,你必须使用不同于GNAT.Sockets.Stream_Access的另一种连接表示。

通常情况下,您会从知道需要读取多少数据的流中读取一条(二进制)消息,因此您可以一直读取直到读取到那么多。

但是,如果您正在从外部定义的来源读取文本消息,因为它可能是 HTTP 请求,则需要一些终止符序列,以便您可以逐个字符地阅读,直到您阅读终结者。在 HTTP 请求的情况下,这是一个 CR/LF/CR/LF 序列。或者它可能是一个空终止的 C 字符串,在这种情况下你会寻找 ASCII.NUL.

传输可变长度文本的 Ada 方法是使用 String’Output/String’Input(参见 ARM 13.13.2(18)ff)。 StringCharacter 的数组)发生的情况是首先发送边界,然后发送内容;在接收时,读取边界,创建具有这些边界的 String,并将所需的字节数读入新的 String,然后返回。