erlang:如何从套接字接收 HTTP/RTSP 消息?
erlang: how to receive HTTP/RTSP messages from socket?
我想用 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}
(获取固定长度的数据)。
是否有推荐的方法来获取和解析这种可变长度的消息?
对于 HTTP,使用为 inet:setopts/2
function. For example, to set a socket to receive HTTP messages as binaries, you can set the {packet, http_bin}
on the socket. Have a look at my simple web server example 记录的 HTTP 数据包模式之一,以查看如何使用 HTTP 数据包模式。
对于 RTSP,没有 built-in 数据包解析器,但是因为 RTSP header 与 HTTP 类似 line-oriented,您可以使用 header 进行自己的解析 {packet, line}
模式。在该模式下,您将一次收到一个 header,直到您收到一个表示 header 结束的空行。然后,您可以将套接字更改为 {packet, raw}
模式以接收任何消息 body。 Content-Length
header(如果存在)表示任何消息的大小 body。
您提到的 {active, true}
与 {active, false}
套接字模式控制数据如何到达套接字的控制进程(所有者)。
{active, true}
模式将所有数据一到达就从套接字发送到控制进程。在这种模式下,数据作为所有者消息 queue 上的消息到达。在进程消息 queue 上接收消息很棒,因为它允许进程在处理套接字数据的同时也处理其他 non-socket-related Erlang 消息,但是 {active, true}
不经常使用,因为它不提供TCP back-pressure 到发送方,因此快速发送方可以超过接收方。
{active, false}
模式要求接收方在套接字上调用gen_tcp:recv/2,3
来检索数据。这没有 {active, true}
的 back-pressure 问题,但它会使消息处理变得笨拙,因为 Erlang 进程必须主动请求套接字数据,而不是仅仅坐在 receive
循环中可以使用其他 active
模式。
- 您没有提到的另外两个
active
模式是 {active, once}
和 {active, N}
。在 {active, once}
模式下,接收进程一次通过其消息 queue 获取一条消息,套接字在每条消息后移动到被动 {active, false}
模式。要获取另一条消息,接收方必须在准备好接收下一条消息时再次在套接字上设置 {active, once}
。这种模式很好,因为消息到达进程消息 queue 与 {active, true}
模式相同,但 back-pressure 仍然有效。 {active, N}
模式类似,只是在套接字恢复到被动模式之前收到 N
条消息,而不是一条消息。
我想用 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}
(获取固定长度的数据)。
是否有推荐的方法来获取和解析这种可变长度的消息?
对于 HTTP,使用为 inet:setopts/2
function. For example, to set a socket to receive HTTP messages as binaries, you can set the {packet, http_bin}
on the socket. Have a look at my simple web server example 记录的 HTTP 数据包模式之一,以查看如何使用 HTTP 数据包模式。
对于 RTSP,没有 built-in 数据包解析器,但是因为 RTSP header 与 HTTP 类似 line-oriented,您可以使用 header 进行自己的解析 {packet, line}
模式。在该模式下,您将一次收到一个 header,直到您收到一个表示 header 结束的空行。然后,您可以将套接字更改为 {packet, raw}
模式以接收任何消息 body。 Content-Length
header(如果存在)表示任何消息的大小 body。
您提到的 {active, true}
与 {active, false}
套接字模式控制数据如何到达套接字的控制进程(所有者)。
{active, true}
模式将所有数据一到达就从套接字发送到控制进程。在这种模式下,数据作为所有者消息 queue 上的消息到达。在进程消息 queue 上接收消息很棒,因为它允许进程在处理套接字数据的同时也处理其他 non-socket-related Erlang 消息,但是{active, true}
不经常使用,因为它不提供TCP back-pressure 到发送方,因此快速发送方可以超过接收方。{active, false}
模式要求接收方在套接字上调用gen_tcp:recv/2,3
来检索数据。这没有{active, true}
的 back-pressure 问题,但它会使消息处理变得笨拙,因为 Erlang 进程必须主动请求套接字数据,而不是仅仅坐在receive
循环中可以使用其他active
模式。- 您没有提到的另外两个
active
模式是{active, once}
和{active, N}
。在{active, once}
模式下,接收进程一次通过其消息 queue 获取一条消息,套接字在每条消息后移动到被动{active, false}
模式。要获取另一条消息,接收方必须在准备好接收下一条消息时再次在套接字上设置{active, once}
。这种模式很好,因为消息到达进程消息 queue 与{active, true}
模式相同,但 back-pressure 仍然有效。{active, N}
模式类似,只是在套接字恢复到被动模式之前收到N
条消息,而不是一条消息。