2009-11-30 55 views
0

我做了一個tcp服務器產生一個進程監聽傳入的連接。下面是示例代碼(從我的原代碼中刪除了一些東西):問題gen_tcp:接受

模塊:

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

模塊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. 

的問題是:每一次當我嘗試在此端口上從telnet連接,我在gen_tcp:accept上收到錯誤{error,closed}。這已經迫使我試圖弄清楚發生了什麼。

感謝,

回答

2

你「接受環」是不是一個真正的環...它是人爲的。

您可能想要「do_accept_loop」和適當的「server_loop」來處理連接。看看this

你想沿着線的東西:

% 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:我已經提供了我的答案的鏈接。在你的'init'函數中,你調用'accept_loop',但你應該做的是調用一個爲這個連接產生一個服務器的函數。這就是爲什麼我根據'do_accept'提出了一些建議。 此外,你需要一個適合你的衍生服務器的「循環」功能。你的'accept_loop'根本不*循環*。看看我提供的鏈接。 – jldupont 2009-11-30 18:49:49

+0

哈哈,你比我快。看看你的例子,我改變了「spawn(server_listener,accept_loop,[LSocket]);」 (就在這裏做%的東西)「accept_loop(LSocket)」,它的工作!所以我認爲產卵電話比我當前的進程退出慢,使得我的接受套接字在新套接字開始前關閉。謝謝! – scooterman 2009-11-30 18:54:53