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

Posted

技术标签:

【中文标题】erlang:如何从套接字接收 HTTP/RTSP 消息?【英文标题】:erlang: how to receive HTTP/RTSP messages from socket? 【发布时间】:2019-08-27 07:40:23 【问题描述】:

我想用 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

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

有没有推荐的方法来获取和解析这些可变长度的消息?

【问题讨论】:

【参考方案1】:

对于 HTTP,请使用为 inet:setopts/2 函数记录的一种 HTTP 数据包模式。例如,要将套接字设置为以二进制形式接收 HTTP 消息,您可以在套接字上设置packet, http_bin。看看我的simple web server example,看看如何使用 HTTP 数据包模式。

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

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

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

【讨论】:

史蒂夫,非常感谢您的回答!您的示例对于更好地理解非常有用。对于 RTSP,我认为将 packet, line 直到“Content-Length”行,然后通过 packet, raw 以 Content-Length 中描述的固定长度获取数据包是个好主意。非常感谢!每次都对 Erlang 社区的团结深信不疑

以上是关于erlang:如何从套接字接收 HTTP/RTSP 消息?的主要内容,如果未能解决你的问题,请参考以下文章

Erlang:连接到服务器,并在同一个套接字上接收输入

Erlang 套接字直到第二个 setopts active,once 才接收

将erlang套接字存储到数据库

Erlang gen_tcp:listen/2 for IPv6

在 erlang 中轮询接收块是一种好的做法吗?

如何从套接字连续接收数据?