【问题标题】:receive specific amount of data from gen_tcp socket从 gen_tcp 套接字接收特定数量的数据
【发布时间】:2012-08-21 19:08:28
【问题描述】:

我有以下代码使用 gen_tcp 套接字,它应该使用 {active, true} 接收一些总是大小为 5 的二进制命令(例如 Command = <<"hello">>

{ok, ListenSocket} = gen_tcp:listen(5555,  [{active, true}, {mode, binary}, 
                                            {packet, 0}]),
{ok, Socket} = gen_tcp:accept(ListenSocket),    
loop().

receive() ->
    {tcp, _Socket, Message:4/binary} ->
         io:format("Success~n", []),
         loop();
    {tcp, _Socket, Other} ->
         io:format("Received: ~p~n", [Other]),
         loop()
end.

但如果我尝试像这样作为客户端连接:

1> {ok, S} = gen_tcp:connect("localhost", 5555, []).
   {ok,#Port<0.582>}
2> gen_tcp:send(S, <<"hello">>).
ok

我在接收部分:

Received: {tcp,#Port<0.585>,<<"hello">>}

所以我想我的错误是在模式匹配中......但是在哪里?

【问题讨论】:

  • 您在发送&lt;&lt;"hello"&gt;&gt; 时收到&lt;&lt;"ciao"&gt;&gt; 吗?
  • 操作,不...现在将在问题中解决它

标签: erlang gen-tcp


【解决方案1】:

您的receive 子句看起来不对,应该是:

{tcp, _Socket, <<Message:5/binary>>} ->
  ....

【讨论】:

  • 对于未来,如果我更改为 ssl,> 还会好吗?只是问:)
  • 协议原子将是ssl 而不是tcp,除此之外你应该没问题
  • 此代码将工作在 99%。但正如您所知,TCP 是流协议,它不能保证您的命令不会被拆分为两个或多个数据包,或者不会与之前的命令合并。
【解决方案2】:

据我了解,您需要gen_tcp:recv 功能。来自文档:

recv(Socket, Length) -> {ok, Packet} | {error, Reason}

在您的代码中,它将类似于:

...
{ok, Socket} = gen_tcp:accept(ListenSocket),
loop(Socket).

loop(Socket) -> 
    case gen_tcp:recv(Socket, 5) of
        {ok, Data} ->
            io:format("Success~n", []),
            loop(Socket);
        {error, closed} -> 
            ok
end.

【讨论】:

  • 是的,我知道那个选项,但是不能使用标准接收代替吗?我宁愿以这种方式处理它。
  • receive 不是从 TCP 套接字接收数据的标准方式(这是用于处理 spawned 进程的通用接口)。您将获得什么好处?
  • AFAIK gen_tcp:recv/2 被阻塞。此外,在未来的实现中,我将在 gen_server 行为的 handle_info 中处理 {active, once} 的数据包
  • 为什么阻塞是个问题?只需将loop(Socket) 替换为spawn(fun() -&gt; loop(Socket) end)
猜你喜欢
  • 2012-12-28
  • 1970-01-01
  • 2014-06-26
  • 2016-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-22
  • 2016-07-30
相关资源
最近更新 更多