[erlang-questions] TCP flow control problem

Kaiduan Xie <>
Thu Feb 10 19:43:22 CET 2011


Nav,

I have been working on a server with TCP/TLS/UDP support for a while,
the following is my experience,

1. For TCP/TLS, spawns one gen_fsm for a connection, and sets the
socket as {active, once} first, and then handles incoming packet in
handle_info(), parses the packet in the gen_fsm (this is the place
where gen_fsm comes into play, state machine is very handy to parse
message because TCP/TLS is stream based), after reading a packet from
network, sets the socket as {active, once} again.

2. You can accept TCP/TLS connections from multiple processes, this
will improve your server's connection acceptance speed.

3. If your TCP/TLS connection is long-live, and idle most of the time,
hibernates the gen_fsm to save memory.

Cheers,

/Kaiduan
On Thu, Feb 10, 2011 at 12:17 PM, Nav <> wrote:
> Hi Bengt and Alain,
>
> Many thanks for pointing out my logical error.
>
> As I am now rewriting my whole network layer, what would be the best
> recommended design.
>
> My requirement is that the Network Layer should just read data, and
> pass it on to other OTP component using handle_cast.
>
> Network Layer Logic (gen_fsm or gen_server) psuedo code
> -------------------------------------------------------------------------------------
>
> - Socket in {active, once} mode  {to keep flow under control with remote server}
> - Read available data using handle_info()
> - Parse message-data using marker, and store rest of message-data
> (=DataRest) inside State variable of OTP
> - Set socket to {active, once} mode
> - Go back to start, read data and add after DataRest, and parse
> message, and repeat above steps.
>
>
> Since I am aiming to handle very high amount of traffic, would this
> design suffice?
>
> For e.g.,
> - Could handle_cast queue run out of memory, if network layer is
> pumping messages at faster rate?
>
> Any better design to make server faster and be able to handle high capacity?
>
>
> Thanks again,
>
> Nav
>
>
> On Mon, Jan 31, 2011 at 7:27 PM, Alain O'Dea <> wrote:
>> Bengt is right.  I suggest using a gen_server to collect the data and look for message boundaries.  As it collects data it would prepend it to an iodata() in its own State structure.  When it encounters a message boundary it would cast the data in its State plus the data up to and including the message boundary onto a delegate gen_server for processing.  The data in the packet after the message boundary would then become the new partial message data in it's State.
>>
>> Below is pseudo-code for this:
>>
>> -record(state, {partial_message :: iodata(), delegate :: pid()}).
>>
>> handle_info({tcp, {data, Data}}, _From, #state{partial_message = Partial} = State) ->
>>    NextPartial = case boundary_split(Data) of
>>        {MsgEnd, NextMsg} ->
>>            tcp_message_handler:handle_message(State#state.delegate, [MsgEnd | Partial]),
>>            NextMsg;
>>        Data ->
>>            [Data | Partial]
>>    end,
>>    {noreply, State#state{partial_message = NextPartial}.
>>
>>
>> On 2011-01-31, at 4:19, Bengt Kleberg <> wrote:
>>
>>> Greetings,
>>>
>>> TCP is a stream protocol. It does not preserve message boundaries. You
>>> have to handle that yourself. Sleeping one second is one way. When you
>>> do not sleep, how do you separate the messages?
>>>
>>>
>>> bengt
>>>
>>> On Sun, 2011-01-30 at 23:38 +0100, Nav wrote:
>>>> I have implemented two TCP servers using gen_fsm, and gen_server, respectively.
>>>> I am using {active, once} option, after getting each message.
>>>>
>>>> When I try to send data from one side to another in a loop, the data
>>>> gets corrupted (first 1 or 2 message arrive ok, but following gets
>>>> corrupted) when it arrives at other side.
>>>>
>>>> However, if I put a timer:sleep(1000) before sending each message,
>>>> then everything seems to go fast.
>>>>
>>>> What seems to go wrong by sending data too fast? Do I need to set some
>>>> more socket options?
>>>>
>>>> Thanks, Nav
>>>>
>>>> ________________________________________________________________
>>>> erlang-questions (at) erlang.org mailing list.
>>>> See http://www.erlang.org/faq.html
>>>> To unsubscribe; mailto:
>>>>
>>>
>>>
>>> ________________________________________________________________
>>> erlang-questions (at) erlang.org mailing list.
>>> See http://www.erlang.org/faq.html
>>> To unsubscribe; mailto:
>>>
>>
>> ________________________________________________________________
>> erlang-questions (at) erlang.org mailing list.
>> See http://www.erlang.org/faq.html
>> To unsubscribe; mailto:
>>
>>
>
> ________________________________________________________________
> erlang-questions (at) erlang.org mailing list.
> See http://www.erlang.org/faq.html
> To unsubscribe; mailto:
>
>


More information about the erlang-questions mailing list