我为一个简单的服务器程序编写了这个模块,该程序接收请求并向客户端发送响应。它工作得很好,但如果在客户端连接的情况下重新编译此模块,客户端会断开连接,如果我将客户端重新连接到此服务器并发送请求,则没有响应。有什么想法吗?!
下面是我的模块:
-module(controller).
-export([start/1, loop/1, response/2]).
-include_lib("types.hrl").
-define(END_CHAR, "$").
-spec start(Port) -> no_return() when
Port :: char().
-spec loop(Listen) -> no_return() when
Listen :: port().
-spec handler(Socket) -> no_return() when
Socket :: port().
-spec response(HandlerPID, Data) -> {send_msg, Msg} when
HandlerPID :: pid(),
Data :: string(),
Msg :: response().
start(Port) ->
{ok, Listen} = gen_tcp:listen(Port, [{active, once}]),
spawn(?MODULE, loop, [Listen]).
loop(Listen) ->
{ok, Socket} = gen_tcp:accept(Listen),
spawn(?MODULE, loop, [Listen]),
handler(Socket).
handler(Socket) ->
receive
{tcp, Socket, Data} ->
%io:format("recv ~p~n", [Data]),
spawn(?MODULE, response, [self(), Data]),
inet:setopts(Socket, [{active, once}]),
handler(Socket);
{tcp_closed, Socket} ->
%io:format("disconnected~n", []),
gen_tcp:close(Socket);
{send_msg, Msg} ->
gen_tcp:send(Socket, lists:flatten(io_lib:format("~p", [Msg])) ++ ?END_CHAR),
handler(Socket)
end.
response(PID, Data) ->
[Req|Args] = string:tokens(Data, ?END_CHAR),
{ReqPID, ReqRef} = spawn_monitor(view, request, [list_to_atom(Req), self(), Args]),
receive
{'DOWN', ReqRef, process, ReqPID, {function_clause, _}} -> PID ! {send_msg, invalid_request};
{'DOWN', ReqRef, process, ReqPID, {{case_clause, _}, _}} -> PID ! {send_msg, bad_args};
{'DOWN', ReqRef, process, ReqPID, {{badmatch, _}, _}} -> PID ! {send_msg, bad_args};
Resp -> PID ! {send_msg, Resp}
end.发布于 2015-09-21 02:12:02
备注
{tcp_closed, Socket} ->
%io:format("disconnected~n", []),
gen_tcp:close(Socket);在handler中。它不会再次调用handler,它只是返回,因此服务器进程停止。
您的loop函数名也具有误导性,handler是实际的循环。
发布于 2015-09-22 20:41:02
我建议您研究一下Ranch -A套接字接收器池。
https://stackoverflow.com/questions/32682623
复制相似问题