[erlang-questions] blocking vs non-blocking gen_tcp:accept()
Serge Aleynikov
saleyn@REDACTED
Sat Feb 16 03:25:59 CET 2008
The objective of the article was to show how to build a TCP server using
only non-blocking processes and relying on the network driver to deliver
events of interest to the application layer. Blocking processes for N
seconds as in the code below is not always an acceptable design.
I also wish that the non-blocking prim_inet:accept/2 call was exposed to
the gen_tcp module. Perhaps this was an oversight rather than a
conscious decision?
Serge
Samuel Tesla wrote:
> Robin: Sorry if you got this twice, I realized just after I hit send that I
> had only replied to you.
>
> It only blocks the Erlang process, I believe.
>
> I've been meaning to post some code examples about this.
>
> What's always bugged me about that article is that it relies on prim_inet
> which is not guaranteed at all to remain the same across releases, whereas
> gen_tcp is (or at least guaranteed to be squawked about). I've written
> several TCP servers for personal projects, and I have found that there's no
> need to use anything but gen_tcp:accept (with a timeout).
>
> Here's an example of using gen_tcp:accept/2 in a gen_server that operates
> similarly to the one in that walkthrough.
>
> %% BEGIN CODE %%
> -module(tcp_lister).
>
> -behaviour(gen_server).
>
> -export([start_link/3]).
> -export([init/1, handle_call/3, handle_cast/2, handle_info/2,
> terminate/2, code_change/3]).
>
> -define(TCP_ACCEPT_TIMEOUT, 10000).
>
> -record(state, {
> listen, % listening socket
> sup % supervisor for client proxies
> }).
>
> start_link(Port, Opts, Sup) when is_integer(Port),
> is_list(Opts),
> is_atom(Sup) ->
> gen_server:start_link(?MODULE, [Port, Opts, Sup], []).
>
> init([Port, Opts, Sup]) ->
> {ok, Listen} = gen_tcp:listen(Port, Opts),
> State = #state{listen=Listen, sup=Sup},
> gen_server:cast(self(), accept),
> ?MODULE:accept(),
> {ok, State}.
>
> handle_call(Request, From, State) ->
> {stop, {unknown_call, {Request, From}}, State}.
>
> handle_cast(accept, State) ->
> #state{listen=Listen, sup=Sup} = State,
> case gen_tcp:accept(Listen, ?TCP_ACCEPT_TIMEOUT) of
> {ok, Socket} -> Sup:start_client(Socket);
> {error, timeout} -> ok
> end,
> gen_server:cast(self(), accept),
> {noreply, State};
> handle_cast(Msg, State) ->
> {stop, {unknown_cast, Msg}, State}.
>
> handle_info(Info, State) ->
> {stop, {unknown_info, Info}, State}.
>
> terminate(_Reason, _State) ->
> ok.
>
> code_change(_OldVsn, State, _Extra) ->
> {ok, State}.
>
> %% END CODE %%
>
> Then Sup:start_link/1 looks like this:
>
> %% BEGIN CODE %%
> start_client(Socket) ->
> {ok, Pid} = supervisor:start_child(?MODULE, []),
> gen_tcp:controlling_process(Socket, Pid),
> ok = client_module:set_socket(Pid, Socket),
> ok.
> %% END CODE %%
>
> And client_module:set_socket just lets the newly spawned process know what
> it's socket is just like in the trapexit article.
>
> There's several things this code doesn't handle. It could get other errors
> such as EMFILE or ENFILE from gen_tcp:accept/2. But in those cases the
> gen_server will blow up and get logged and the supervisor will do something
> appropriate. There is a brief moment during which sockets will sit idle in
> the buffer, but seriously, it's brief.
>
> The key thing here is that you're using gen_tcp:accept/2, so you won't be
> blocking the process forever. That means that the process will eventually
> loop through and check it's mailbox again and can handle all of the fun
> supervision-tree stuff gen_server does behind the scenes.
>
> Hope this helps!
>
> -- Samuel
>
> On Fri, Feb 15, 2008 at 2:16 PM, Robin <robi123@REDACTED> wrote:
>
>> Does gen_tcp:accept() block the entire OS thread or just the calling
>> erlang process?
>>
>> "One of the shortcomings of the gen_tcp module is that it only exports
>> interface to a blocking accept call." ->
>>
>> http://www.trapexit.org/Building_a_Non-blocking_TCP_server_using_OTP_principles
>>
>> Does the performance gain of non-blocking accept justify the added
>> complexity (finite state machine etc)?
>>
>> thanks,
>>
>> Robin
>> _______________________________________________
>> erlang-questions mailing list
>> erlang-questions@REDACTED
>> http://www.erlang.org/mailman/listinfo/erlang-questions
>>
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://www.erlang.org/mailman/listinfo/erlang-questions
More information about the erlang-questions
mailing list