Erlang get_tcp:recv data length
Vance Shipley
vances@REDACTED
Thu Mar 3 18:28:07 CET 2011
Below is an example snipped from some code I use where the protocol
on a TCP connection is ASCII line based with the Start-of-Transmission
(STX) and End-of-Transmission (ETX) ASCII characters use to delinetated
each "frame". In simple cases one frame (STX.......ETX) is received in
one message. However when there are multiple messages sent quickly they
could wind up in the same TCP packet. It could also be that with slow
charater based writes one frame is received in multiple TCP packets.
The code below is meant to buffer up the incoming feed and act only
when a complete frame is received.
-behaviour(gen_server).
-define(STX, 2).
-define(ETX, 3).
handle_info({tcp, Socket, Data}, #state{socket = Socket} = State) ->
handle_frame(Data, State);
%% Parse the receive buffer for a framed record.
%%
handle_frame([?STX | Rest] = Data, State) ->
case lists:splitwith(fun(?ETX) -> false; (_) -> true end, Rest) of
{Record, [?ETX]} ->
% handle received frame
...
NewState = State#state{buffer = []},
{noreply, NewState};
{Record, [?ETX, ?STX | T]} ->
% handle received frame
...
NewState = State#state{buffer = []},
handle_frame([?STX | T], NewState);
{_, []} ->
NewState = State#state{buffer = Data},
{noreply, NewState}
end;
handle_frame([], State) ->
{noreply, State};
handle_frame(Data, #state{buffer = [?STX | _]} = State) ->
handle_frame(State#state.buffer ++ Data, State#state{buffer = []});
handle_frame([_ | T] = Data, #state{buffer = []} = State) ->
handle_frame(T, State).
--
-Vance
More information about the erlang-questions
mailing list