为啥套接字关闭 Erlang

Posted

技术标签:

【中文标题】为啥套接字关闭 Erlang【英文标题】:why is the socket closed Erlang为什么套接字关闭 Erlang 【发布时间】:2018-06-24 12:07:05 【问题描述】:

我是 Erlang 的新手。 我的问题是,当我第一次启动客户端时,一切似乎都很好,我得到了排序列表:>。 但是到第二次它不会收到排序列表,因为我认为套接字已关闭。客户端的输出是“连接关闭”。

这是我的代码:

客户

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

谁能帮帮我?

【问题讨论】:

【参考方案1】:

当您调用client:client/0 时,它会创建一个连接,发送其数据,接收响应,然后返回。同时,服务器关闭套接字。当你再次调用client:client/0 时,它会再次创建连接并发送数据,但随后它会收到上一个套接字的tcp_closed 消息,然后返回。

您可以通过在 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, _, Bintcp_closed, _ 元组中的下划线。这会强制消息只匹配指定的套接字。

【讨论】:

谢谢,伙计!你拯救了我的一天! :)

以上是关于为啥套接字关闭 Erlang的主要内容,如果未能解决你的问题,请参考以下文章

Erlang TCP 服务器总是在接受时关闭

生成后,Tcp Socket 在 erlang 中的远程节点上不起作用,错误,关闭?

Erlang 套接字发送超时永远不会发生

使用 XMPP 关闭 GCM 连接服务器的套接字

为啥 SO_RCVTIMEO 从侦听套接字继承到接受的套接字? [关闭]

为啥我的 Angular 2 应用程序中的 Web 套接字已关闭,尽管我还没有明确关闭它?