erlang:如何从套接字接收 HTTP/RTSP 消息?

Nic*_*Saw 3 erlang http erlang-otp rtsp gen-tcp

我想用 Erlang 管理 HTTP 或 RTSP 会话。

例如,RTSP 协议的标准会话如下所示:

OPTIONS rtsp://192.168.1.55/test/ RTSP/1.0\r\n
CSeq: 1\r\n
User-Agent: VLC media player (LIVE555 Streaming Media v2008.07.24)\r\n
...
PLAY rtsp://192.168.1.55/test/ RTSP/1.0\r\n
CSeq: 5\r\n
Session: 1\r\n
Range: npt=0.000-\r\n
User-Agent: VLC media player (LIVE555 Streaming Media v2008.07.24)\r\n
Run Code Online (Sandbox Code Playgroud)

每条消息的长度是不同的。对于 erlang,gen_server:listen使用一个选项{active, true}(允许获取无限数量的数据)或{active, false}(获取固定长度的数据)。

是否有推荐的方法来获取和解析此类长度可变的消息?

Ste*_*ski 5

对于 HTTP,使用为该inet:setopts/2函数记录的 HTTP 数据包模式之一。例如,要将套接字设置为以二进制形式接收 HTTP 消息,您可以{packet, http_bin}在套接字上设置。查看我的简单 Web 服务器示例,了解如何使用 HTTP 数据包模式。

对于 RTSP,没有内置的数据包解析器,但是因为 RTSP 标头像 HTTP 一样面向行,所以您可以使用该{packet, line}模式进行自己的标头解析。在这种模式下,您将一次收到一个标题,直到您收到一个指示标题结尾的空行。然后,您可以将套接字更改为{packet, raw}模式以接收任何消息正文。所述Content-Length标头(如果存在)表示的任何消息体的大小。

您提到的{active, true}vs{active, false}套接字模式控制数据如何到达套接字的控制进程(所有者)。

  • {active, true}模式将所有数据从套接字发送到控制进程,一旦它们到达。在这种模式下,数据作为消息到达所有者的消息队列。在进程消息队列上接收消息很棒,因为它允许进程在处理套接字数据的同时也处理其他非套接字相关的 Erlang 消息,但{active, true}不经常使用,因为它不向发送方提供 TCP 背压,并且所以一个快速的发送者可以超越接收者。
  • {active, false}模式要求接收方调用gen_tcp:recv/2,3套接字以检索数据。这没有背压问题,{active, true}但它会使消息处理变得笨拙,因为 Erlang 进程必须主动请求套接字数据,而不是receive像其他active模式那样只是坐在一个循环中。
  • active您没有提到的另外两种模式是{active, once}{active, N}。在{active, once}模式下,接收进程一次通过其消息队列获取一条消息,套接字{active, false}在每条消息后进入被动模式。要获得另一条消息,接收方必须{active, once}在准备好接收下一条消息时再次设置套接字。这种模式很好,因为消息到达进程消息队列与{active, true}模式相同,但背压仍然有效。{active, N}除了N在套接字恢复到被动模式之前接收消息而不是仅接收消息之外,该模式是相似的。