0

I decided to modify the code in this thread by changing the server to a parallel one (as mentioned in the book) and it doesn't work properly. The following code is supposed to be presto-chango according to the book "Programming Erlang" but I get an error on line 17. Here is the parallel server code (the completed parallel server is on the bottom, this is just the change to the old server code on the last thread),

startp() ->
    {ok, Listen} = gen_tcp:listen(4042, [binary, {packet, 0},  
                     {reuseaddr, true},
                     {active, true}]),                       
                     spawn(fun() -> par_connect(Listen) end).

par_connect(Listen) ->      
        {ok, Socket} = gen_tcp:accept(Listen),
        spawn(fun() -> par_connect(Listen) end),
        loop(Socket).

and this is the error,

=ERROR REPORT==== 12-Feb-2013::23:05:13 ===
Error in process <0.35.0> with exit value: {{badmatch,{error,einval}},[{ps1,loop,1,[{file,"ps1.erl"},{line,17}]}]}

The following is the parallel server code, I'm thinking that something is wrong with the argument on line 14 for the call loop(Socket). Maybe its something else, I dunno?

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

startp() ->
    {ok, Listen} = gen_tcp:listen(4042, [binary, {packet, 0},  
                     {reuseaddr, true},
                     {active, true}]),                       
                     spawn(fun() -> par_connect(Listen) end).

par_connect(Listen) ->      
        {ok, Socket} = gen_tcp:accept(Listen),
        spawn(fun() -> par_connect(Listen) end),
        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), 
        io:format("Server (unpacked)  ~p~n",[Str]),
        Reply = string:to_upper(Str),  
        io:format("Server replying = ~p~n",[Reply]),
        gen_tcp:send(Socket, term_to_binary(Reply)),  
        loop(Listen);
    {tcp_closed, Socket} ->
        io:format("Server socket closed~n")
    end.

next is the client code which also ends up dieing waiting for a reply

c1:nano("list_to_tuple([2+3*4,10+20])").
nano got not answer to "list_to_tuple([2+3*4,10+20])"
{error,timeout}

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

%old port 2345
nano(Str) ->
    {ok, Socket} = 
    gen_tcp:connect("localhost", 4042,
            [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 got no answer to ~p~n",[Str]),
            {error,timeout}
    end,
%   gen_tcp:close(Socket),
    R.
4

1 に答える 1

2

ドキュメントによると、表示されるエラーの説明は少し奇妙です。

einval

Attempt to delete the current directory. On some platforms, eacces is returned instead.

私はそれがあまり役に立たないと言わなければなりません。

{ok, Socket} = gen_tcp:accept(Listen)とにかく、ループでリコールする必要はありませんが、ですでに実行されていpar_connect(Listen)ます。ただし、この場合、ループの引数はListenではなくSocketになります。per_connectで修正を行いましたが、ループでは修正しませんでした(これがエラーの原因です)。

これを行うと、最初のサーバーが生成され、gen_tcp:listenで接続が初期化され、gen_tcp:acceptで接続が待機されます。接続が確立されるとすぐに、新しいプロセスが起動され、受け入れを待機します。現在のプロセスでは、接続ポートをパラメーターとしてループが呼び出されます。

ここで、私が提案するよりも賢いクライアントを作成する必要があります。これは、同じオープン接続を使用してしばらくループする可能性があります:o)

-module(socket_examples).
-compile(export_all).

nano_client_eval(Str) ->
    {ok, Socket} = gen_tcp:connect("localhost", 2345,[binary, {packet, 0}]),
    nano_client_eval(Str,10,Socket).

nano_client_eval(_,0,Socket) ->
    gen_tcp:close(Socket);
nano_client_eval(Str,N,Socket) ->
    ok = gen_tcp:send(Socket, term_to_binary(Str ++ " loop " ++ integer_to_list(N))),
    receive
        {tcp,Socket,Bin} ->
            io:format("Client received binary = ~p on socket ~p~n",[Bin,Socket]),
            Val = binary_to_term(Bin),
            io:format("Client result = ~p~n",[Val]),
            timer:sleep(1000),
            nano_client_eval(Str,N-1,Socket)
        after 5000 ->
            io:format("nano_client_eval got not answer to ~p~n",[Str]),
            {error,timeout}
    end.

start_nano_server() ->
    {ok, Listen} = gen_tcp:listen(2345, [binary, {packet, 0},{reuseaddr, true},{active, true}]),                       
    spawn(fun() -> par_connect(Listen) end).

par_connect(Listen) ->      
    {ok, Socket} = gen_tcp:accept(Listen),
    spawn(fun() -> par_connect(Listen) end),
    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)
        Reply = string:to_upper(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 ~p closed by request~n",[Socket])
    after 60000 ->
            gen_tcp:close(Socket),
            io:format("Server socket ~p closed, no more activity~n",[Socket])
    end.

ここに画像の説明を入力してください

于 2013-02-13T08:40:23.733 に答える