0

我决定通过将服务器更改为并行服务器(如书中所述)来修改此线程中的代码,但它无法正常工作。根据“Programming Erlang”一书,以下代码应该是 presto-chango,但我在第 17 行遇到错误。这是并行服务器代码(完成的并行服务器在底部,这只是对最后一个线程上的旧服务器代码),

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).

这就是错误,

=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}]}]}

以下是并行服务器代码,我认为调用循环(套接字)的第 14 行参数有问题。也许是别的东西,我不知道?

-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.

接下来是客户端代码,它也最终死于等待回复

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). 但在这种情况下,循环的参数将是 Socket 而不是 Listen。您在 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 回答