基本上,我设法将多个客户端连接到一台服务器,但是从服务器读取时遇到问题。我有两个任务(线程):一个用于阅读,一个用于写作。
"Incoming > "
?String'Write
的快捷方式ada.streams.write
。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;
答案 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
时,它会从套接字读取,直到
在案例2中,Read
调用将阻塞,直到有更多数据到达。只有在第3种情况下,您才能获得一个不足的缓冲区(在您的代码中,Offset
小于Buffer’Last
)。
如果您有多个客户端,其中任何一个都可以发送数据,您可以使用GNAT.Sockets.Check_Selector
阻止,直到其中一个客户端套接字有数据要读取,然后从该套接字读取。
至于读取完整的输入消息,您可以一次读取一个字节,直到到达终结符(在HTTP请求的情况下,这将是双CR / LF)。当然,您需要同意客户方将构成终结者的内容。
The answer from @ajb涵盖了写作。