%%%------------------------------------------------------------------- %%% @author Joe Zhao %%% @copyright (C) 2014, %%% @doc %%% TCP server for socket connections %%% One listenners of ports %%% Spawns one receiver and one sender for different socket. %%% @end %%% Created : 27. 四月 2014 20:52 %%%------------------------------------------------------------------- -module(tcpserv). -author("Joe Zhao"). -compile([debug_info,export_all]). -define(TCP_OPTIONS,[list, {packet, 1}, {active, false}]). -define(DLYTIME,1000). %% API %%-export([]). lsockinit() -> ok. do_send(Sock,Pid,From) -> receive {From,exiting} -> ok; {Pid,shutdown} -> gen_tcp:close(Sock), ok; {_PPid,comm,Msg} -> gen_tcp:send(Sock,Msg), do_send(Sock,Pid,From) end. do_recv(Sock,Pid,To,Cnt) -> case gen_tcp:recv(Sock,0) of {ok, B} -> io:format("~p:\n ~p\n",[Cnt,B]), manip_msg(Pid,To,B), %% devicemon ! {self(),comm,Msg}, do_recv(Sock,Pid,To,Cnt+1); {error, closed} -> ok end. %% Message manipulation & dispatch routine manip_msg(Pid,To,[0,0,Addr,MsgReq,MsgRes|Name]) -> %% Operation command dispatch -> Complex(devicemon + Message handler) cmdiface:reg_feedbackOps(Addr,Name,?DLYTIME,[MsgReq],[MsgRes],To); manip_msg(Pid,To,[0|Tail]) -> %% Seperation from the next part devicemon ! {To,comm,[0|Tail]}; manip_msg(Pid,To,[Addr,Cmd|Name]) when Addr<10 -> %% Seperation from the next part cmdiface:invoke_cmd(Addr,Name,[Cmd]); manip_msg(Pid,To,Msg) -> % This needs improvements %% Fallback -> WTF Pid ! {self(),comm,Msg}. createsock(Sock,Pid) -> To=spawn(?MODULE,do_send,[Sock,Pid,self()]), Pid ! {self(),create,To}, ok = do_recv(Sock,Pid,To,0), To ! Pid ! {self(),exiting}. listenport(LSock,Pid) -> {ok,Sock} = gen_tcp:accept(LSock), spawn(?MODULE,createsock,[Sock,Pid]), listenport(LSock,Pid). portlistener(Port,Pid) -> {ok, LSock} = gen_tcp:listen(Port, [list, {packet, 1}, {active, false}]), listenport(LSock,Pid). monloop(Procs) -> receive {_Pid,shutdown} -> [ To ! shutdown || {_From,To} <- orddict:to_list(Procs) ]; {Pid,create,To} -> monloop(orddict:store(Pid,To,Procs)); {Pid,exiting} -> monloop(orddict:erase(Pid,Procs)); {_Pid,comm,Msg} -> [ To ! {self(),comm,Msg} || {_From,To} <- orddict:to_list(Procs) ], monloop(Procs) end. tcpmon(Port) -> Lis=spawn(?MODULE,portlistener,[Port,self()]), register(?MODULE,self()), monloop(orddict:new()), exit(Lis,shutdown). start(Port) -> spawn(?MODULE,tcpmon,[Port]). trap() -> trap(). test() -> start(5575), trap().