Erlang 我应该/可以为TCP数据执行嵌套接收吗?

Erlang 我应该/可以为TCP数据执行嵌套接收吗?,erlang,Erlang,我可以嵌套接收{tcp,Socket,Bin}->调用吗?例如,我有一个名为loop的顶级循环,它在接收到tcp数据时调用parse_header函数来解析头数据(一个整数,它指示要遵循的数据类型及其大小),之后,我需要在继续之前接收整个负载。当我需要完整的20个字节时,我可能只接收4个字节,并且希望在一个名为parse_payload的单独函数中调用receive。因此,调用链看起来像循环->解析\u头->解析\u有效载荷,我希望解析\u有效载荷调用接收{tcp,Socket,Bin}->我不

我可以嵌套
接收{tcp,Socket,Bin}->
调用吗?例如,我有一个名为loop的顶级循环,它在接收到tcp数据时调用parse_header函数来解析头数据(一个整数,它指示要遵循的数据类型及其大小),之后,我需要在继续之前接收整个负载。

当我需要完整的20个字节时,我可能只接收4个字节,并且希望在一个名为parse_payload的单独函数中调用receive。因此,调用链看起来像
循环->解析\u头->解析\u有效载荷
,我希望解析\u有效载荷调用
接收{tcp,Socket,Bin}->


我不知道这是否正常,或者我是否会把事情搞砸,只能在循环函数中完成。有人能启发我吗?如果允许我这样做,是否违反了某种最佳实践?

也许您可以查看“erlang编程”的示例代码。 下载页面是

在文件socket_examples.erl中,请选中“接收数据”功能

对于perse消息,我认为您应该确定如何逐个分离消息(固定长度或带终止字节),然后解析消息头和负载

receive_data(Socket, SoFar) -> receive {tcp,Socket,Bin} -> %% (3) receive_data(Socket, [Bin|SoFar]); {tcp_closed,Socket} -> %% (4) list_to_binary(reverse(SoFar)) %% (5) end. 接收数据(插座、SoFar)-> 接收 {tcp,套接字,Bin}->%%(3) 接收|u数据(套接字,[Bin|SoFar]); {tcp_已关闭,套接字}->%%(4) 列表到二进制(反向(SoFar))%%(5) 结束。
也许您可以查看“erlang编程”的示例代码。 下载页面是

在文件socket_examples.erl中,请选中“接收数据”功能

对于perse消息,我认为您应该确定如何逐个分离消息(固定长度或带终止字节),然后解析消息头和负载

receive_data(Socket, SoFar) -> receive {tcp,Socket,Bin} -> %% (3) receive_data(Socket, [Bin|SoFar]); {tcp_closed,Socket} -> %% (4) list_to_binary(reverse(SoFar)) %% (5) end. 接收数据(插座、SoFar)-> 接收 {tcp,套接字,Bin}->%%(3) 接收|u数据(套接字,[Bin|SoFar]); {tcp_已关闭,套接字}->%%(4) 列表到二进制(反向(SoFar))%%(5) 结束。
您还可以将gen_tcp套接字设置为被动模式。这样,拥有进程将不会通过消息接收输入,但必须使用genu tcp:recv(Socket,ByteCount)获取它,它返回{ok,input}{error,Reason}。由于此方法无限等待字节,您可能希望使用gen_tcp:recv/3添加超时。()

乍一看,流程现在似乎完全无法对发送给它的消息做出反应,但有以下解决方法可以稍微改善这种情况:

f1(X) ->
    receive
        message1 ->
            ... do something ...,
            f1(X);
        message2 ->
            ... do something ...,
            f1(X)
        after 0 %timeout in ms
            {ok, Input} = gen_tcp:recv(Socket, ByteCount, Timeout),
            ... do something ... % maybe call some times gen_tcp:recv again
            f1(X)
    end.

如果您不在此处为gen_tcp:recv添加超时,其他进程可能会等待f1处理其消息。

您也可以将gen_tcp套接字设置为被动模式。这样,拥有进程将不会通过消息接收输入,但必须使用genu tcp:recv(Socket,ByteCount)获取它,它返回{ok,input}{error,Reason}。由于此方法无限等待字节,您可能希望使用gen_tcp:recv/3添加超时。()

乍一看,流程现在似乎完全无法对发送给它的消息做出反应,但有以下解决方法可以稍微改善这种情况:

f1(X) ->
    receive
        message1 ->
            ... do something ...,
            f1(X);
        message2 ->
            ... do something ...,
            f1(X)
        after 0 %timeout in ms
            {ok, Input} = gen_tcp:recv(Socket, ByteCount, Timeout),
            ... do something ... % maybe call some times gen_tcp:recv again
            f1(X)
    end.
如果不在此处为gen_tcp:recv添加超时,其他进程可能会等待f1处理其消息