erlang异步监听套接字连接请求实验

-module(socket).

-behavior(gen_server).

-export([
	start/0,
	do_client_connect/0
	]).

-export([
	init/1,
	handle_call/3,
	handle_cast/2,
	handle_info/2,
	terminate/2,
	code_change/3
	]).
	
-define(TCP_OPTIONS,[binary, {packet, 4}, {nodelay, true}, {reuseaddr, true}, {active, true}]).
-define(LISTEN_PORT,12345).

do_client_connect() ->
	gen_tcp:connect("localhost",12345,[]).
	
start() ->
	{ok,LSocket} = gen_tcp:listen(?LISTEN_PORT,?TCP_OPTIONS),
	io:format("start. LSocket:~w~n",[LSocket]),
	
	%% 这里启动了两个gen_server进程去accept。当有连接请求过来时,哪个进程空闲就由哪个去处理;
	{ok,Pid1} = gen_server:start_link({local,a},?MODULE,[LSocket],[]),
	io:format("start. Pid1:~w~n",[Pid1]),
	{ok,Pid2} = gen_server:start_link({local,b},?MODULE,[LSocket],[]),   
	io:format("start. Pid2:~w~n",[Pid2]),
	
	
	%%gen_tcp:controlling_process(Pid,LSocket).
	ok.
	
init([LSocket]) ->
	do_accept(LSocket),
	{ok,LSocket}.
	
handle_info({inet_async, LSock, _Ref, {ok, Sock}},LSock) ->
	io:format("handle_info. pid:~w~n",[self()]),
	io:format("handle_info. accepted one LSock:~w~n",[LSock]),
	io:format("handle_info. accepted one Sock:~w~n",[Sock]),
	%%do_accept(LSock). %%这里本不应该注释掉的。注释掉的目的是为了测试:先有客户端请求connect,然后再手动发消息accept给服务端让服务端执行prim_inet:async_accept监听。实验证明是可以的;
	{noreply,LSock};
handle_info(accept,LSock) ->
	do_accept(LSock),
	{noreply,LSock}.
	
handle_cast(_Msg,_State) ->
	{noreply,_State}.
	
handle_call(_Request,_From,_State) ->
	{noreply,_State}.
	
terminate(_Reason, _State) ->
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.
	
do_accept(LSocket) ->
  %%经过测试,发现,可以是服务端先accept,然后客户端connect;也可以是客户端先connect,然后服务端再accept;都可以建立socket连接; case prim_inet:async_accept(LSocket, -1) of {ok, _Ref} -> ok; _Error -> ok end.

  

posted @ 2015-06-02 00:23  gitfong  阅读(450)  评论(0编辑  收藏  举报