Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何处理Erlang中TCP流中数据包的错误长度报头?_Tcp_Erlang_Gen Tcp - Fatal编程技术网

如何处理Erlang中TCP流中数据包的错误长度报头?

如何处理Erlang中TCP流中数据包的错误长度报头?,tcp,erlang,gen-tcp,Tcp,Erlang,Gen Tcp,我使用gen\u TCP在Erlang中通过TCP接收消息。流通过使用一个4字节长的报头(由{packet,4}选项指定)划分为数据包。这就是我如何调用gen_tcp:listen/2的方法: gen_tcp:listen(Port, [binary, inet, {active, once}, {packet, 4}]). 如您所见,我使用了{active,once}选项,这样我就可以从进程邮箱中获取数据包,而不会使其泛滥。只要长度标题正确,这就可以正常工作。如果不是,任何事情都可能发生。所

我使用
gen\u TCP
在Erlang中通过TCP接收消息。流通过使用一个4字节长的报头(由
{packet,4}
选项指定)划分为数据包。这就是我如何调用gen_tcp:listen/2的方法:

gen_tcp:listen(Port, [binary, inet, {active, once}, {packet, 4}]).
如您所见,我使用了
{active,once}
选项,这样我就可以从进程邮箱中获取数据包,而不会使其泛滥。只要长度标题正确,这就可以正常工作。如果不是,任何事情都可能发生。所以我想以某种方式处理错误数据包的可能性

这有点棘手,因为我实际上是在处理流。忽略错误的数据包是可以的,但如何让Erlang跳过这些数据包并识别以下数据包呢?这个问题通常是如何处理的

使用分隔符更好吗?我已经研究了
gen\u tcp
的一些其他
packet
选项。特别是:

asn1 | cdr | sunrm | fcgi | tpkt | line

我唯一真正理解的是
line
,但我认为这不是一个好的选择。我希望接收用我不熟悉的Objective C发送和构造的包,它包含许多不同类型的数据,而不仅仅是字符串。

我认为在使用{packet,N}时不能跳过“坏”包

主要原因是,什么是坏包

任何4个字节都可以表示大小,因此如果有人发送: 你好\n

你实际上得到: 0x48656c6c 作为大小标头,指示帧的长度为:1214606444字节 后跟“o\n” 然后你就被绞死了

您可以设置{packet_size,1024}(或其他任何设置),以防止在“hello”上分配1.2gb

不确定这是否返回错误或删除套接字

在TCP中,由于消息在传输过程中被任意分割,所以实际上没有办法从坏帧恢复

如果你不使用{packet,N},那么你就必须做你自己的分段控制,比如说你得到几行文本,你需要知道消息何时结束

如果您控制客户机/服务器协议,您可能希望使用{packet,http}或更完善的we解决方案,如

然后让客户端提交http请求(主体仍然可以是二进制的),framwork为您处理格式错误的请求


如果您需要一个双向通道,websocket可能仍然可以(假设您在目标c中有一个websocket库)

我认为在使用{packet,N}时不能跳过“坏”数据包

主要原因是,什么是坏包

任何4个字节都可以表示大小,因此如果有人发送: 你好\n

你实际上得到: 0x48656c6c 作为大小标头,指示帧的长度为:1214606444字节 后跟“o\n” 然后你就被绞死了

您可以设置{packet_size,1024}(或其他任何设置),以防止在“hello”上分配1.2gb

不确定这是否返回错误或删除套接字

在TCP中,由于消息在传输过程中被任意分割,所以实际上没有办法从坏帧恢复

如果你不使用{packet,N},那么你就必须做你自己的分段控制,比如说你得到几行文本,你需要知道消息何时结束

如果您控制客户机/服务器协议,您可能希望使用{packet,http}或更完善的we解决方案,如

然后让客户端提交http请求(主体仍然可以是二进制的),framwork为您处理格式错误的请求


如果您需要双向频道,websocket可能仍然可以(假设您在目标c中有一个websocket库)

谢谢您的回复,David。我认为我将坚持使用长度帧,并依赖于正确实现的协议。我在考虑一种解决方案,在
receive
子句中,套接字的缓冲区在一段时间后被刷新,这表明没有收到任何数据包或者缓冲区中的下一个数据包是错误的,并让客户端重新发送消息。不过,我还没有找到一种在活动模式下刷新套接字缓冲区的方法。我试着切换到
被动
模式并调用
recv/2
,希望它能奏效。没有。(为什么?)。。如果您自己实现了框架,那么在套接字读取时总是可以超时。不过刷新缓冲区从来都不是一个好的选择。。。假设您的超时时间为5秒,您的客户端发送3000字节。您的MTU可能是1500字节,因此您得到两个1500字节的数据包。但如果另一端挂起呢。假设它位于实时迁移的VMWare节点上,或者您有某种GC暂停之类的情况。你将刷新前1500个字节,只会得到另一个1500字节的坏数据包。谢谢你的回复,大卫。我认为我将坚持使用长度帧,并依赖于正确实现的协议。我在考虑一种解决方案,在
receive
子句中,套接字的缓冲区在一段时间后被刷新,这表明没有收到任何数据包或者缓冲区中的下一个数据包是错误的,并让客户端重新发送消息。不过,我还没有找到一种在活动模式下刷新套接字缓冲区的方法。我试着切换到
被动
模式并调用
recv/2
,希望它能奏效。没有。(为什么?)。。如果您自己实现了框架,那么在套接字读取时总是可以超时。不过刷新缓冲区从来都不是一个好的选择。。。假设您的超时时间为5秒,您的客户端发送3000字节。您的MTU可能是1500字节,因此您得到两个1500字节的数据包。但如果另一端挂起呢。假设它位于实时迁移的VMWare节点上,或者您有某种GC暂停之类的情况。您将刷新前1500个字节,只会得到另一个1500字节的坏数据包。