2016-04-05 8 views
1

私はgen_server()としてtcp_listenerを実装しました。私はstart_link(ポート)と呼ばれる関数をそのポートでtcp_listenerを作成します。さて、tcp_listenerにstop()のリッスンを止めるように指示する方法を理解するのは難しいです。 このような関数をstopで呼び出そうとしました。erlangのgen_serverとして実装されたtcp_listenerを停止する方法

stop() -> gen_server:cast(?MODULE, shutdown) 

terminate/2関数リスニングソケットを閉じようとしましたが失敗しました。

terminate(_Reason, State = #state{lsocket = LSocket}) -> 
gen_tcp:close(LSocket), 
NewState = State#state{lsocket = null}, 
{ok, NewState}. 

リスニングソケットを閉じると、私が生成した受け入れられた接続はどうなりますか?

ありがとうございました!

start_link(Port) when is_integer(Port) -> 
    State = #state{port = Port}, 
    gen_server:start_link({local, ?MODULE}, ?MODULE, State, []). 

    init(State = #state{port = Port}) -> 
    io:format("Supervisor started me and I am listening at ~p ~n", [Port]), 
    case gen_tcp:listen(Port, ?TCP_OPTIONS) of 
    {ok, LSocket} -> 
    NewState = State#state{lsocket = LSocket}, 
    spawn(fun() -> accept(NewState) end), 
    {ok, NewState}; 
    {error, Reason} -> 
    {stop, Reason} 
    end. 

    accept(State = #state{lsocket = LSocket}) -> 
    case gen_tcp:accept(LSocket) of 
    {ok, Socket} -> 
    Pid = spawn(fun() -> 
    io:format("Connection accepted ~n"), 
    loop(Socket) 
       end), 
    gen_tcp:controlling_process(Socket, Pid), 
    accept(State); 
    {error, closed} -> error 
    end. 

    loop(Socket) -> 
    case gen_tcp:recv(Socket, 0) of 
     {ok, Data} -> 
     gen_tcp:send(Socket, Data), 
    loop(Socket); 
    {error, closed} -> 
     ok 
    end. 
+0

接続は生成されず、プロセスのみが生成されます。ソケットを閉じると、すべての接続が切断されます。あなたは実際にどのようなプロセスを産んでいますか? – Amiramix

+0

はい私は実際にプロセスを生成しています。私が接続を受け入れれば、私は新しいプロセスを生み出しています。だから後でリスニングソケットを閉じても、私はメッセージを送受信しているときに受け入れられたソケットで作業することができます(私の場合はecho_server)。今編集されたコードを参照してください。感謝amiramix – listen

答えて

1

私は特に、this chapter in the Learn You Some Erlang bookを見てお勧めします。

両方のソケットが同じ方法でメッセージを送信することができ、その後、gen_tcp:close(Socket)で閉じることができます。 acceptソケットを閉じると、そのソケットだけが閉じられ、listenソケットを閉じると、関連して確立されたacceptソケットは閉じられませんが、{error, closed}を返して現在実行中のaccept呼び出しを中断します。

したがって、すべてのソケットでgen_tcp:close(Socket)を呼び出すだけで済みます。

+1

。今や意味をなさないどのようにすべての受け入れられたソケットをstateの一部として格納してから、stop()が呼び出されたときにそれらのソケットをすべて閉じますか?それは悪いアプローチですか? – listen

+1

いいえ、まったくそうではありませんが、親または子のいずれかの状態に保存する必要があります。ソケットが閉じられ、プロセスがそれを使用しようとすると、エラーを受け取り、処理できる必要があることを忘れないでください。 – Amiramix

+0

ありがとう!私は、接続されているすべてのソケットを格納し、それぞれのソケットを閉じる状態の一部ではなく、etsテーブルとして実装しました。 – listen

関連する問題