Erlang gen_tcp丢失数据包?

Erlang gen_tcp丢失数据包?,tcp,erlang,imap,pop3,Tcp,Erlang,Imap,Pop3,我正在为Erlang开发一个邮件客户端适配器。我在尝试执行fetch命令时遇到问题,Erlang无法获取正文内容 当我试图通过netcat使用命令时,这是终端的输出: 4 FETCH 2 BODY[2] * 2 FETCH (BODY[2] {1135} <div> test content </div> ) 4 OK FETCH comple

我正在为Erlang开发一个邮件客户端适配器。我在尝试执行fetch命令时遇到问题,Erlang无法获取正文内容

当我试图通过netcat使用命令时,这是终端的输出:

4 FETCH 2 BODY[2]
* 2 FETCH (BODY[2] {1135}

                <div>
                    test content
                </div>
            )
4 OK FETCH completed.

非常感谢您的帮助。

如果您处于
活动
模式,最好的方法是使用模式
{tcp,Socket,Msg}在
句柄信息
(或自定义接收函数)中接收流
并将其存储在缓冲区中,直到它满足特定的模式匹配或具有特定的长度,然后根据需要刷新缓冲区

正如@rvirding所说,您无法确定所有消息都将在单个数据包中接收,因此您必须处理可能的多个数据包。否则,您必须使用
被动
模式和功能
gen_tcp:recv/2
,但请记住此功能是阻塞的


我建议您阅读以下内容:

以下内容仅是对您的问题的评论,而不是对您的问题的回答,我相信Rbirding会提供上述内容

由于您使用的是一种标准行为(gen_server),因此可以假定您打算编写符合OTP的应用程序。如果是这样的话,除非您准备好处理所有可能的系统消息以及应用程序的消息,否则永远不要直接使用接收表达式。对于gen_服务器或gen_fsm,非系统消息由handle_info/2回调函数处理。您可以使用State变量来保存您正在处理的命令的指示符(例如login),并为每个命令设置一个单独的子句:

 handle_info({tcp,Socket,Reply}, #state{pending = login} = State) ->
 ...;
 handle_info({tcp,Socket,Reply}, #state{pending = list} = State) ->
 ...;
。。。然而,这将成为穷人的有限状态机,因此您最好将其移植到gen_fsm行为回调模块,在该模块中,每个模块都有一个单独的状态(即等待登录)。然后您可以使用handle_info/3:

 handle_info({tcp,Socket,Reply}, wait_for_login, State) ->
 ...;
 handle_info({tcp,Socket,Reply}, wait_for_list, State) ->
 ...;

TCP是一种流协议,因此不能保证您可以一次性收到整个消息,即使它是以这种方式发送的。由接收端为整个消息收集“足够”的字节。在您的情况下,您只需等待一条消息。为了在
listener/2
中安全起见,我将使用
{TCP,Socket,Reply}
模式匹配TCP消息,这样更明确、更安全。
 handle_info({tcp,Socket,Reply}, #state{pending = login} = State) ->
 ...;
 handle_info({tcp,Socket,Reply}, #state{pending = list} = State) ->
 ...;
 handle_info({tcp,Socket,Reply}, wait_for_login, State) ->
 ...;
 handle_info({tcp,Socket,Reply}, wait_for_list, State) ->
 ...;