2015-09-23 4 views
0

Я пишу простой серверный модуль tcp и запускаю его хорошо. Когда я компилирую этот модуль во время работы, проблема в том, что когда клиент отправляет что-либо на сервер, он не получает ответа! Как это исправить?Модуль Erlang не работает после компиляции во время работы

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. 

ответ

2

я рекомендую следующее:

  • В параметрах слушающих, измените {active,once} на {active,false}. Вы не будете получать какие-либо сообщения в своем слуховом сокете, и вы не хотите, чтобы какие-либо принятые сокеты наследовали активные настройки, так как лучше, если бы они установили активные настройки, когда они действительно готовы обрабатывать входящие сообщения.

  • В вашей функции handler/1 переместите вызов inet:setopts/2 наверх, перед receive. Кроме того, измените его, чтобы проверить возвращаемое значение, например:

    ok = inet:setopts(Socket, [{active, once}]), 
    

    Я подозреваю, что вы положили его под обработку пункта {tcp, ...} сообщение, потому что технически это необходимо только там, но и иметь его в верхней части меньше подвержены ошибкам. Это также необходимо, так как в сокете нет активной настройки при первом вызове handler/1, учитывая первое изменение, которое я рекомендовал выше.

  • В вашем вызове gen_tcp:send/2, нет никакой необходимости, чтобы расплющить список вернулся из io_lib:format — он возвращает iolist, который gen_tcp:send/2 может работать нормально.