2013-02-11 102 views
2

我正在閱讀「編程Erlang」一書,並且有關運行客戶機/服務器連接的示例。下面的代碼建議在兩個單獨的erlang控制檯窗口中運行以下命令,從中我得到以下錯誤。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. 
+0

客戶端和服務器的選項'{packet,N}'應該是相同的。我建議你現在一直保持'N == 0'。 – 2013-02-11 08:05:46

+0

@Muzaaya - 這個{packet,4}應該是這個{packet,0}。這是什麼做btw? – pandoragami 2013-02-11 09:20:08

回答

2

您收到的消息({error,econnrefused})表明服務器已關閉。

正如Muzaaya所說,{數據包,N}在系統中應該是一致的。如果不是,服務器將在binary_to_term轉換和崩潰失敗(我沒有深入,但我想這是鏈接到信息傳輸的方式)。

接下來的請求會得到連接被拒絕的消息。

隨着Muzaaya建議的更改服務器能夠執行binary_to_term,並且一切工作,直到調用b_misc:string2value ...這不包括在帖子中。

我注意到一些奇怪,則:

  • 我用產卵推出的服務器(socket_examples,start_nano_server,[])。
  • 服務器在調用未定義模塊時崩潰 - >正常行爲。
  • 但後來shell掛起,我不能輸入任何新的命令。

我不明白是怎麼回事。

編輯:

感謝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. 
+0

由於代碼的接收部分是由shell進程本身處理的,所以shell掛起。 – 2013-02-11 18:00:42

+0

@ Muzaya-如果只有兩個獨立的erlang程序,一個用於服務器,另一個用作客戶端,並在兩個控制檯上運行它們會更好嗎?帕斯卡爾你在哪裏做了這個改變,你可以請你發佈你的代碼嗎?謝謝... – pandoragami 2013-02-11 19:06:18

+0

我編輯答案並將修改後的代碼 – Pascal 2013-02-12 08:33:31