为什么套接字关闭了Erlang
why is the socket closed Erlang
我是 Erlang 的新手。
我的问题是,当我第一次启动客户端时,一切似乎都很好,我得到了排序列表:<<1,5,72,97,108,108,111>>。
但是到第二次它不会收到排序列表,因为我认为套接字已关闭。客户端的输出是 "Connection closed".
这是我的代码:
客户
-module(client).
-export([client/0]).
client() ->
case gen_tcp:connect("localhost", 6000, [{mode, binary}]) of
{ok, Sock} ->
Data = [1, "Hallo", 5],
gen_tcp:send(Sock, Data),
receive
{tcp, _, Bin} ->
io:fwrite("Received sorted list from server: ~w~n", [Bin]);
{tcp_closed, _} ->
io:fwrite("Connection closed"),
gen_tcp:close(Sock)
end;
{error,_} ->
io:fwrite("Connection error! Quitting...~n")
end.
服务器
-module(server).
-export([server/0]).
-import(mergeSort,[do_recv/1]).
%creates a tcp socket on Port 6000
server() ->
{ok, Listen} = gen_tcp:listen(6000, [{keepalive, true}, %send keepalive packets
{reuseaddr, true}, %reuse address
{active, once}, %socket is active once
{mode, list}]), %binary traffic
spawn(fun() -> parallel_connection(Listen) end).
%server is listening
%accepts the connection
%starts MergeSort
parallel_connection(Listen) ->
io:fwrite("Listening connections..~n"),
{ok, Socket} = gen_tcp:accept(Listen),
io:fwrite("Connection accepted from ~w~n", [Socket]),
spawn(fun() -> parallel_connection(Listen) end),
do_recv(Socket).
合并排序
-module(mergeSort).
-export([do_recv/1]).
merge_sort(List) -> m(List, erlang:system_info(schedulers)).
%break condition
m([L],_) ->
[L];
%for more than one scheduler
m(L, N) when N > 1 ->
{L1,L2} = lists:split(length(L) div 2, L),
%self () returns Pid, make_ref() returns almost unique reference
{Parent, Ref} = {self(), make_ref()},
%starts a new process for each half of the list
%and sends Message to Parent
spawn(fun()-> Parent ! {l1, Ref, m(L1, N-2)} end),
spawn(fun()-> Parent ! {l2, Ref, m(L2, N-2)} end),
{L1R, L2R} = receive_results(Ref, undefined, undefined),
lists:merge(L1R, L2R);
m(L, _) ->
{L1,L2} = lists:split(length(L) div 2, L),
lists:merge(m(L1, 0), m(L2, 0)).
receive_results(Ref, L1, L2) ->
receive
{l1, Ref, L1R} when L2 == undefined -> receive_results(Ref, L1R, L2);
{l2, Ref, L2R} when L1 == undefined -> receive_results(Ref, L1, L2R);
{l1, Ref, L1R} -> {L1R, L2};
{l2, Ref, L2R} -> {L1, L2R}
after 5000 -> receive_results(Ref, L1, L2)
end.
do_recv(Socket) ->
%{ok, {Address, _}} = inet:peername(Socket),
receive
{tcp, Socket, List} ->
try
Data = merge_sort(List),
gen_tcp:send(Socket, Data),
io:fwrite("Sent sorted list to ~w | Job was done! Goodbye :)~n", [Socket]),
gen_tcp:close(Socket)
catch
_:_ ->
io:fwrite("Something went wrong with ~w | Worker terminated and connection closed!~n", [Socket]),
gen_tcp:close(Socket)
end;
{tcp_closed, _} ->
io:fwrite("Connection closed ~n");
{error, _} ->
io:fwrite("Connection error from ~w | Worker terminated and connection closed!~n", [Socket]),
gen_tcp:close(Socket)
end.
谁能帮帮我?
当您调用 client:client/0
时,它会创建连接、发送数据、接收响应,然后 returns。同时,服务器关闭套接字。当您再次调用 client:client/0
时,它会再次创建连接并发送数据,但随后它会收到前一个套接字的 tcp_closed
消息,然后它会 returns.
您可以通过在 receive
模式中指定客户端套接字来解决此问题:
receive
{tcp, Sock, Bin} ->
io:fwrite("Received sorted list from server: ~w~n", [Bin]);
{tcp_closed, Sock} ->
io:fwrite("Connection closed"),
gen_tcp:close(Sock)
end;
在此代码中,变量 Sock
替换了原始代码中 {tcp, _, Bin}
和 {tcp_closed, _}
元组中的两个下划线。这会强制消息仅匹配指定的套接字。
我是 Erlang 的新手。 我的问题是,当我第一次启动客户端时,一切似乎都很好,我得到了排序列表:<<1,5,72,97,108,108,111>>。 但是到第二次它不会收到排序列表,因为我认为套接字已关闭。客户端的输出是 "Connection closed".
这是我的代码:
客户
-module(client).
-export([client/0]).
client() ->
case gen_tcp:connect("localhost", 6000, [{mode, binary}]) of
{ok, Sock} ->
Data = [1, "Hallo", 5],
gen_tcp:send(Sock, Data),
receive
{tcp, _, Bin} ->
io:fwrite("Received sorted list from server: ~w~n", [Bin]);
{tcp_closed, _} ->
io:fwrite("Connection closed"),
gen_tcp:close(Sock)
end;
{error,_} ->
io:fwrite("Connection error! Quitting...~n")
end.
服务器
-module(server).
-export([server/0]).
-import(mergeSort,[do_recv/1]).
%creates a tcp socket on Port 6000
server() ->
{ok, Listen} = gen_tcp:listen(6000, [{keepalive, true}, %send keepalive packets
{reuseaddr, true}, %reuse address
{active, once}, %socket is active once
{mode, list}]), %binary traffic
spawn(fun() -> parallel_connection(Listen) end).
%server is listening
%accepts the connection
%starts MergeSort
parallel_connection(Listen) ->
io:fwrite("Listening connections..~n"),
{ok, Socket} = gen_tcp:accept(Listen),
io:fwrite("Connection accepted from ~w~n", [Socket]),
spawn(fun() -> parallel_connection(Listen) end),
do_recv(Socket).
合并排序
-module(mergeSort).
-export([do_recv/1]).
merge_sort(List) -> m(List, erlang:system_info(schedulers)).
%break condition
m([L],_) ->
[L];
%for more than one scheduler
m(L, N) when N > 1 ->
{L1,L2} = lists:split(length(L) div 2, L),
%self () returns Pid, make_ref() returns almost unique reference
{Parent, Ref} = {self(), make_ref()},
%starts a new process for each half of the list
%and sends Message to Parent
spawn(fun()-> Parent ! {l1, Ref, m(L1, N-2)} end),
spawn(fun()-> Parent ! {l2, Ref, m(L2, N-2)} end),
{L1R, L2R} = receive_results(Ref, undefined, undefined),
lists:merge(L1R, L2R);
m(L, _) ->
{L1,L2} = lists:split(length(L) div 2, L),
lists:merge(m(L1, 0), m(L2, 0)).
receive_results(Ref, L1, L2) ->
receive
{l1, Ref, L1R} when L2 == undefined -> receive_results(Ref, L1R, L2);
{l2, Ref, L2R} when L1 == undefined -> receive_results(Ref, L1, L2R);
{l1, Ref, L1R} -> {L1R, L2};
{l2, Ref, L2R} -> {L1, L2R}
after 5000 -> receive_results(Ref, L1, L2)
end.
do_recv(Socket) ->
%{ok, {Address, _}} = inet:peername(Socket),
receive
{tcp, Socket, List} ->
try
Data = merge_sort(List),
gen_tcp:send(Socket, Data),
io:fwrite("Sent sorted list to ~w | Job was done! Goodbye :)~n", [Socket]),
gen_tcp:close(Socket)
catch
_:_ ->
io:fwrite("Something went wrong with ~w | Worker terminated and connection closed!~n", [Socket]),
gen_tcp:close(Socket)
end;
{tcp_closed, _} ->
io:fwrite("Connection closed ~n");
{error, _} ->
io:fwrite("Connection error from ~w | Worker terminated and connection closed!~n", [Socket]),
gen_tcp:close(Socket)
end.
谁能帮帮我?
当您调用 client:client/0
时,它会创建连接、发送数据、接收响应,然后 returns。同时,服务器关闭套接字。当您再次调用 client:client/0
时,它会再次创建连接并发送数据,但随后它会收到前一个套接字的 tcp_closed
消息,然后它会 returns.
您可以通过在 receive
模式中指定客户端套接字来解决此问题:
receive
{tcp, Sock, Bin} ->
io:fwrite("Received sorted list from server: ~w~n", [Bin]);
{tcp_closed, Sock} ->
io:fwrite("Connection closed"),
gen_tcp:close(Sock)
end;
在此代码中,变量 Sock
替换了原始代码中 {tcp, _, Bin}
和 {tcp_closed, _}
元组中的两个下划线。这会强制消息仅匹配指定的套接字。