2009-11-30 3 views
0

J'ai créé un serveur tcp qui génère un processus pour écouter les connexions entrantes. Voici l'exemple de code (suppression d'un certain nombre de choses de mon code d'origine):Problèmes gen_tcp: accepter

Module

a:

main([]) -> 
    { ok, Pid } = b:start(), 
    receive 
      _ -> 
        ok 
    end. 

Module b:

-define(TCP_OPTIONS, [binary, { active, false}, { packet, 0 } , {reuseaddr, true}]). 

... 

start_link(Port) -> 
    Pid = spawn_link(server_listener, init, [ Port ]), 
    { ok , self() }. 

init(Port, Processor) -> 
    case gen_tcp:listen(Port, ?TCP_OPTIONS) of 
    { ok , LSocket } -> 
      accept_loop(LSocket); 
    { error, Reason } -> 
     { stop, Reason } 
    end. 

accept_loop(LSocket) -> 
    ?LOG("Current socket acceptor PID [~w]~n", [self()]), 
    case gen_tcp:accept(LSocket) of 
     { ok, Socket } -> 
     %do stuff here 
     spawn(server_listener , accept_loop, [ LSocket ]); 
     { error, Reason } -> 
     ?LOG("Error accepting socket! [ ~s ]~n", [ Reason ]) 
    end. 

Le problème est: chaque fois que je tente de se connecter depuis telnet sur ce port, je reçois une erreur {error, closed} sur gen_tcp: accept. Cela me rend déjà fou en essayant de comprendre ce qui se passe.

Merci,

Répondre

2

Votre « boucle accepter » n'est pas vraiment une boucle ... et il est artificiel.

Vous voulez probablement "do_accept_loop" et un "server_loop" approprié pour gérer une connexion. Jetez un oeil à this.

Vous voulez quelque chose le long des lignes de:

% Call echo:listen(Port) to start the service. 
listen(Port) -> 
    {ok, LSocket} = gen_tcp:listen(Port, ?TCP_OPTIONS), 
    accept(LSocket). 

% Wait for incoming connections and spawn the echo loop when we get one. 
accept(LSocket) -> 
    {ok, Socket} = gen_tcp:accept(LSocket), 
    spawn(fun() -> loop(Socket) end), 
    accept(LSocket). 

% Echo back whatever data we receive on Socket. 
loop(Socket) -> 
    case gen_tcp:recv(Socket, 0) of 
     {ok, Data} -> 
      gen_tcp:send(Socket, Data), 
      loop(Socket); 
     {error, closed} -> 
      ok 
    end. 
+1

@scooterman: J'ai fourni un lien dans ma réponse. Dans votre fonction 'init', vous appelez' accept_loop' mais vous devez appeler une fonction qui génère un serveur pour cette connexion. C'est pourquoi j'ai suggéré quelque chose du genre 'do_accept'. En outre, vous avez besoin d'une fonction 'loop' appropriée pour votre serveur engendré. Votre 'accept_loop' n'est pas * en boucle * du tout. Jetez un oeil sur le lien que j'ai fourni. – jldupont

+0

Lol vous étiez plus rapide que moi. En regardant votre exemple, j'ai changé le "spawn (server_listener, accept_loop, [LSocket]);" (juste après% fait des choses ici) pour "accept_loop (LSocket)" et cela a fonctionné! Donc, je pense que l'appel de spawn a été plus lent que la sortie de mon processus en cours, ce qui rend ma socket d'acceptation fermée avant que le nouveau ne démarre. Merci quand même! – scooterman

Questions connexes