1

私は本 Programming Erlang を読んでいて、253 ページにクライアント/サーバー接続を実行する例があります。以下のコードは、次のエラーが表示される 2 つの個別の erlang コンソール ウィンドウで次のコマンドを実行することを提案しています。

2> socket_examples:nano_client_eval("list_to_tuple([2+3*4,10+20])").
** exception error: no match of right hand side value {error,econnrefused}
     in function  socket_examples:nano_client_eval/1 (socket_examples.erl, line 28)

サーバー側のコマンド: socket_examples:start_nano_server().

クライアント側のコマンド: socket_examples:nano_client_eval("list_to_tuple([2+3*4,10+20])").

ファイアウォールをオンにしていませんが、オンラインではないため問題にはなりません。

    %% ---
%%  Excerpted from "Programming Erlang",   
%%---
-module(socket_examples).
-compile(export_all).
-import(lists, [reverse/1]).


nano_get_url() ->
    nano_get_url("www.google.com").

nano_get_url(Host) ->
    {ok,Socket} = gen_tcp:connect(Host,80,[binary, {packet, 0}]), %% (1)
    ok = gen_tcp:send(Socket, "GET / HTTP/1.0\r\n\r\n"),  %% (2)
    receive_data(Socket, []).

receive_data(Socket, SoFar) ->
    receive
    {tcp,Socket,Bin} ->    %% (3)
        receive_data(Socket, [Bin|SoFar]);
    {tcp_closed,Socket} -> %% (4)
        list_to_binary(reverse(SoFar)) %% (5)
    end.



nano_client_eval(Str) ->
    {ok, Socket} = 
    gen_tcp:connect("localhost", 2345,
            [binary, {packet, 4}]),
    ok = gen_tcp:send(Socket, term_to_binary(Str)),
    receive
    {tcp,Socket,Bin} ->
        io:format("Client received binary = ~p~n",[Bin]),
        Val = binary_to_term(Bin),
        io:format("Client result = ~p~n",[Val]),
        gen_tcp:close(Socket)
    end.



start_nano_server() ->
    {ok, Listen} = gen_tcp:listen(2345, [binary, {packet, 4},  %% (6)
                     {reuseaddr, true},
                     {active, true}]),
    {ok, Socket} = gen_tcp:accept(Listen),  %% (7)
    gen_tcp:close(Listen),  %% (8)
    loop(Socket).

loop(Socket) ->
    receive
    {tcp, Socket, Bin} ->
        io:format("Server received binary = ~p~n",[Bin]),
        Str = binary_to_term(Bin),  %% (9)
        io:format("Server (unpacked)  ~p~n",[Str]),
        Reply = lib_misc:string2value(Str),  %% (10)
        io:format("Server replying = ~p~n",[Reply]),
        gen_tcp:send(Socket, term_to_binary(Reply)),  %% (11)
        loop(Socket);
    {tcp_closed, Socket} ->
        io:format("Server socket closed~n")
    end.



error_test() ->
    spawn(fun() -> error_test_server() end),
    lib_misc:sleep(2000),
    {ok,Socket} = gen_tcp:connect("localhost",4321,[binary, {packet, 2}]),
    io:format("connected to:~p~n",[Socket]),
    gen_tcp:send(Socket, <<"123">>),
    receive
    Any ->
        io:format("Any=~p~n",[Any])
    end.

error_test_server() ->
    {ok, Listen} = gen_tcp:listen(4321, [binary,{packet,2}]),
    {ok, Socket} = gen_tcp:accept(Listen),
    error_test_server_loop(Socket).

error_test_server_loop(Socket) ->
    receive
    {tcp, Socket, Data} ->
        io:format("received:~p~n",[Data]),
        atom_to_list(Data),
        error_test_server_loop(Socket)
    end.
4

1 に答える 1

1

受け取ったメッセージ ({error,econnrefused}) は、サーバーがダウンしていることを示しています。

Muzaaya が言ったように、{packet,N} はシステム内で一貫している必要があります。そうでない場合、サーバーは binary_to_term 変換に失敗してクラッシュします (詳しくは調べていませんが、これは情報の転送方法に関連していると思います)。

次のリクエストは、接続拒否メッセージを受け取ります。

Muzaaya によって提案された変更により、サーバーは binary_to_term を実行でき、投稿に含まれていない b_misc:string2value... への呼び出しまですべてが機能します。

私は奇妙なことに気づきます:

  • spawn(socket_examples,start_nano_server,[]) を使用してサーバーを起動しました。
  • 未定義のモジュールへの呼び出しでサーバーがクラッシュします --> 通常の動作。
  • しかし、シェルがハングし、新しいコマンドを入力できません。

何が起こっているのか理解できません。

編集:

Muzaaya さん、クライアント コードを確認するのを忘れていました。

変更したコードをここに投稿します。パケット定義に加えて、サーバーとクライアントにいくつかの変更を加えました。ドキュメンテーションを深く見ていないと言わざるを得ませんが、元のコードには、開く、閉じる、受け入れるという問題があったようです。ここのコードが正しいかどうかはわかりません。また、ソケットを適切に閉じるために何かが欠けていることもわかっています。何よりも、このコードは複数のリクエストを並行して処理していません。

 -module(socket_examples).
-compile(export_all).
-import(lists, [reverse/1]).


nano_get_url() ->
    nano_get_url("www.google.com").

nano_get_url(Host) ->
    {ok,Socket} = gen_tcp:connect(Host,80,[binary, {packet, 0}]), %% (1)
    ok = gen_tcp:send(Socket, "GET / HTTP/1.0\r\n\r\n"),  %% (2)
    receive_data(Socket, []).

receive_data(Socket, SoFar) ->
    receive
    {tcp,Socket,Bin} ->    %% (3)
        receive_data(Socket, [Bin|SoFar]);
    {tcp_closed,Socket} -> %% (4)
        list_to_binary(reverse(SoFar)) %% (5)
    end.



nano_client_eval(Str) ->
    {ok, Socket} = 
    gen_tcp:connect("localhost", 2345,
            [binary, {packet, 0}]),
    ok = gen_tcp:send(Socket, term_to_binary(Str)),
    R = receive
        {tcp,Socket,Bin} ->
            io:format("Client received binary = ~p~n",[Bin]),
            Val = binary_to_term(Bin),
            io:format("Client result = ~p~n",[Val]),
            {ok,Val}
        after 5000 ->
            io:format("nano_client_eval got not answer to ~p~n",[Str]),
            {error,timeout}
    end,
%   gen_tcp:close(Socket),
    R.



start_nano_server() ->
    {ok, Listen} = gen_tcp:listen(2345, [binary, {packet, 0},  %% (6)
                     {reuseaddr, true},
                     {active, true}]),
 %   {ok, Socket} = gen_tcp:accept(Listen),  %% (7)
 %   gen_tcp:close(Listen),  %% (8)
%    loop(Socket).
    loop(Listen).

% loop(Socket) ->
loop(Listen) ->
    {ok, Socket} = gen_tcp:accept(Listen),
    receive
    {tcp, Socket, Bin} ->
        io:format("Server received binary = ~p~n",[Bin]),
        Str = binary_to_term(Bin),  %% (9)
        io:format("Server (unpacked)  ~p~n",[Str]),
%        Reply = lib_misc:string2value(Str),  %% (10)
        Reply = string:to_upper(Str),  %% (10)
        io:format("Server replying = ~p~n",[Reply]),
        gen_tcp:send(Socket, term_to_binary(Reply)),  %% (11)
%        loop(Socket);
        loop(Listen);
    {tcp_closed, Socket} ->
        io:format("Server socket closed~n")
    end.



error_test() ->
    spawn(fun() -> error_test_server() end),
    lib_misc:sleep(2000),
    {ok,Socket} = gen_tcp:connect("localhost",4321,[binary, {packet, 0}]),
    io:format("connected to:~p~n",[Socket]),
    gen_tcp:send(Socket, <<"123">>),
    receive
    Any ->
        io:format("Any=~p~n",[Any])
    end.

error_test_server() ->
    {ok, Listen} = gen_tcp:listen(4321, [binary,{packet,0}]),
    {ok, Socket} = gen_tcp:accept(Listen),
    error_test_server_loop(Socket).

error_test_server_loop(Socket) ->
    receive
    {tcp, Socket, Data} ->
        io:format("received:~p~n",[Data]),
        atom_to_list(Data),
        error_test_server_loop(Socket)
    end.
于 2013-02-11T10:44:10.363 に答える