创建新的短代码Erlang时面临的问题

1l5u6lss  于 2023-10-14  发布在  Erlang
关注(0)|答案(1)|浏览(315)

我试图实现一个emoji服务器并为它编写代码。但是当我在终端测试它时,它显示超时错误。要检查代码,请检查alias函数:

  1. -spec alias(Pid :: pid(), Short1 :: shortcode(), Short2 :: shortcode()) -> ok | {error, Reason :: term()}.
  2. alias(Pid, Short1, Short2) when is_pid(Pid), is_list(Short1), is_list(Short2) ->
  3. Pid ! {alias, Short1, Short2},
  4. receive
  5. {ok, Short2} -> ok;
  6. {error, Reason} -> {error, Reason}
  7. after 1000 -> {error, timeout}
  8. end.
  9. emoji_loop(State = #emoji_state{}) ->
  10. receive
  11. {alias, Short1, Short2} ->
  12. io:format("Received alias: Short1 = ~p, Short2 = ~p~n", [Short1, Short2]),
  13. case dict:find(Short1, State#emoji_state.shortcodes) of
  14. {ok, _} ->
  15. case dict:find(Short2, State#emoji_state.aliases) of
  16. {ok, _} -> emoji_loop(State);
  17. error ->
  18. NewAliases = dict:store(Short2, Short1, State#emoji_state.aliases),
  19. emoji_loop(State#emoji_state{aliases = NewAliases})
  20. end;
  21. error -> emoji_loop(State)
  22. end;
  23. end.

我已经添加了io:format来调试代码,似乎我的new_shortcode函数有问题,但我无法找到问题。
下面是我输入到终端的输入:

  1. {ok, Pid} = emoji:start([{"happy", <<"😄">>}, {"sad", <<"😢">>}]).

然后接收到如下输出:

  1. {ok,<0.92.0>}

然后又输入了另一个输入

  1. emoji:new_shortcode(Pid, "dollar", <<"💵"/utf8>>).

收到了这样一条信息:

  1. Received new_shortcode: Short = "dollar", Emo = <<240,159,146,181>>

超时错误{error,timeout}
如何才能完美地运行创建短代码功能?
谢谢你再次澄清,但我仍然在努力与停止功能。下面是循环中的stop函数的代码。

  1. {stop, Pid} ->
  2. if
  3. Pid =:= self() ->
  4. exit(Pid);
  5. true ->
  6. emoji_loop(State)
  7. end

在这个停止函数中,我需要在编写命令emoji:stop(Pid)时停止服务器。之后,服务器的表情符号命令将无法工作,并给予错误。这里是停止主函数,按照您的指示传递Pid。

  1. -spec stop(Pid :: pid()) -> ok | {error, Reason :: term()}.
  2. stop(Pid) when is_pid(Pid) ->
  3. Pid ! {stop, self()},
  4. receive
  5. ok -> ok;
  6. {error, Reason} -> {error, Reason}
  7. after 5000 ->
  8. {error, timeout}
  9. end.
xeufq47z

xeufq47z1#

查看new_shortcode/3函数,我们看到它向Pid发送了一条消息,然后期待一个响应,但是它在{error, timeout}上失败了,因为它从来没有得到那个响应:

  1. new_shortcode(Pid, Short, Emo) when is_pid(Pid), is_binary(Emo), is_list(Short) ->
  2. Pid ! {new_shortcode, Short, Emo},
  3. receive
  4. {ok, Short} -> ok;
  5. {error, Reason} -> {error, Reason}
  6. after 1000 -> {error, timeout}
  7. end.

这里的Pid是运行emoji_loop/1函数的进程,它以元组的形式接收命令,并通过改变循环状态来执行命令。但是emoji_loop/1函数不做的是将消息发送回发送命令的进程,这就是为什么像new_shortcode/3这样的函数会超时等待回复。
要修复它,请将调用者的pid发送到emoji_loop/1,以便它可以回复。这意味着更改new_shortcode/1以将self()添加到它发送给emoji_loop/1的命令元组中:

  1. new_shortcode(Pid, Short, Emo) when is_pid(Pid), is_binary(Emo), is_list(Short) ->
  2. Pid ! {new_shortcode, Short, Emo, self()},
  3. receive
  4. {ok, Short} -> ok;
  5. {error, Reason} -> {error, Reason}
  6. after 1000 -> {error, timeout}
  7. end.

然后,我们必须更改emoji_loop/1以将回复发送回调用者。例如,像这样更改new_shortcode的处理:

  1. {new_shortcode, Short, Emo, Pid} ->
  2. io:format("Received new_shortcode: Short = ~p, Emo = ~p~n", [Short, Emo]),
  3. NewShortCodes = case dict:find(Short, State#emoji_state.shortcodes) of
  4. {ok, _} -> State#emoji_state.shortcodes;
  5. error ->
  6. dict:store(Short, Emo, State#emoji_state.shortcodes)
  7. end,
  8. Pid ! {ok, Short},
  9. emoji_loop(State#emoji_state{shortcodes = NewShortCodes});

通过这个更改以及lookup的类似更改,我们可以看到它按预期工作:

  1. 3> {ok, Pid} = emoji:start([{"happy", <<"😄">>}, {"sad", <<"😢">>}]).
  2. {ok,<0.138.0>}
  3. 4> emoji:new_shortcode(Pid, "dollar", <<"💵"/utf8>>).
  4. Received new_shortcode: Short = "dollar", Emo = <<240,159,146,181>>
  5. ok
  6. 5> emoji:lookup(Pid, "dollar").
  7. Received lookup: Short = "dollar"
  8. {ok,<<240,159,146,181>>}

我们必须对所有期望emoji_loop/1进程回复的命令函数进行类似的更改。
我强烈建议你考虑使用gen_server,而不是运行你自己的服务器,因为它可以轻松地处理你在这里尝试做的一切,也有助于错误处理和进程管理和清理。

  • 更新:这个问题被修改为添加了一个关于emoji:stop/1的具体问题,所以我更新了我的答案来解决它:*

emoji_loop/1中的原始stop处理程序只是退出:

  1. stop ->
  2. exit(normal)

为了解决超时问题,您将其修改为:

  1. {stop, Pid} ->
  2. if
  3. Pid =:= self() ->
  4. exit(Pid);
  5. true ->
  6. emoji_loop(State)
  7. end

但这种变化有两个问题:

  1. Pid永远不会是self(),因为emoji_loop/1不会发送自己的消息,所以if的第一个子句永远不会发生。
    1.让emoji_loop/1像在true子句中那样递归地调用自己意味着循环进程保持运行,而不是按请求停止。
    要修复这些问题,您必须修复stop处理程序,就像上面修复new_shortcode处理程序一样:用命令传递调用者的pid,并让命令处理程序向调用者返回一个应答。如果我们回到原始的stop处理程序并进行这些更改,我们会得到:
  1. {stop, Pid} ->
  2. Pid ! ok,
  3. exit(normal)

stop/1函数必须更改为使用命令发送其pid:

  1. stop(Pid) when is_pid(Pid) ->
  2. Pid ! {stop, self()},
  3. receive
  4. ok -> ok;
  5. {error, Reason} -> {error, Reason}
  6. after 1000 -> {error, timeout}
  7. end.

我们可以测试stop/1来验证它是否真的停止了循环进程:

  1. 2> {ok, Pid} = emoji:start([{"happy", <<"😄">>}, {"sad", <<"😢">>}]).
  2. {ok,<0.117.0>}
  3. 3> is_process_alive(Pid).
  4. true
  5. 4> emoji:stop(Pid).
  6. ok.
  7. 5> is_process_alive(Pid).
  8. false
展开查看全部

相关问题