I have a tcp server(echo server) accepting connections. I have a client which when given a parameter N, creates those many processes trying to connect with the tcp listener. I am able to connect to those sockets but I can see many sockets being closed which is evident since I am using an echo server, I am not receiving messages back that I sent.
Here is the server code( crucial part)
init(State = #state{port = Port}) ->
ets:new(csockets, [ordered_set, named_table, public]),
ets:insert(csockets, {sockets, []}),
case gen_tcp:listen(Port, ?TCP_OPTIONS) of
{ok, LSocket} ->
NewState = State#state{lsocket = LSocket},
spawn(fun() -> accept(NewState) end),
{ok, NewState};
{error, Reason} ->
{stop, Reason}
end.
accept(State = #state{lsocket = LSocket}) ->
case gen_tcp:accept(LSocket) of
{ok, Socket} ->
{sockets, List} = hd(ets:lookup(csockets, sockets)),
NewList = [Socket | List],
ets:insert(csockets, {sockets, NewList}),
Pid = spawn(fun() ->
loop(Socket)
end),
gen_tcp:controlling_process(Socket, Pid),
accept(State);
{error, closed} -> State
end.
loop(Socket) ->
case gen_tcp:recv(Socket, 0) of
{ok, Data} ->
gen_tcp:send(Socket, Data),
loop(Socket);
{error, closed} ->
io:format("CLOSED ~n"), %% This asserts for many sockets
ok
end.
Client that connects to the server. Creating N processes that connect to the server and then use the returned socket to communicate.
send(State = #state{}) ->
Low = State#state.low,
High = State#state.high + 1,
case Low of
High -> State;
_Else ->
N = Low rem 10,
Dest = lists:nth(1, State#state.dest),
spawn(?MODULE, loop, [Dest, Low]),
NewState = State#state{low = Low + 1},
send(NewState)
end.
loop({IP, Port}, Low) ->
case gen_tcp:connect(IP, Port, [binary, {active, true}]) of
{ok, Socket} ->
io:format("~p Connected ~n", [Low]),
gen_tcp:send(Socket, "Hi"),
receive
{tcp, RecPort, Data} ->
io:format("I have received ~p on port ~p ~n", [Data, RecPort])
end;
_Else ->
io:format("The connection failed ~n")
loop({IP, Port}, Low)
end.
The error is on your server, you are pattern matching a messa like this on a tcp closed:
{error, closed}
but if you go to the documentantion for gen_tcp, you will notice that you should pattern match these messages:
{tcp_closed, Socket}
{tcp_error, Socket, Reason}
Update your code with:
loop(Socket) ->
case gen_tcp:recv(Socket, 0) of
{ok, Data} ->
gen_tcp:send(Socket, Data),
loop(Socket);
{tcp_error, Socket} ->
io:format("CLOSED ~n"), %% This asserts for many sockets
ok
end.
and you should start getting the CLOSED string on your screen