[解決済み] Elixirでgen_tcpを使用してアクティブなソケットのTCPタイムアウトを検出するにはどうすればよいですか?
質問内容
を持っています。
GenServer
を介してリモートの TCP コネクションに接続しています。
gen_tcp
.
opts = [:binary, active: true, packet: :line]
{:ok, socket} = :gen_tcp.connect('remote-url', 8000, opts}
でメッセージを処理しています。
def handle_info({:tcp, socket, msg}, stage) do
IO.inspect msg
{:noreply, state}
end
これは素晴らしい動作です。しかし、TCPサーバーはタイムアウトしがちです。もし私が
gen_tcp.recv
タイムアウトを指定することができます。しかし、私が使っているのは
active: true
でメッセージを受信し
handle_info
をループして呼び出す必要はありません。
recv
. そのため
GenServer
は、サーバーがタイムアウトしても、喜んで次のメッセージを待ちます。
どうすれば
GenServer
X秒後にTCPコネクションからメッセージを受信しなかった場合、関数をトリガーしますか?私は
recv
?
解決方法は?
TCP接続自体がタイムアウトした場合、クローズドソケットメッセージを受信するはずです。
{tcp_closed, Socket}
. でマッチングさせます。
handle_info
で終わりです。を確立することについては
自分の
接続のタイムアウト、私は通常
erlang:send_after/3
で受け取ることができるタイムアウトメッセージのセマンティックを効果的に追加しています。
handle_info
または
receive
サービスループが存在する可能性があります。
erlang:send_after(?IDLE_TIMEOUT, self(), {tcp_timeout, Socket})
これは、トラフィックを受信するたびにタイマーをキャンセルすることと対になっている必要があります。これは次のようなものです。
handle_info({tcp, Socket, Bin}, State = #s{timer = T, socket = Socket}) ->
_ = erlang:cancel_timer(T),
{Messages, NewState} = interpret(Bin, State),
ok = handle(Messages),
NewT = erlang:send_after(?IDLE_TIMEOUT, self(), {tcp_timeout, Socket})
{noreply, NewState#s{timer = NewT}};
handle_info({tcp_closed, Socket}, State = #s{timer = T, socket = Socket}) ->
_ = erlang:cancel_timer(T),
NewState = handle_close(State),
{noreply, NewState};
handle_info({tcp_timeout, Socket}, State = #s{socket = Socket}) ->
NewState = handle_timeout(State),
{noreply, NewState};
handle_info(Unexpected, State) ->
ok = log(warning, "Received unexpected message: ~tp", [Unexpected]),
{noreply, State}.
関連
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン