Erlang客户端 - 服务器错误 [英] Erlang client-server error

查看:293
本文介绍了Erlang客户端 - 服务器错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读Erlang编程一书,第253页有一个运行客户端/服务器连接的例子。下面的代码建议在两个单独的erlang控制台窗口中运行以下命令,从中得到以下错误。

  2> socket_examples:nano_client_eval(list_to_tuple([2 + 3 * 4,10 + 20]))。 
**异常错误:没有匹配的右侧值{error,econnrefused}
在函数socket_examples:nano_client_eval / 1(socket_examples.erl,第28行)

服务器端的命令:
socket_examples:start_nano_server()。 / p>

客户端的命令:
socket_examples:nano_client_eval(list_to_tuple([2 + 3 * 4,10 + 20]) )。



我没有防火墙,但不应该是一个问题,因为它不在线。

  %% --- 
%%摘自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 /1.0\r\\\
\r\\\
),%%(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 ,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 (服务器回复=〜p〜n),
回复= lib_misc:string2value(Str),%%(10)
io: [回复]),
gen_tcp:send(Socket,term_to_binary(Reply)),%%(11)
loop
{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,二进制,{packet,2}]),
io:format(connected to:〜p〜n,[Socket]),
gen_tcp:send(Socket,< >>),
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插座)。

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。


解决方案

您收到的邮件({error,econnrefused})显示服务器已关闭。



正如Muzaaya所说,{packet,N}在系统中应该是一致的。如果不是服务器将失败在binary_to_term转换和崩溃(我没有深入,但我猜这与信息的传输方式相关联)。



下一个请求将获得连接拒绝消息。



与Muzaaya建议的更改服务器能够执行binary_to_term,一切正常,直到调用b_misc:string2value




我注意到有点奇怪 b


  • 我使用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 /1.0\r\\\
\r\\\
),%%(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 ,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}
5000->
io:format(nano_client_eval没有回答〜p〜n,[Str]),
{错误,超时}
结束,
%gen_tcp: ),
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(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 (str),%%(10)
回复=字符串: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,二进制,{packet,0}]),
io:format(connected to:〜p〜n,[Socket]),
gen_tcp:send(Socket,< >>),
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插座)。

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。


I'm reading the book Programming Erlang and on page 253 there is an example for running a client/server connection. The code below suggests to run the following commands in two separate erlang console windows from which I get the following error.

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)

the command for the server side: socket_examples:start_nano_server().

the command for the client side: socket_examples:nano_client_eval("list_to_tuple([2+3*4,10+20])").

I don't have my firewall on but that shouldn't be an issue since its not online.

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

解决方案

The message you receive ({error,econnrefused}) shows that the server is down.

As Muzaaya said, the {packet,N} should be consistent in the system. If not the server will fail in the binary_to_term conversion and crash (I didn't dig into that but i guess this is linked to the way the information is transported).

The next requests will get then the connection refused message.

with the change suggested by Muzaaya the server is able to execute binary_to_term, and everything works until the call to b_misc:string2value... which is not included in the post.

I notice something weird then:

  • I launched the server using spawn(socket_examples,start_nano_server,[]).
  • the server crash on the call to an undefined module --> normal behavior.
  • But then the shell hang, and I cannot enter any new command.

I cannot understand what is going on.

Edit:

Thanks Muzaaya, I forgot to look at the client code...

I post here the code modified, in addition to the packet definition, I made some changes in the server and the client. I must say that I didn't look deeply in the documentation, but it seems that there were some trouble in the original code with opening, closing and accepting. I am not sure that the code here is correct, and I know it misses something to close properly the socket, and above all that this code doesn't serve multiple requests in parallel.

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

这篇关于Erlang客户端 - 服务器错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆