[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