代码之家  ›  专栏  ›  技术社区  ›  nmichaels

Erlang缺少消息

  •  1
  • nmichaels  · 技术社区  · 14 年前

    我正在运行以下代码 dbg:p(client, r) :

    -module(client).
    -export([start/0, start/2, send/1, net_client/1]).
    
    start() ->
        start("localhost", 7000).
    
    start(Host, Port) ->
        io:format("Client connecting to ~p:~p.~n", [Host, Port]),
        register(ui, spawn(fun() -> gui_control([]) end)),
        case gen_tcp:connect(Host, Port, [binary, {packet, 0}]) of
            {ok, Socket} ->
                Pid = spawn(client, net_client, [Socket]),
                register(client, Pid),
                gen_tcp:controlling_process(Socket, Pid);
            Error ->
                io:format("Error connecting to server: ~p~n", [Error]),
                erlang:error("Could not connect to server.")
        end,
        ok.
    
    send(Msg) ->
        client!{send, Msg}.
    
    
    %% Forwards messages to either the GUI controller or the server.
    net_client(Socket) ->
        receive
            {tcp, Socket, Message} ->
                Msg = binary_to_term(Message),
                io:format("Received TCP message on ~p: ~p~n", [Socket, Msg]),
                ui!{server, Msg};
            {send, Message} ->
                io:format("Sending ~p.~n", [Message]),
                gen_tcp:send(Socket, term_to_binary(Message));
            close ->
                gen_tcp:close(Socket),
                exit(normal);
            {tcp_closed, Socket} ->
                io:format("Server terminated connection.~n"),
                exit(normal); %% Reconnect?
            timeout -> %% This
                io:format("Timed out?~n");
            {inet_reply, Socket, Message} -> %% and this never happen.
                io:format("inet_reply: ~p~n", Message);
            Error ->
                io:format("Net client got bad message: ~p.~n", [Error])
        after 10000 ->
                refresh %% gen_tcp:send(Socket, term_to_binary(keepalive))
        end,
        ?MODULE:net_client(Socket).
    
    
    gui_control(Data) ->
        receive
            %% This will hang the gui until the sync is done. Not sure if
            %% that's okay.
            {server, {sync, Datum}} -> % Resync command from server.
                gui_control(resync([Datum]));
            {client, refresh} -> % Refresh request from display.
                display:update(Data);
            {server, Msg} ->
                io:format("UI Rx: ~p~n", [Msg])
        end,
        gui_control(Data).
    
    resync(Data) ->
        receive
            {server, {sync, Datum}} ->
                resync([Datum|Data]);
            {server, {done, Num}} ->
                case length(Data) of
                    Num ->
                        Data;
                    _ ->
                        io:format("Got done before all the data were received.~n"),
                        send({sync})
                end
        after 5000 ->
                io:format("Timed out waiting for data.~n"),
                send({sync})
        end.
    

    它与我用gen_tcp和gen_server编写的服务器通信,如下所示 this . 我的主要问题是我不能可靠地接收所有的信息。有时我会得到

    (<0.2.0>) << {tcp,#Port<0.517>,
                      <<131,104,6,100,0,4,99,97,114,100,100,0,7,117,110,107,110,
                        111,119,110,100,0,7,117,110,107,110,111,119,110,106,106,
                        104,3,107,0,6,83,101,99,111,110,100,100,0,4,100,114,97,
                        119,97,2,131,104,6,100,0,4,99,97,114,100,100,0,7,117,110,
                        107,110,111,119,110,100,0,7,117,110,107,110,111,119,110,
                        106,106,104,3,107,0,6,83,101,99,111,110,100,100,0,4,100,
                        114,97,119,97,3,131,104,6,100,0,4,99,97,114,100,100,0,7,
                        117,110,107,110,111,119,110,100,0,7,117,110,107,110,111,
                        119,110,106,106,104,3,107,0,5,70,105,114,115,116,100,0,4,
                        100,114,97,119,97,0>>}
    

    从调试输出,但没有相应的 Received TCP message on #Port<0.517>:... 信息。我也会看到这样的事情:

    (<0.2.0>) << {io_reply,<0.24.0>,ok}
    (<0.2.0>) << timeout
    (<0.2.0>) << {io_reply,<0.24.0>,ok}
    (<0.2.0>) << timeout
    (<0.2.0>) << {io_reply,<0.24.0>,ok}
    

    但是什么都没有 net_client 的接收。我观察过wireshark的网络流量,我知道数据包正在到达它们应该去的地方 ACK 我做错什么了?

    编辑: 我调用这个 erl -smp enable -eval "client:start()." 以防万一。

    3 回复  |  直到 14 年前
        1
  •  1
  •   arun_suresh    14 年前

    我想最基本的问题是“net_客户端”应该作为一个单独的进程派生出来。。

    在开始方法中,更改

    register(client, self()),
    net_client(Socket);
    

    register(client, fun() -> net_client(Socket) end);
    

    这应该能解决问题。。

        2
  •  1
  •   etnt    14 年前

    另外,我建议使用redbug(eper的一部分) https://github.com/massemanet/eper 追踪的时候。它保护您的系统不被跟踪输出淹没,并提供了一个死板的简单语法,例如:redbug:start(“mymod:foo->return”,[{msgs,10}])。跟踪对mymod:foo的所有调用以及这些调用返回的内容,但最多只能提供10条跟踪消息。

        3
  •  1
  •   nmichaels    14 年前

    结果是 {packet, 0} 是我的问题。换成 {packet, 2} 一切都很好。

    推荐文章