我正在阅读“编程Erlang”一书,第253页有一个运行客户端/服务器连接的示例。下面的代码建议在两个独立的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 :(得分:1)
您收到的消息({error,econnrefused})显示服务器已关闭。
正如Muzaaya所说,{packet,N}应该在系统中保持一致。如果不是服务器将在binary_to_term转换和崩溃中失败(我没有深入研究,但我想这与信息的传输方式有关)。
接下来的请求将获得连接被拒绝的消息。
根据Muzaaya建议的更改,服务器能够执行binary_to_term,并且一切正常,直到调用b_misc:string2value ...这不包含在帖子中。
我注意到奇怪的东西:
我无法理解发生了什么。
编辑:
感谢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.