亿图图示和Erlang:一个套接字应用程序
发布日期:2021-06-29 17:24:21
浏览次数:2
分类:技术文章
本文共 8278 字,大约阅读时间需要 27 分钟。
-module(lib_chan).
-export([cast/2,start_server/0,start_server/1,connect/5,disconnect/1,rpc/2]). -import(lists,[map/2,member/2,foreach/2]). -import(lib_chan_mm,[send/2,close/1]).start_server()->
case os:getenv(“HOME”) of false-> exit({ebadEnv,“HOME”}); Home-> start_server(Home++"./erlang_config/lib_chan.conf") end. start_server(ConfigFile)-> io:format(“lib_chan starting:pn”,[ConfigFile]), case file:consult(ConfigFile) of {ok,ConfigData}-> io:format(“ConfigData=pn”,[ConfigData]), case check_terms(ConfigData) of []-> start_server1(ConfigData); Errors-> exit({eDaemonConfig,Errors}) end; {error,Why}-> exit({eDaemonConfig,Why}) end. check_terms(ConfigData)-> L=map(fun check_term/1,ConfigData), [X||{error,X}<-L]. check_term({port,P}) when is_integer§->ok; check_term({service,,password,,mfa,,,})->ok; check_term(X)->{error,{badTerm,X}}. start_server1(ConfigData)->register(lib_chan,spawn(fun()->start_server2(ConfigData) end)). start_server2(ConfigData)-> [Port]=[P||{port,P}<-ConfigData], start_port_server(Port,ConfigData). start_port_server(Port,ConfigData)-> lib_chan_cs:start_raw_server(Port, fun(Socket)-> start_port_instance(Socket,ConfigData) end, 100, 4). start_port_instance(Socket,ConfigData)-> S=self(), Controller=spawn_link(fun()->start_erl_port_server(S,ConfigData) end), lib_chan_mm:loop(Socket,Controller). start_erl_port_server(MM,ConfigData)-> receive {chan,MM,{startService,Mod,ArgC}}-> case get_service_definition(Mod,ConfigData) of {yes,Pwd,MFA}-> case Pwd of none -> send(MM,ack), really_start(MM,ArgC,MFA); -> do_authentication(Pwd,MM,ArgC,MFA) end; no-> io:format(“sending bad service~n”), send(MM,badService), close(MM) end; Any-> io:format("*** Erl port server got:~p pn",[MM,Any]), exit({protocolViolation,Any}) end. do_authentication(Pwd,MM,Argc,MFA)-> C=lib_chan_auth:make_chanllenge(), send(MM,{chanllenge,C}), receive {chan,MM,{response,R}}-> case lib_chan_auth:is_response_correct(C,R,Pwd) of true-> send(MM,ack), really_start(MM,Argc,MFA); false-> send(MM,authFail), close(MM) end end. really_start(MM,ArgC,{Mod,Func,ArgS})-> case(catch apply(Mod,Func,[MM,ArgC,ArgS])) of {‘EXIT’,normal}->true; {‘EXIT’,Why}-> io:format(“server error:pn”,[Why]); Why-> io:format(“server error should die with exit(normal) was:pn”,[Why]) end. get_service_definition(Mod,[{service,Mod,password,Pwd,mfa,M,F,A}|])-> {yes,Pwd,{M,F,A}}; get_service_definition(Name,[|T])-> get_service_definition(Name,T); get_service_definition(_,[])-> no. connect(Host,Port,Service,Secret,ArgC)-> S=self(), MM=spawn(fun()->connect(S,Host,Port) end), receive {MM,ok}-> case authenticate(MM,Service,Secret,ArgC) of ok->{ok,MM}; Error->Error end; {MM,Error}-> Error end. connect(Parent,Host,Port)-> case lib_chan_cs:start_newclient(Host,Port,4)of {ok,Socket}-> Parent!{self(),ok}, lib_chan_mm:loop(Socket,Parent); Error-> Parent!{self(),Error} end. authenticate(MM,Service,Secret,ArgC)-> send(MM,{startService,Service,ArgC}), receive {chan,MM,ack}-> ok; {chan,MM,{challenge,C}}-> R=lib_chan_auth:make_response(C,Secret), send(MM,{response,R}), receive {chan,MM,ack}-> ok; {chan,MM,authFail}-> wait_close(MM), {error,authFail}; Other-> {error,Other} end; {chan,MM,badService}-> wait_close(MM), {error,badService}; Other-> {error,Other} end. wait_close(MM)-> receive {chan_closed,MM}-> true after 5000-> io:format("**error lib_chan~n"), true end. disconnect(MM)->close(MM). rpc(MM,Q)-> send(MM,Q), receive {chan,MM,Reply}-> Reply end. cast(MM,Q)-> send(MM,Q).-module(mod_math).
-export([run/3]). run(MM,ArgC,ArgS)-> io:format(“mod_math:run starting ~n” “ArgC=~p ArgS=pn”,[ArgC,ArgS]), loop(MM). loop(MM)-> receive {chan,MM,{factorial,N}}-> MM!{send,fac(N)}, loop(MM); {chan,MM,{fibonacci,N}}-> MM!{send,fib(N)}, loop(MM); {chan_closed,MM}-> io:format(“mod_math stopping ~n”), exit(normal) end. fac(0)->1; fac(N)->N*fac(N-1). fib(1)->1; fib(2)->1; fib(N)->fib(N-1)+fib(N-2).-module(lib_chan_cs).
-export([start_raw_server/4,start_raw_client/3]). -export([stop/1]). -export([children/1]). start_raw_client(Host,Port,PacketLength)-> gen_tcp:connect(Host,Port,[binary,{active,true},{packet,PacketLength}]).start_raw_server(Port,Fun,Max,PacketLength)->
Name = port_name(Port), case whereis(Name) of undefined-> Self = self(), Pid = spawn_link(fun()-> cold_start(Self,Port,Fun,Max,PacketLength) end), receive {Pid,ok}-> register(Name,Pid), {ok,self()}; {Pid,Error}-> Error end; _Pid-> {error,already_started} end.stop(Port) when is_integer(Port)->
Name = port_name(Port), case whereis(Name) of undefined-> not_started; Pid-> exit(Pid,kill), (catch unregister(Name)), stopped end. children(Port) when is_integer(Port)-> port_name(Port)!{children,self()}, receive {session_server,Reply}->Reply end. port_name(Port) when is_integer(Port)-> list_to_atom(“portserver”++integer_to_list(Port)). cold_start(Master,Port,Fun,Max,PacketLength)-> process_flag(trap_exit,true), case gen_tcp:listen(Port,[binary, {nodelay,true}, {packet,PacketLength}, {reuseaddr,true}, {active,true}]) of {ok,Listen}-> Master!{self(),ok}, New=start_accept(Listen,Fun), socket_loop(Listen,New,[],Fun,Max); Error-> Master!{self(),Error} end. socket_loop(Listen,New,Active,Fun,Max)-> receive {istarted,New}-> Active1=[New|Active], possibly_start_another(false,Listen,Active1,Fun,Max); {‘EXIT’,New,_Why}-> possibly_start_another(false,Listen,Active,Fun,Max); {‘EXIT’,Pid,_Why}-> Active1=lists:delete(Pid,Active), possibly_start_another(New,Listen,Active1,Fun,Max); {children,From}-> From!{session_server,Active}, socket_loop(Listen,New,Active,Fun,Max); _Other-> socket_loop(Listen,New,Active,Fun,Max) end. possibly_start_another(New,Listen,Active,Fun,Max) when is_pid(New)-> socket_loop(Listen,New,Active,Fun,Max); possibly_start_another(false,Listen,Active,Fun,Max)-> case length(Active) of N when N < Max -> New = start_accept(Listen,Fun), socket_loop(Listen,New,Active,Fun,Max); _-> socket_loop(Listen,false,Active,Fun,Max) end. start_accept(Listen,Fun)-> S=self(), spawn_link(fun()->start_child(S,Listen,Fun)end). start_child(Parent,Listen,Fun)-> case gen_tcp:accept(Listen) of {ok,Socket}-> Parent!{istarted,self()}, inet:setopts(Socket,[{packet,4}, binary,{nodelay,true}, {active,true}]), process_flag(trap_exit,true), case(catch Fun(Socket)) of {‘EXIT’,normal}-> true; {‘EXIT’,Why}-> io:format(“port process dies with exit:pn”,[Why]), true; _-> true end end. configur1.txt如下 {port,2233}. {service,math,password,“qwerty”,mfa,mod_math,run,[]}. -module(lib_chan_mm). -export([loop/2,send/2,close/1,controller/2,set_trace/2,trace_with_tag/2]). send(Pid,Term)->Pid!{send,Term}. close(Pid)->Pid!close. controller(Pid,Pid1)->Pid!{setController,Pid1}. set_trace(Pid,X)->Pid!{trace,X}. trace_with_tag(Pid,Tag)-> set_trace(Pid,{true,fun(Msg)->io:format(“MM:~p pn”,[Tag,Msg]) end}).loop(Socket,Pid)->
process_flag(trap_exit,true), loop1(Socket,Pid,false). loop1(Socket,Pid,Trace)-> receive {tcp,Socket,Bin}-> Term=binary_to_term(Bin), trace_it(Trace,{socketReceived,Term}), Pid!{chan,self(),Term}, loop1(Socket,Pid,Trace); {tcp_closed,Socket}-> trace_it(Trace,socketClosed), Pid!{chan_closed,self()}; {‘EXIT’,Pid,Why}-> trace_it(Trace,{controllingProcessExit,Why}), gen_tcp:close(Socket); {setController,Pid1}-> trace_it(Trace,{changedController,Pid}), loop1(Socket,Pid1,Trace); {trace,Trace1}-> trace_it(Trace,{setTrace,Trace1}), loop1(Socket,Pid,Trace1); close-> trace_it(Trace,closedByClient), gen_tcp:close(Socket); {send,Term}-> trace_it(Trace,{sendingMessage,Term}), gen_tcp:send(Socket,term_to_binary(Term)), loop1(Socket,Pid,Trace); UUg-> io:format(“lib_chan_mm:protocol error:pn”,[UUg]), loop1(Socket,Pid,Trace) end. trace_it(false,_)->void; trace_it({trye,F},M)->F(M).-module(lib_chan_auth).
-export([make_challenge/0,make_response/2,is_response_correct/3]). make_challenge()-> random_string(25). make_response(Challenge,Secret)-> lib_md5:string(Challenge++Secret). is_response_correct(Challenge,Response,Secret)-> case lib_md5:string(Challenge++Secret) of Response->true; _ ->false end. random_string(N)->random_seed(),random_string(N,[]). random_string(0,D)->D; random_string(N,D)-> random_string(N-1,[random:uniform(26)-1+$a|D]). random_seed()-> { ,,X}=erlang:now(), {H,M,S}=time(), H1=HX rem 32767, M1=MX rem 32767, S1=S*X rem 32767, put(random_seed,{H1,M1,S1}). Erlang程序设计(第2版)------【瑞典】Joe Armstrong著 牛化成译转载地址:https://blog.csdn.net/m0_38127487/article/details/113772321 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
表示我来过!
[***.240.166.169]2024年04月26日 20时55分53秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
CSS3 帧动画(Sprite,直译叫雪碧图)
2019-04-29
Java 父线程与子线程相互通信的方法
2019-04-29
Redis 六种淘汰策略和三种删除策略
2019-04-29
Java LinkedHashMap
2019-04-29
JPA 多线程同时对一条数据进行Update的问题
2019-04-29
Java 高性能队列Disruptor
2019-04-29
Java 读写锁
2019-04-29
SpringBoot @Scheduled 执行两次的问题
2019-04-29
tomcat配置JVM
2019-04-29
面试笔试易错知识点Java篇八
2019-04-29
弹性事务框架ETF4J——面向Java微服务的交易最终一致性解决方案
2019-04-29
【Scala 教程】Scala 集合类型
2019-04-29
JAVA 线程同步机制 synchronized
2019-04-29
MySQL 安装教程(无脑版)
2019-04-29
IDEA 怎么删除一个Module
2019-04-29
走进数据科学:最好是通过比网课更好的方法
2019-04-29
2020年开发运维工具清单:选择开发运维工具堆栈吧
2019-04-29
【技术分享】使用AES加密技术保障数据安全
2019-04-29
数据可视化工具:Matplotlib绘图
2019-04-29
闺蜜看我用Python画了一幅樱花图,吵着要我给他介绍程序员小哥哥
2019-04-29