1

私は次のコードを実行しています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で作成したサーバーと通信します。私の主な問題は、すべてのメッセージを確実に受信できないことです。時々私は得るでしょう

(<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()."それが重要な場合に備えて、私はこれを呼び出しています。

4

3 に答える 3

1

基本的な問題は、「net_client」を別のプロセスとして生成する必要があることだと思います。

startメソッドで、

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

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

それはそれを解決するはずです。

于 2010-11-16T18:02:35.430 に答える
1

また、トレース時には redbug (eper の一部) https://github.com/massemanet/eperを使用することをお勧めします。トレース出力でシステムが混乱するのを防ぎ、非常に単純な構文 (例: redbug:start("mymod:foo -> return", [{msgs,10}])) を提供します。mymod:foo へのすべての呼び出しと、それらの呼び出しが返すものをトレースしますが、10 個を超えるトレース メッセージは表示されません。

于 2010-11-16T21:31:27.923 に答える
1

{packet, 0}私の問題だったことが判明しました。それを置き換えると{packet, 2}、すべてがうまくいきます。

于 2010-11-17T22:51:44.460 に答える