I have TCP server that listen Ip:Port.
listen(Ip, Port) ->
Opts = [
binary,
{active, false},
{packet, 0},
{reuseaddr, true},
{ip, Ip}
],
case gen_tcp:listen(Port, Opts) of
{ok, ListenSock} ->
?MODULE:loop_accept(ListenSock);
{error, Reason} ->
exit(Reason)
end.
loop_accept(ListenSock) ->
{ok, Sock} = gen_tcp:accept(ListenSock),
?MODULE:loop(Sock),
?MODULE:loop_accept(ListenSock).
loop(Sock) ->
case gen_tcp:recv(Sock, 0) of
{ok, Data} ->
gen_tcp:send(Sock, [<<"Response: ">>, Data]),
?MODULE:loop(Sock);
{error, Reason} ->
ok
end.
Task: when one client connected on Ip:Port (for example telnet Ip Port), another client trying connection must be dropped. In other words, exclusive usage of Ip:Port.
Questions:
- How it's implement on Erlang using gen_tcp module?
- It is possible resolve by options of gen_tcp:listen?
- How to programmaticaly drop trying connection in Erlang?
P.S. I am new in erlang.
First, you can't
recv()like that when you specify{packet, 0}. Read this answer about gen_tcp.The server could:
Pid = spawn(?MODULE, loop, [Sock])Monitor the process in #1:
But to prevent a race condition, you should perform #1 and #2 in one step:
After
gen_tcp:accept(ListenSock)executes, do:Detect when the client terminates and therefore it's time to start listening for a new client:
Or, if the client will not terminate after it is done sending data, then you can detect when the client closes the socket in
loop():=====
backlog socket option (e.g.
{backlog, 0}):The backlog option sets an OS socket configuration parameter. From
man listen:And, a good read is this thread at Perl Monks: TCP server: How to reject connections when busy? Some snippets about the backlog configuration: