[erlang-questions] tcp data in a gen_fsm

Frans Schneider schneider@REDACTED
Sun Nov 29 15:25:37 CET 2015


Great! thanks for your explanation. Makes sense to send messages instead 
of calling the state functions.
But what about style? Would you consider a solution as you describe good 
style? I didn't see it in other projects used this way.

(Weird thing that good style is becoming such an issue to me since I 
started coding Erlang.)

/Frans

On 11/29/2015 02:59 PM, Jesper Louis Andersen wrote:
> One possible way is to message yourself. The following needs some help 
> because it never loops over the unpacking, which it should. But surely 
> you get the idea. The unpack function is now tasked with returning a 
> list of decoded packets, not just the first one:
>
> handle_info({tcp, Socket, RawData}, State_name, #state{buffer_state = 
> BufState} = State) ->
>     inet:setopts(Socket, [{active, once}]),
>     case unpack(BufState, RawData) of
>         {ok, Datas, BufState2} ->
>             [gen_fsm:send_event(self(), {packet, D}) || D <- Datas],
>             {next_state, State_name, State#state { buffer_state = 
> BufState2 }};
>         {more, BufState2} ->
>             {next_state, State_name, State#state { buffer_state = 
> BufState2 }}
>     end;
>
> Now, you can build two variants of the unpack/2 function. Rather than 
> returning {more, State} you can simply return {ok, [], State} which 
> eliminates the need for a separate 'more-variant'. But some times, it 
> is clever to return {more, NeededBytes, State} or something such in 
> order to tell the layer how many bytes it needs before it can produce 
> a new packet. In active mode, this allows you to expect the right 
> number of bytes directly, which sometimes helps since you can move 
> more or the load into the Erlang runtime.
>
> Now, the beauty is that the messages will sit in your own mailbox, and 
> in order. So you just handle them as any other messages and move the 
> state accordingly. And when you get new stuff in, your decode it in 
> your handle_info block and inject it into the mailbox. It is a fairly 
> modular solution as well: you effectively decoupled the TCP state from 
> the rest of your code, so you can now freely move it out of the FSM 
> should you prefer doing so. Vice versa, it also decouples the protocol 
> decoding from your FSM state, so it can worry about the semantic 
> impact of the protocol rather than the syntactic impact.
>
> On Sun, Nov 29, 2015 at 2:27 PM, Frans Schneider <schneider@REDACTED 
> <mailto:schneider@REDACTED>> wrote:
>
>     Dear list,
>
>     I have a gen_fsm representing the tcp connection to a remote
>     server with 6 states defined. Tcp data is handled by handle_info
>     with active = once.Tcp packets can contain more than one
>     commands/data items.
>     I would like to feed the data into the different FSM states in the
>     same manner as with send_event() and not handle the different
>     states in separate handle_info clauses for the different states or
>     a massive handle_info clause with a huge case statement.
>     Question is, can I call the state clauses like this or do I brake
>     OTP behavior?This is a client and blocking incoming data is not an
>     issue.
>
>     handle_info({tcp, Socket, Raw_data}, State_name, #state{buffer =
>     Buffer} = State) ->
>         {Datas, Buffer1} = unpack(<<Buffer/binary, Raw_data/binary>>),
>         lists:foldl(fun(Data, {StateName_in, State_in}) ->
>                             {next_state, StateName_out, State_out} =
>     ?MODULE:StateName_in({recv, Data}, State_in),
>                 {StateName_out, State_out}
>             end, {State_name, State}, Datas),
>         inet:setopts(Socket, [{active, once}]),
>         {next_state, active, State#state{buffer = Buffer1}};
>
>     I can of course use a seperate process for handling the tcp stuff
>     which makes the gen_fsm calls, but was just wondering if this
>     could work as well.
>
>     Thanks,
>
>     /Frans
>     _______________________________________________
>     erlang-questions mailing list
>     erlang-questions@REDACTED <mailto:erlang-questions@REDACTED>
>     http://erlang.org/mailman/listinfo/erlang-questions
>
>
>
>
> -- 
> J.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20151129/a2f3e32b/attachment.htm>


More information about the erlang-questions mailing list