在Erlang中切换到多线程后,一个简单的Web服务器无法正常工作

时间:2015-09-05 16:29:33

标签: multithreading erlang

以下是 rudy.erl 的代码:

-module(rudy).
-export([init/1,handler/1,request/1,reply/2, start/1, stop/0]).

start(Port) ->
  register(rudy, spawn(fun() ->
    init(Port) end)).

stop() ->
  exit(whereis(rudy), "time to die").

init(Port) ->
  Opt = [list, {active, false}, {reuseaddr, true}],
  case gen_tcp:listen(Port, Opt) of         % opens a listening socket
    {ok, Listen} ->
      handler(Listen),
      gen_tcp:close(Listen),            % close the socket
      ok;
    {error, _Error} -> error
  end.

handler(Listen) ->
  case gen_tcp:accept(Listen) of            % listen to the socket
    {ok, Client} ->
      request(Client),
      gen_tcp:close(Client),
      handler(Listen);
    {error, _Error} -> error
  end.

request(Client) ->
  Recv = gen_tcp:recv(Client, 0),
  case Recv of
    {ok, Str} ->
      Request = http:parse_request(Str),
%%       spawn(rudy, reply, [Client, Request]);
      reply(Client, Request);
    {error, Error} ->
      io:format("rudy: error: ~w~n", [Error])
  end.


reply(Client, {{get, URI, _}, _, _}) ->
  timer:sleep(40),
  Response = http:ok(URI),
  gen_tcp:send(Client, Response),
  gen_tcp:close(Client).

如果我执行rudy:start(8027),它将通过访问 http://localhost:8027/ 正常工作,但是如果我将reply(Client, Request);转换为spawn(rudy, reply, [Client, Request]);,则前面的网址没有错误输出到命令行访问无法访问。

这里可能出现的问题是什么?提前谢谢。

1 个答案:

答案 0 :(得分:2)

这是由于竞争条件导致套接字在生成的进程可以回复之前关闭。 handler/1函数调用request/1,以及spawn发生回复的位置。一旦spawn启动新进程以调用reply/2,它将立即返回并request/1然后返回handler/1,这会在reply/2执行时立即关闭套接字新进程仍在尝试使用套接字。

您可以从gen_tcp:close/1移除handler/1来电,因为reply/2函数在回复后会调用它。

如果您想在Erlang中查看小型HTTP服务器的示例,请参阅我的simple web server

相关问题