Чтение из Socket Stream, блокирующееся после получения - PullRequest
0 голосов
/ 29 октября 2018

В настоящее время я пытаюсь прочитать входящее сообщение из клиентского сокета, которое до описанной ниже процедуры уже было подключено к серверному сокету. Приведенная ниже процедура выводит сообщение по одному символу за раз, когда оно извлекает его из потока.

Проблема в том, что, когда в потоке нет информации, вызов 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, но та же проблема остается: поток приложения полностью останавливается, ожидая получения дополнительной информации из потока, даже если больше нечего извлекать.

Любые указатели в правильном направлении будут высоко оценены!

Ответы [ 2 ]

0 голосов
/ 30 октября 2018

Обычно вы читаете (двоичное) сообщение из потока, зная, сколько данных необходимо прочитать, чтобы вы могли читать, пока не получите столько.

Но, если вы читаете текстовое сообщение из внешнего источника, как это может быть HTTP-запрос, должна быть некоторая последовательность терминатора, чтобы вы могли читать символ за символом, пока не прочитаете терминатор. В случае HTTP-запроса это последовательность CR / LF / CR / LF. Или это может быть строка C с нулевым символом в конце, и в этом случае вы будете искать ASCII.NUL.

Ада способ передачи текста переменной длины заключается в использовании String’Output / String’Input (см. ARM 13.13.2 (18) ff). Что происходит с String (массивом Character), так это то, что сначала отправляются границы, а затем содержимое; при получении считываются границы, создается String с этими границами и необходимое количество байтов считывается в новый String, который затем возвращается.

0 голосов
/ 29 октября 2018

По сути, так работают потоки Ada. Конец потока наступает только тогда, когда вы достигнете конечного конца потока, а не только текущего конца буфера.

Если вы хотите прервать чтение, вам нужно использовать другое представление соединения, чем GNAT.Sockets.Stream_Access.

...