2013-02-13 76 views
0

我决定修改this thread中的代码,将服务器更改为并行的(如本书所述),并且无法正常工作。根据“编程Erlang”一书,下面的代码应该是presto-chango,但是我在第17行得到了错误。这里是并行服务器代码(完成的并行服务器在底部,这只是对最后一个线程)在旧服务器代码,erlang并行服务器错误?

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为调用循环(Socket)。也许是其他的东西,我不知道?

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

下一个是客户端代码,这也结束了dieing等待答复

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. 

回答

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. 

enter image description here

+0

能否请您上传您所使用的命令测试客户端和服务器?谢谢... – pandoragami 2013-02-13 14:38:04

+0

我开始3虚拟机:werl -sname w0,werl -sname w1和werl -sname w2。在一个虚拟机中,我启动服务器:socket_examples:start_nano_server()。在另一个虚拟机中,我启动客户端socket_examples:nano_client_eval(“来自w1的hello”)。和socket_examples:nano_client_eval(“来自w2的hello”)。一个客户端可以在服务器窗口中启动,但我更喜欢在不同的窗口中分开不同的打印输出。 – Pascal 2013-02-13 16:52:41