如何使用Ada正确读写套接字?

时间:2014-02-05 12:40:01

标签: ada

基本上,我设法将多个客户端连接到一台服务器,但是从服务器读取时遇到问题。我有两个任务(线程):一个用于阅读,一个用于写作。

  1. 偏移量永远不会为0,从而导致无限循环。每次有来自服务器的新传入消息时,如何打印"Incoming > "
  2. 我不确定缓冲区大小。我尝试了1..1024但是在服务器发送1024个字符之前没有打印。
  3. String'Write的快捷方式ada.streams.write
  4. 编写数据

    String'Write(channel, "Hello client");
    --Where channel is Gnat.Sockets.Stream_Access type
    

    从服务器读取数据

        task body reader_task is    
          Offset : Streams.Stream_Element_Count;
          Buffer : Streams.Stream_Element_Array (1 .. 1);
       begin
         loop
          Text_IO.put_line("Incoming > "); 
          loop
              Streams.Read (Channel.All, Buffer, Offset);
          exit when offset = 0; 
              for I in Buffer'Range loop
                  Text_IO.Put (Character'Val (Buffer (I)));
              end loop;
          end loop;
         end loop;
       end reader_task; 
    

2 个答案:

答案 0 :(得分:4)

要回答上一个问题:String'Write 使用 Ada.Streams.Write(更准确地说,因为Ada.Streams.Write对抽象类型进行操作并且正在调度,它将调用任何内容已为实际流类型编写了覆盖Write。但这不是速记。 Ada.Streams.Write采用Stream_Element数组作为参数(Stream_Element可能是一个字节)。但是String'Write需要String,这是一个字符数组,而不是一个流元素数组。该实现将String视为流元素的数组并写入每个元素。实际上,它会写出每个字符,因此结果非常相似,但结构并不相同。 Integer'Write之类的东西会将整数视为流元素数组,并在其上调用Ada.Streams.Write;如何实现没有定义。

'Write也可用于用户定义的类型。有关如何工作的默认规则,但您也可以编写自己的'Write例程来代替默认例程。 RM 13.13.2解释了所有这些。

(前两个问题似乎是关于Read是否阻塞或非阻塞GNAT套接字。我不知道答案。)

答案 1 :(得分:3)

GNAT套接字是阻塞创建的,所以当你调用Streams.Read时,它会从套接字读取,直到

  1. 您的缓冲区已满;或
  2. 还没有更多的字节需要读取;或
  3. 套接字已关闭。
  4. 在案例2中,Read调用将阻塞,直到有更多数据到达。只有在第3种情况下,您才能获得一个不足的缓冲区(在您的代码中,Offset小于Buffer’Last)。

    如果您有多个客户端,其中任何一个都可以发送数据,您可以使用GNAT.Sockets.Check_Selector阻止,直到其中一个客户端套接字有数据要读取,然后从该套接字读取。

    至于读取完整的输入消息,您可以一次读取一个字节,直到到达终结符(在HTTP请求的情况下,这将是双CR / LF)。当然,您需要同意客户方将构成终结者的内容。

    The answer from @ajb涵盖了写作。