2016-04-08 2 views
0

J'ai trouvé un problème intéressant lors de l'utilisation du comportement gen_tcp. J'ai un serveur et un client. Le serveur accepte les connexions et le client crée de nombreux processus qui tentent tous de se connecter au serveur d'écoute.taux d'acceptation des sockets lors de l'utilisation de gen_tcp

Si j'essaie de démarrer le client qui engendre de nombreux processus qui tentent tous de se connecter au socket en même temps, beaucoup échouent. Cependant si je mets timer:sleep(x) alors chaque socket est en cours d'acceptation. Est-ce que cela signifie que gen_tcp:accept() a une limite où il peut accepter une demande de connexion?

Code pour le serveur et le client suit:

accept(State = #state{lsocket = LSocket, num = Num}) -> 
    case gen_tcp:accept(LSocket) of 
    {ok, Socket} -> 
     io:format("Accepted ~p ~n", [Num]), 
     {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#state{num = Num + 1}); 
    {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"), 
     ok 
    end. 

Client:

send(State = #state{low = Low, high = Low}) -> 
    State; 
send(State = #state{low = Low}) -> 
    N = Low rem 10, 
    Dest = lists:nth(N + 1, State#state.dest), 
    spawn(?MODULE, loop, [Dest, Low]), 
    %%timer:sleep(1), 
    NewState = State#state{low = Low + 1}, 
    send(NewState). 

loop({IP, Port}, Low) -> 
    case gen_tcp:connect(IP, Port, [binary]) 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 ~p ~n", [Data, RecPort, Low]) 
     end; 
    _Else -> 
     io:format("The connection failed ~n"), 
     loop({IP, Port}, Low) 
    end. 
+3

Vous pouvez imprimer le résultat _Else dans le client pour obtenir la raison de l'échec de la connexion au serveur. J'ai reformaté votre message pour le lire plus facilement. Il apparaît que lorsque le client réussit à se connecter, le client ne boucle pas et le processus se termine immédiatement, en fermant le socket. – Pascal

+2

Vous devez vérifier votre backlog TCP, la valeur par défaut étant 5. Vous pouvez le définir dans votre appel listen via l'option '{backlog, B}', où 'B' est un entier. Oh, et aussi, 'gen_tcp' n'est pas un comportement, c'est juste un module. –

Répondre

1

Il est vrai qu'un seul processus ne peut gen_tcp:accept/1 si vite, même si je ne suis pas sûr que c'est le goulot d'étranglement dans lequel vous courez.

Vous pourriez être intéressé par Ranch, la bibliothèque TCP pour le serveur web Cowboy. Le manuel comprend un section on internal features qui parle de l'utilisation de plusieurs accepteurs.

Dans votre cas, vous devriez essayer de produire plus de sortie de débogage pour vous-même. L'impression de l'erreur lorsque le client ne parvient pas à se connecter serait un bon début - il y a beaucoup de raisons pour lesquelles un client TCP pourrait ne pas se connecter.