轉自:http://blog.csdn.net/summerhust/article/details/8740973
一旦打開了一個使用TCP連接的套接字,它就始終保持打開狀態,直至任何一方關閉它或因為一個錯誤而終止。在建立一個連接時,一般為每一次請求產生一個新進程,只要有請求被處理,就保持這個進程的存活。
假設有一個監聽進程,其任務是等待傳入的TCP請求。只要一個請求到達,響應該連接請求的進程就變成了接收進程,有2種方案:
1. 產生新的進程並成為接收進程,而監聽者返回並繼續監聽下一個新的連接請求:
server() ->
{ok, ListenSocket} = gen_tcp:listen(1234, [binary, {active, false}]),
wait_connect(ListenSocket,0).
wait_connect(ListenSocket, Count) ->
{ok, Socket} = gen_tcp:accept(ListenSocket),
Pid = spawn(?MODULE, get_request, [Socket, [], Count]),
%將該套接字的控制進程改為Pid進程
gen_tcp:controlling_process(Socket, Pid),
wait_connect(ListenSocket, Count+1).
get_request(Socket, BinaryList, Count) ->
case gen_tcp:recv(Socket, 0, 5000) of
{ok, Binary} ->
io:format("received data: ~p~n", [binary_to_list(Binary)]),
get_request(Socket, [Binary|BinaryList], Count);
{error, closed} ->
handle(lists:reverse(BinaryList), Count)
end.
2. 使監聽進程成為接收進程,並使產生的新進程成為新的監聽者:
server() ->
{ok, ListenSocket} = gen_tcp:listen(1234, [binary, {active, false}]),
wait_connect(ListenSocket,0).
wait_connect(ListenSocket, Count) ->
{ok, Socket} = gen_tcp:accept(ListenSocket),
spawn(?MODULE, wait_connect, [ListenSocket, Count+1]),
get_request(Socket, [], Count).
說明:
(1) 創建一個套接字的進程(通過調用gen_tcp:accept或gen_tcp:connect)也就是該套接字的控制進程,該套接字所收到的任何消息都會轉發給這個控制進程,如果控制進程消亡,那么該套接字也會自行關閉。我們可以通過gen_tcp:controlling_process(Socket, NewPid)函數來把一個套接字的控制進程改為新的控制進程NewPid;
(2) gen_tcp:accept和gen_tcp:recv是阻塞的,可以用prim_inet:async_accept和prim_inet:async_recv實現非阻塞。