锘??xml version="1.0" encoding="utf-8" standalone="yes"?> ejabberd寮鍙戝拰閮ㄧ講 (閲戝簡鐨勪笓鏍?2016.10) 鎼緩浜嗚嚜宸辯殑ejabberd闆嗙兢錛岀劧鍚庡皯閲忔洿鏀規簮鐮侊紝瀹炵幇瀹氬埗鐨刋MPP鏈嶅姟鍣ㄣ?/p> 浠巊ithub fork ejabberd 搴擄紝瀹氫負 master 鍒嗘敮璺熻釜鍘熷搴?master 鍒嗘敮錛岀増鏈崌綰ф椂浠庡師搴撳悎騫朵竴嬈°?/p> 浠?6.09鐗堟湰鍒嗕竴涓?dev 鍒嗘敮錛岃嚜宸辯殑浠g爜灝卞湪榪欎釜 dev 鍒嗘敮涓婂啓銆?/p> 鏈嶅姟鍣ㄤ粠婧愮爜緙栬瘧瀹夎銆?/p> 浠g爜鏇存敼鍚庯紝make install, 鐒跺悗 ejabberd restart, 鎴栬?ejabberd update all. 濡傛灉鏈夐厤緗洿鏀癸紝鍒欒繕瑕佹洿鏀?/etc/ejabberd/ejabberd.yml. 鏈潵涓誨簱鐗堟湰鍗囩駭鍚庯紝鍙噸鏂板紑涓猟ev2鍒嗘敮錛屽皢dev鐨勬洿鏀瑰悎騫跺埌dev2. 璺敱娑堟伅鍦?handle_info 涓鐞嗭紝瀹冨皢鏉ユ簮鍜岀洰鐨勮皟鎹竴涓嬶紝鐒跺悗璋冪敤 route() 鍙戦佸師鍖呫?/p> 渚嬪錛屾柊寤?src/tttt/, 騫舵坊鍔?dd_util.erl 鏂囦歡銆?br /> 緇撴灉鏄?涓泦緹ゅ彲浠ユ湁浜ら泦銆?/p>
(閲戝簡鐨勪笓鏍?2016.11)
ejabberd鑱婂ぉ鏈嶅姟鍣ㄩ粯璁や細闄愬埗鍚屼竴IP娉ㄥ唽甯愬彿欏婚棿闅?00s銆?
鍦ㄦ父鎴忎腑闇瑕佷負姣忎釜瑙掕壊娉ㄥ唽涓涓亰澶╁笎鍙鳳紝涓嶅簲璇ユ湁姝ら檺鍒躲?
鍙互鏇存敼鏈嶅姟鍣ㄤ唬鐮侊紝涓烘父鎴忔湇鍔″櫒鍏嶉櫎榪欎竴娉ㄥ唽闂撮殧鏃墮棿銆?
鍋囪娓告垙鏈嶇敤涓撶敤鐨勫笎鍙風櫥褰昬jabberd, 鐒跺悗涓鴻繖縐嶅笎鍙峰厤闄ゆ敞鍐岄檺鍒躲?br />
鍦╡jabberd.yml閰嶇疆璁塊棶鎺у埗鍒楄〃(ACL)涓坊鍔?game_master錛?br />
acl:
game_master:
user:
- "game_master_1@localhost"
- "game_master_2@localhost"
game_master 甯愬彿棰勫厛鍒涘緩錛屼緵娓告垙鏈嶅姟鍣ㄧ櫥褰昬jabberd.
mod_register鐨勯厤緗腑錛屽皢 "access_from: deny" 鏀逛負 "access_from: all".
"access_from: deny" 琛ㄧず浠諱綍鐢ㄦ埛閮戒笉鑳芥敞鍐屽笎鍙鳳紝鍙兘鏄櫥褰曞墠娉ㄥ唽銆?
"access_from: all" 琛ㄧず鐧誨綍鐢ㄦ埛涔熻兘娉ㄥ唽甯愬彿銆?
榪欐牱game_master甯愬彿鍏堢櫥褰曪紝鐒跺悗灝卞彲浠ユ敞鍐屾柊甯愬彿浜嗐?
娣誨姞 access_from_without_time_limit錛屽厑璁竒ame_master鏃犳敞鍐岄檺鍒躲?br />
mod_register:
access_from: all
access: register
## Allow some user register accounts without registration_timeout limit.
access_from_without_time_limit:
- allow: game_master
瀹為檯涓婁篃鍙互榪欐牱鐩存帴閰嶇疆錛?
access_from_without_time_limit:
- allow:
- user: game_master_1@localhost
- user: game_master_2@localhost
閰嶇疆鎴?acl 鐨勫ソ澶勬槸錛屽彲浠ョ敤
ejabberdctl reload_config
閲嶆柊鍔犺澆 acl, 鑰屾ā鍧楅厤緗儴鍒嗘棤娉曢噸鏂板姞杞姐?br />
acl 閰嶇疆榪樺彲浠ュ湪 http admin 鐣岄潰鏇存敼銆?br />
浠g爜闇紼嶅姞鏇存敼錛屼慨鏀筸od_register.erl.
try_register/5 娣誨姞 From 鍙傛暟鏀逛負 try_register/6
try_register(User, Server, Password, From, SourceRaw, Lang)
騫跺皢鍏朵腑
case check_timeout(Source) of
鏀規垚
CheckTimeout = case check_from_without_time_limit(From, Server) of
allow -> true;
_ -> check_timeout(Source)
end,
case CheckTimeout of
鍗沖鏋淔rom鏄痝m甯愬彿鏃訛紝CheckTimeout鐩存帴閫氳繃錛屼笉鍐嶅垽鏂?00s鐨勯棿闅斻?br />
check_from_without_time_limit/2 浠跨収check_from/2錛岃繖鏍峰疄鐜幫細
check_from_without_time_limit(JID, Server) ->
Access = gen_mod:get_module_opt(Server, ?MODULE, access_from_without_time_limit,
fun(A) -> A end,
none),
acl:match_rule(Server, Access, JID).
娣誨姞錛?br />
mod_opt_type(access_from_without_time_limit) ->
fun acl:access_rules_validator/1;
...
mod_opt_type(_) ->
[..., access_from_without_time_limit, ...].
]]>
]]>
(閲戝簡鐨勪笓鏍?2016.8)
鎸夊紑鍙戝叆闂ㄧ殑璇存槑錛宮od_echo鏄渶綆鍗曠殑妯″潡涔嬩竴銆?br />https://docs.ejabberd.im/developer/
褰撶劧 mod_hello_world 鍙湁寮濮嬪拰緇撴潫鏃ュ織錛屾病鏈夊疄闄呭姛鑳斤紝姣?mod_echo 鏇寸畝鍗曘?br />
閰嶇疆璇存槑涓瀹氳鐪嬶紝鍥犱負鍏朵腑鏈夋ā鍧楀姛鑳界殑綆浠嬶細
https://docs.ejabberd.im/admin/guide/configuration/#modecho
娌$湅鍔熻兘綆浠嬶紝鐩存帴鐪嬩唬鐮侊紝緇撴灉琚?do_client_version/3 緇欏紩鍏ヤ簡姝ч斻?br />
echo妯″潡瀹炵幇浜唀cho鍔熻兘錛屽悜鐗瑰畾鍩熷悕鐨勭敤鎴峰彂閫佽亰澶╂秷鎭紝浼氬師鏍瘋繑鍥炪?br />
嫻嬭瘯鍥撅細
echo鍩熷悕鏄彲閰嶇疆鐨勶細
modules:
mod_echo:
host: "echo_x.mydomain"
緙虹渷涓?"echo.@HOST@", 鍏朵腑@HOST@浼氳鏇挎崲鎴愭湇鍔″櫒鍩熷悕銆?br />
浠g爜涓殑 do_client_version/3 婕旂ず浜?route + receive 鍙戦佸茍鏀跺彇搴旂瓟錛?br />浣嗘槸涓巈cho鍔熻兘鏃犲叧錛屽彲浠ュ拷鐣ヨ鍑芥暟銆?br />
echo鍔熻兘鏄?register_route/2 瀹屾垚鐨勶紝
ejabberd_route:register_route(MyHost, Host)
琛ㄧず浠嶩ost鍒癕yHost鐨勬秷鎭渶瑕佹湰妯″潡鏉ヨ礬鐢便?br />Host鏄湇鍔″櫒鍚嶏紝MyHost鏄厤緗殑mod_echo.host.
鍙互鏌ョ湅route琛細
(ejabberd@localhost)1> ets:tab2list(route).
[{route,<<"pubsub.zt-2203857">>,<<"zt-2203857">>,<0.5500.0>,
undefined},
{route,<<"echox.zt-2203857">>,<<"zt-2203857">>,<0.5492.0>,
undefined},
{route,<<"conference.zt-2203857">>,<<"zt-2203857">>,
<0.5445.0>,undefined},
{route,<<"zt-2203857">>,<<"zt-2203857">>,<0.5406.0>,
{apply,ejabberd_local,route}}]
(ejabberd@localhost)2>
]]>
(閲戝簡鐨勪笓鏍?2016.8)
鍙傝冿細
https://docs.ejabberd.im/developer/modules/
榪愯
ejabberdctl modules_update_specs
浼氬垱寤?C:\.ejabberd-modules\source\, 鍏朵腑涓嬭澆浜?br />https://github.com/processone/ejabberd-contrib
鍙互鍚屾牱鍦╯ources鐩綍涓嬪垱寤鴻嚜宸辯殑妯″潡浠g爜錛屽錛?br />$HOME/.ejabberd-modules/sources/mod_mysupermodule/
榪愯
ejabberdctl module_check mod_mysupermodule
鍙鏌ヨ鐩綍鏄惁絎﹀悎妯″潡瑙勫畾(policy), 濡?
C:\Program Files\ejabberd-16.08\bin>ejabberdctl module_check mod_mysupermodule
Error: [{missing,"COPYING"},
{missing,"README.txt"},
{missing,"src (Erlang) or lib (Elixir) sources directory"},
{missing_meta,url},
{missing_meta,home},
{missing_meta,summary},
{missing_meta,author}]
闇瑕丆OPYING鍜孯EADME.txt鏂囦歡錛宻rc鐩綍銆?br />榪樻湁 mod_mysupermodule.spec 鏂囦歡錛屼豢鐓у叾浠栨ā鍧楃殑渚嬪瓙鍐欏氨琛屼簡錛屼緥濡傦細
url: "http://localhost"
summary: "My super m"
home: "http://localhost"
author: "Jin Qing"
鍙互鏌ョ湅鍒板彲鐢ㄦā鍧楋細
C:\Program Files\ejabberd-16.08\bin>ejabberdctl modules_available
...
mod_mysupermodule My super m
...
鍗充嬌娌℃湁浠諱綍婧愭枃浠訛紝涔熷彲浠odule_install.
C:\Program Files\ejabberd-16.08\bin>ejabberdctl module_install mod_mysupermodule
ok
鏇存敼 src\mod_mysupermodule.erl 鍚庯紝鏃犳硶鍐嶆瀹夎錛?br />C:\Program Files\ejabberd-16.08\bin>ejabberdctl module_install mod_mysupermodule
Error: conflict
濂藉儚鍙互鐢?module_upgrade錛?br />C:\Program Files\ejabberd-16.08\bin>ejabberdctl module_upgrade mod_mysupermodule
src/mod_mysupermodule.erl:4: Warning: undefined callback function depends/2 (beh
aviour 'gen_mod')
src/mod_mysupermodule.erl:4: Warning: undefined callback function mod_opt_type/1
(behaviour 'gen_mod')
ok
C:\Program Files\ejabberd-16.08\bin>
鎸夋枃妗h鏄庯紝闇瑕佹墜宸ヤ慨鏀?
C:\Users\jinqing\AppData\Roaming\ejabberd\conf\ejabberd.yml
瀹為檯嫻嬭瘯閰嶇疆涓嶉渶瑕佹墜宸ヤ慨鏀癸紝鍙渶瑕佸垱寤?
C:\.ejabberd-modules\sources\mod_mysupermodule\conf\mod_mysupermodule.yml
modules:
mod_mysupermodule: {}
鎸夋枃浠惰鏄庯紝闇瑕佹墜宸ュ鍒剁紪璇戠敓鎴愮殑
C:\.ejabberd-modules\mod_mysupermodule
鍒?br />C:\Program Files\ejabberd-16.08\lib\mod_mysupermodule
鏌ョ湅浠g爜錛屽簲璇ユ槸浼氳嚜鍔ㄦ坊鍔犱唬鐮佺洰褰?
C:\.ejabberd-modules\mod_mysupermodule\ebin
瀹為檯鍙戠幇
options: []
error: undef
[{mod_mysupermodule,start,[<<"zt-2203857">>,[]],[]},
{gen_mod,start_module,3,[{file,"src/gen_mod.erl"},{line,154}]},
{lists,foreach,2,[{file,"lists.erl"},{line,1337}]},
{ejabberd_app,start,2,[{file,"src/ejabberd_app.erl"},{line,76}]},
{application_master,start_it_old,4,
[{file,"application_master.erl"},{line,273}]}]
2016-08-24 16:27:54.016 [critical] <0.550.0>@gen_mod:maybe_halt_ejabberd:170 ejabberd initialization was aborted because a module start failed.
闇濡備笅鏇存敼ext_mod.erl:
modules_dir() ->
DefaultDir = filename:join(getenv("HOME"), ".ejabberd-modules"),
- getenv("CONTRIB_MODULES_PATH", DefaultDir).
+ getenv("CONTRIB_MODULES_PATH", filename:absname(DefaultDir)).
涓嶇劧add_patha/1浼氬け璐ワ細
code:add_patha("/.ejabberd-modules/mod_mysupermodule/ebin").
鐒跺悗閲嶅惎(鍙兘涓嶉渶瑕?錛?br />C:\Program Files\ejabberd-16.08\bin>ejabberdctl restart
]]>
(閲戝簡鐨勪笓鏍?2016.8)
鐢╮ebar緙栬瘧ejabberd婧愮爜錛岀劧鍚庡鍒剁紪璇戞墍寰梑eam鏂囦歡鍒癳jabberd瀹夎鐩綍錛?br />璋冪敤ejabberdctl鐑洿鏂般?br />
call rebar compile skip_deps=true
REM Need write right to ejabberd dir.
copy ebin\*.beam "C:\Program Files\ejabberd-16.08\lib\ejabberd-16.08\ebin\"
echo Update ejabberd.
call "C:\Program Files\ejabberd-16.08\bin\ejabberdctl.cmd" update all
]]>
(閲戝簡鐨勪笓鏍?2016.8)
浠?鍙版満鍣ㄦ惌寤轟竴涓猠jabberd闆嗙兢銆?br />
2鍙版満鍣ㄩ兘鏄緗戜竴鍧楃綉鍗★紝鍐呯綉鍙︿竴鍧楃綉鍗°?br />鏂板緩涓涓煙鍚嶏紝娣誨姞2鍙版満鍣ㄧ殑澶栫綉IP.
鍒嗗埆鐢ㄦ簮鐮佸畨瑁卐jabberd錛屽彲浠ュ崟鏈鴻繍琛屻?br />
澶嶅埗 .erlang.cookie, 浣?鍙版満鍣ㄩ兘鍚屻?br />
鏇存敼 /sbin/ejabberdctl
ERLANG_NODE=ejabberd@localhost 鏀逛負
ERLANG_NODE=ejabberd@192.168.7.160
鍗砽ocalhost鏀逛負鍐呯綉IP
鍚姩澶辮觸錛?br />[error] <0.63.0>@ejabberd_app:start_elixir_application:245 Elixir application not started.
[critical] <0.63.0>@ejabberd_app:db_init:127 Node name mismatch: I'm [ejabberd@192.168.7.160], the database is owned by [ejabberd@localhost]
[critical] <0.63.0>@ejabberd_app:db_init:129 Either set ERLANG_NODE in ejabberdctl.cfg or change node name in Mnesia
[error] <0.62.0> CRASH REPORT Process <0.62.0> with 0 neighbours exited with reason: node_name_mismatch in ejabberd_app:db_init/0 line 131 in application_master:init/4 line 134
[info] <0.31.0> Application ejabberd exited with reason: node_name_mismatch in ejabberd_app:db_init/0 line 131
鍥犱負Mnesia搴撲腑浣跨敤浜嗘棫鐨勮妭鐐瑰悕
[root@host-192-168-7-160 ~]# ejabberdctl mnesia
[{auto_repair,true},
{backup_module,mnesia_backup},
{db_nodes,[ejabberd@localhost]},
鍒犻櫎鏃у簱銆?br />
[root@host-192-168-7-160 ejabberd]# pwd
/var/lib/ejabberd
[root@host-192-168-7-160 ejabberd]# ls
caps_features.DAT muc_registered.DCD pubsub_index.DCD sr_group.DCD
DECISION_TAB.LOG muc_room.DCD pubsub_item.DAT sr_user.DCD
irc_custom.DCD oauth_token.DCD pubsub_node.DCD vcard.DAT
last_activity.DCD offline_msg.DAT pubsub_state.DCD vcard_search.DCD
LATEST.LOG passwd.DCD roster.DCD
motd.DCD privacy.DCD roster_version.DCD
motd_users.DCD private_storage.DAT schema.DAT
[root@host-192-168-7-160 ejabberd]# rm -f *
[root@host-192-168-7-160 ejabberd]#
鏇存敼 ejabberd.yml:
hosts:
- "my_domain.cn"
# - "localhost"
鍏堝惎鍔?ejabberd@192.168.7.160錛岀劧鍚庡惎鍔ㄥ彟涓鑺傜偣錛屽茍璁╄鑺傜偣鍔犲叆闆嗙兢錛?br />ejabberdctl join_cluster 'ejabberd@192.168.7.160'
[root@host-192-168-7-159 ejabberd]# ejabberdctl list_cluster
'ejabberd@192.168.7.160'
'ejabberd@192.168.7.159'
[root@host-192-168-7-159 ejabberd]#
]]>
(閲戝簡鐨勪笓鏍?
瀹夎 erlang OTP. 娣誨姞璺緞鍒?PATH, 浣?erl 鍙互榪愯銆?br />
git clone ejabberd
瀹夎 rebar:
git clone git@github.com:rebar/rebar.git
E:\Git\rebar>bootstrap.bat
escript: exception error: no match of right hand side value "鎵句笉鍒?E:\\Git\\reb
ar\\ebin\\rebar.beam\r\n"
鍏堝垱寤?ebin\rebar.beam銆傝錛歨ttps://github.com/rebar/rebar/issues/613
澶嶅埗鐢熸垚鐨?rebar.cmd 鍒?ejabberd 鐩綍銆傚叾瀹炲氨鍑犺浠g爜錛?br />setlocal
set rebarscript=%~f0
escript.exe "%rebarscript:.cmd=%" %*
rebar.cmd get-deps
Cloning into 'p1_xmlrpc'...
Pulling luerl from {git,"https://github.com/rvirding/luerl",{tag,"v0.2"}}
Cloning into 'luerl'...
'sh' 涓嶆槸鍐呴儴鎴栧閮ㄥ懡浠わ紝涔熶笉鏄彲榪愯鐨勭▼搴?br />鎴栨壒澶勭悊鏂囦歡銆?br />ERROR: Command ['get-deps'] failed!
鏇存敼 rebar.config.script錛屽幓闄h, 鏀逛負
{'get-deps', ""}
灝?ejabberd.app.src.in 澶嶅埗涓?ejabberd.app.src錛屾洿鏀瑰叾涓殑鍙橀噺錛?br />E:\Git\ejabberd>rebar compile skip_deps=true
==> rel (compile)
==> ejabberd (compile)
deps 娌℃湁緙栬瘧錛屽彲浠ヤ嬌鐢ㄥ畨瑁呭寘銆?br />鍙渶鏇挎崲鏈夋洿鏂扮殑beam鏂囦歡鍒板畨瑁呯洰褰曘?br />
琛ュ厖錛?br />
==> rel (compile)
==> ejabberd_jinq0123 (compile)
Compiled asn1/XmppAddr.asn1
Compiled src/eldap_filter_yecc.yrl
e:/Git/ejabberd_jinq0123/src/ejabberd_config.erl:none: undefined parse transform
'lager_transform'
ERROR: compile failed while processing E:/Git/ejabberd_jinq0123: rebar_abort
欏誨厛鐢?rebar compile 緙栬瘧 lager. 鍏朵粬鏃犳硶緙栬瘧鐨勫彲蹇界暐錛岀劧鍚庡啀
]]>
(閲戝簡鐨勪笓鏍?
Erlang鐨凱ort鎺ュ彛浣跨敤cin, cout涓庡閮≒ort榪涚▼閫氫俊銆?br />
涓鑸琽pen_port()鐢╞inary妯″紡鎵撳紑銆?br />
Port = open_port({spawn, PortExe},
[{packet, 4}, binary, use_stdio]),
姝ゆ椂欏誨皬蹇働ort榪涚▼鍦╓indows涓婅緭鍑?\n 鍓嶄細鑷姩娣誨姞 \r銆?br />PortExe鍙戦?
<<10,11,84,101,115,116,77,101,115,115,97,103,101,18,10,10,8,98,98,98,98,98,98,98,98>>
Erlang鎺ユ敹鎴愪負錛?nbsp;
<<13,10,11,84,101,115,116,77,101,115,115,97,103,101,18,13,10,13,10,8,98,98,98,98,98>>
闇瑕佸皢Port榪涚▼鐨剆tdin, stdout璁句負浜岃繘鍒舵ā寮忥細
void set_binary_mode()
{
#if defined(WIN32)
int result;
result = _setmode(_fileno(stdin), _O_BINARY);
if (-1 == result)
{
perror("set mode");
exit(1);
}
result = _setmode(_fileno(stdout), _O_BINARY);
if (-1 == result)
{
perror("set mode");
exit(1);
}
#endif
}
]]>
(閲戝簡鐨勪笓鏍?
Erlang寮鍙戜嬌鐢↖DEA IDE鍙互璁劇疆澶栭儴宸ュ叿Dialyzer, 鐒跺悗灝卞彲浠ョ洿鎺?br />Tools->External Tools -> dialyzer 璋冪敤榪涜浠g爜鍒嗘瀽銆?br />
閰嶇疆鏂規硶涓猴細
File | Settings | Tools | External Tools
闇瑕佹坊鍔犲弬鏁?-r $ProjectFileDir$/ebin
杈撳嚭紺轟緥錛?br />dialyzer -r D:\ServerSix/ebin
Checking whether the PLT C:\dailyzer_plt is up-to-date... yes
Proceeding with analysis...
b_pb.erl:81: Guard test is_list(Records::tuple()) can never succeed
b_pb.erl:85: Guard test is_list(Records::tuple()) can never succeed
b_pb.erl:90: Guard test is_list(Records::tuple()) can never succeed
鍥犱負dialyzer杈撳嚭鏈夎澶氳鍛婏紝鎴戜細灝嗚緭鍑哄瓨涓?dialyzer_output.txt, 鍔犲叆SVN錛?br />姣忔鍒嗘瀽涓庝笂嬈″垎鏋愪粎闇鏌ョ湅宸紓銆?/div>
]]>
(閲戝簡鐨勪笓鏍?
sample/a_hello.erl 榪炴帴鏈満鏇存敼涓鴻繛鎺ュ眬鍩熺綉鍐呯殑MySql鏈嶅姟鍣細
emysql:add_pool(hello_pool, [{size,1},
{host, "192.168.1.2"},
...
緙栬瘧榪愯鏃朵細鍑虹幇瓚呮椂閫鍑猴細
D:\...\deps\emysql\samples>erl -pa ../ebin -s a_hello run -s init stop -noshell
add_pool...{"init terminating in do_boot",{{nocatch,{failed_to_recv_packet_header,timeout}},[{init,start_it,1,[{file,"init.erl"},{line,1062}]},{init,start_em,1,[{file,"init.erl"},{line,1034}]}]}}
Crash dump is being written to: erl_crash.dump...done
init terminating in do_boot ()
璁劇疆 default_timeout 鍙傛暟涓?10s 灝卞彲浠ユ垚鍔燂細
D:\...\deps\emysql\samples>erl -pa ../ebin -s a_hello run -s init
stop -noshell -emysql default_timeout 10000
鏌ョ湅浠g爜錛岀己鐪佺殑 default_timeout 涓?s銆?br />褰揗ySql娌℃湁skip-name-resolve鏃訛紝榪炴帴MySql闇瑕佽繎10縐掓墠鑳借繛涓婏紝
鎵浠ュ緢瀹規槗鍑虹幇瓚呮椂閿欒銆?br />
宸叉彁浜ら棶棰橈細
https://github.com/Eonblast/Emysql/issues/174
]]>
(閲戝簡鐨勪笓鏍?
鍦╝pplication琛屼負妯″潡鐨剆tart()涓惎鍔╞son搴旂敤錛屽湪stop()涓仠姝son錛?br />緇撴灉application:stop(bson)浼氭閿併?br />
-module(my_app).
-behaviour(application).
%% Application callbacks
-export([start/2, stop/1]).
%% ===================================================================
%% Application callbacks
%% ===================================================================
start(_StartType, _StartArgs) ->
ok = application:start(bson),
{ok, Pid} = my_sup:start_link(),
{ok, Pid}.
stop(_State) ->
application:stop(bson),
ok.
鍙傝?How to stop third-party Erlang applications
http://stackoverflow.com/questions/2305511/how-to-stop-third-party-erlang-applications
鎵嶆槑鐧絪top()鏄洖璋冿紝鍦ㄥ洖璋冧腑璇曞浘鍋滄鍏朵粬搴旂敤灝變細姝婚攣銆?br />stop()鏄簲鐢ㄦ帶鍒跺櫒鍥炶皟鐨勶紝搴旂敤鎺у埗鍣ㄥ湪絳夊緟鍥炶皟榪斿洖鏃訛紝鏃犳硶鍝嶅簲application:stop()璇鋒眰錛屾墍浠ユ閿佷簡銆?br />
]]>
錛堥噾搴嗙殑涓撴爮錛?br />
Erlang騫惰鏈嶅姟鍣ㄤ負姣忎釜Tcp榪炴帴鍒涘緩瀵瑰簲鐨勮繛鎺ヨ繘紼嬶紝澶勭悊瀹㈡埛绔暟鎹?br />
鍙傝?Erlang紼嬪簭璁捐錛堢2鐗堬級
17.1.3 欏哄簭鍜屽茍琛屾湇鍔″櫒
騫惰鏈嶅姟鍣ㄧ殑璇紿嶆槸錛氭瘡褰揼en_tcp:accept鏀跺埌涓涓柊榪炴帴鏃跺氨绔嬪嵆鍒嗚涓涓柊榪涚▼銆?br />涓烘瘡涓柊濂楁帴瀛楄繛鎺ュ垱寤轟竴涓茍琛岃繘紼嬨?br />
-module(gs_svr).
-author("jinqing").
-behaviour(gen_server).
%% API
-export([start_link/0]).
init([]) ->
gs_listener:start_parallel(),
{ok, #{}}.
gs_svr(GameServer gen_server)鍚姩Tcp鐩戝惉錛屽茍緇存姢榪炴帴錛屽榪炴帴璁℃暟錛屽彂閫佸箍鎾?br />
start_parallel()鍒涘緩鐩戝惉绔彛錛岀劧鍚庡垱寤鴻繛鎺ヨ繘紼嬨?br />
start_parallel() ->
Port = server_csv:get_my_port(),
lager:info("Starting game server on port ~p...", [Port]),
{ok, ListenSocket} = gen_tcp:listen(Port,
[binary, {packet, 4},
{packet_size, 256 * 1024}, % limit packet size
{reuseaddr, true},
{nodelay, true},
{backlog, 999999},
{active, once}]),
connection:spawn_connection(ListenSocket).
spawn_connection()鍒涘緩榪炴帴榪涚▼銆傛瘡鎺ュ彈涓涓繛鎺ュ氨鍐嶅垱寤轟竴涓柊鐨勮繛鎺ヨ繘紼嬨?br />
-module(connection).
-author("jinqing").
%% API
-export([spawn_connection/1]).
-export([parallel_connect/1, loop/2]).
-spec spawn_connection(ListenSocket :: gen_tcp:socket()) -> pid().
spawn_connection(ListenSocket) ->
spawn(fun() -> ?MODULE:parallel_connect(ListenSocket) end).
-spec parallel_connect(ListenSocket :: gen_tcp:socket()) -> ok.
parallel_connect(ListenSocket) ->
{ok, Socket} = gen_tcp:accept(ListenSocket),
spawn_connection(ListenSocket),
gs_svr:cast_connection_new(self()),
ConnStat = conn_stat:new(),
erlang:send_after(1000, self(), timer_sec),
try ?MODULE:loop(Socket, ConnStat)
catch
Type:E -> lager:error("loop() ~p:~p. ~p",
[Type, E, erlang:get_stacktrace()])
end,
gs_svr:cast_connection_ended(self()),
ok.
-spec loop(Socket :: gen_tcp:socket(), ConnStat :: conn_stat:conn_stat()) -> any().
loop(Socket, ConnStat) ->
receive
{tcp, Socket, Bin} ->
NewConnStat = rpc_handler:handle_bin(Socket, Bin, ConnStat),
inet:setopts(Socket, [{active, once}]),
NewConnStat2 = cutil_dos_checker:on_data(size(Bin), NewConnStat),
?MODULE:loop(Socket, NewConnStat2#{idle_sec=>0});
{tcp_closed, Socket} ->
save_on_end(ConnStat);
{tcp_error, Socket, Reason} ->
save_on_end(ConnStat);
{gs_to_connection, Msg} ->
NewConnStat = handle_gs_msg(Msg, Socket, ConnStat),
?MODULE:loop(Socket, NewConnStat);
timer_sec ->
case conn_timer:timer_sec(ConnStat) of
{ok, NewConnStat} ->
erlang:send_after(1000, self(), timer_sec),
?MODULE:loop(Socket, NewConnStat);
end;
Other ->
lager:error("Unknown msg: ~p", [Other]),
?MODULE:loop(Socket, ConnStat)
end. % This is tail-recursive.
緙虹偣鏄繛鎺ヨ繘紼嬫病鏈夊姞鍏ョ洃鎺ф爲銆俫s_svr鍑洪敊閲嶅惎鏃訛紝榪炴帴榪涚▼connection搴旇鏂紑騫墮鍑恒?/div>
]]>
Residence module
The module where a process has its tail-recursive loop function(s).
If the tail-recursive loop functions are implemented in several modules,
all those modules are residence modules for the process.
Functional module
A module which is not a residence module for any process.
Note that for a process implemented using an OTP behaviour,
the behaviour module is the residence module for that process.
The callback module is a functional module.
甯擱┗妯″潡鏄寚loop()鍑芥暟鎵鍦ㄦā鍧楋紝鍏朵粬妯″潡涓哄姛鑳芥ā鍧椼?br />瀵逛簬OTP琛屼負錛岃涓烘ā鍧楁槸甯擱┗妯″潡錛屽洖璋冩ā鍧楁槸鍔熻兘妯″潡銆?br />
琛屼負妯″潡宸茬敱OTP瀹炵幇銆?br />
]]>
%%%-------------------------------------------------------------------
%%% @author jinqing
%%% @copyright (C) 2015, <COMPANY>
%%% @doc 閫掑綊鍒椾婦鐩綍涓嬬殑鎵鏈夋枃浠躲?/span>
%%%
%%% @end
%%% Created : 29. 鍥涙湀 2015 16:02
%%%-------------------------------------------------------------------
-module(dir_util).
-author("jinqing").
%% API
-export([list_dir_recursive/1]).
%% 鍒椾婦鏁版嵁琛ㄧ洰褰曚笅鐨勬墍鏈夋枃浠訛紝鍖呮嫭瀛愮洰褰曚腑鐨勩?/span>
%% 榪斿洖鏂囦歡鍚嶉兘甯︽湁 Dir 鍓嶇紑錛?/span>
%% 濡傦細["Dir/a.dat", "Dir/b/b.dat"]
-spec(list_dir_recursive(Dir :: string()) -> [string()]).
list_dir_recursive(Dir) when is_list(Dir) ->
list_dirs_r([Dir], []).
%%%===================================================================
%%% Internal functions
%%%===================================================================
%% List recursively all files in dir/file list.
%% Returns (files ++ Acc).
list_dirs_r([] = _Files, Acc) ->
Acc;
list_dirs_r([File | Tail] = _Files, Acc) ->
case filelib:is_dir(File) of
true -> case file:list_dir(File) of
{ok, NewFiles} ->
FullNewFiles = [filename:join(File, N) || N <- NewFiles],
list_dirs_r(FullNewFiles ++ Tail, Acc);
{error, Reason} ->
lager:error("List dir(~p): ~p", [File, Reason]),
list_dirs_r(Tail, Acc) % Ignore dir if error
end;
false -> list_dirs_r(Tail, [File | Acc])
end.
list_dirs_r()鏄熬閫掑綊銆?br />鍒楀嚭褰撳墠鐩綍涓嬬殑鎵鏈夋枃浠跺拰鐩綍錛屾斁鍦‵iles鍙橀噺涓?br />Acc鏄瘡鍔犲櫒錛屾槸涓涓垪琛紝鏀墮泦鎵鏈夋枃浠躲?br />鍙朏iles涓ご閮ㄥ厓绱狅紝濡傛灉鏄枃浠訛紝鍒欐斁鍏cc緇撴灉闆嗭紝緇х畫澶勭悊浣欎笅鐨凢iles,
濡傛灉鏄洰褰曪紝鍒欏垪鍑鴻鐩綍涓嬫墍鏈夛紝鏇挎崲鍒?Files 澶撮儴銆?br />鎬ц兘娑堣楀湪
filename:join(File, N)
FullNewFiles ++ Tail
]]>
錛堥噾搴嗙殑涓撴爮錛?br />
gen_server with a dict vs mnesia table vs ets
http://stackoverflow.com/questions/2154376/gen-server-with-a-dict-vs-mnesia-table-vs-ets
緇欏嚭涓涓寜搴旂敤綾誨瀷閫夋嫨鐨勬柟娉曪細
Multiple processes on multiple VMs -> mnesia
Multiple processes on one VM -> ets/dets
One process -> bag/dict/...
Frequently Asked Questions about Erlang
February 22 2011
6.2 Is there a collection of data structures, e.g. balanced trees?
http://ftp.sunet.se/pub/lang/erlang/faq/libraries.html#id55214
鏃х増FAQ涓湁浠ヤ笅璇存槑錛?br />
In practice, Erlang programs use lists (either natively or via dict) for data structures involving up to a few hundred elements and use ETS (the Erlang Term Store) or mnesia for anything larger. ETS uses hashing to allow near constant-time access to almost arbitrarily large amounts of data.
For a collection of data consisting of a few (tens or hundreds) items, lists often outperform both ETS and trees. For large numbers of small items, ETS tends to work best. For larger items, balanced trees can outperform ETS because they avoid copying the data.
浣嗘槸鏂扮増FAQ涓垹闄や簡浠ヤ笂榪欎簺璇存槑錛屼及璁℃柊鐗堟湰涓湁浜嗗彉鍖栵紵
Frequently Asked Questions about Erlang
April 20 2015
6.2 Is there a collection of data structures, e.g. balanced trees?
http://www.erlang.org/faq/libraries.html#idp33085264
Erlang寮鍙戝緩璁?鏉傝鐗?
http://erlangdisplay.iteye.com/blog/374167
緇欏嚭浜嗘牴鎹妯¢夋嫨鐨勮寖鍥達紝搴旇鏄寜鏃х増FAQ浣滃嚭鐨勶細
Suggestion錛?br />elments count: 0 錛?100 | 100 - 10000 | 10000 -
our select : list | ets | gb_tree
]]>
rebar緙栬瘧鏃舵姤閿欙細
D:\server\six>d:/tools/rebar/rebar.cmd compile
==> mysql (compile)
Compiling d:/server/six/deps/mysql/src/mysql_recv.erl failed:
d:/server/six/deps/mysql/src/mysql_recv.erl:none: undefined parse transform 'lager_transform'
d:/server/six/deps/mysql/src/mysql_recv.erl:12:
Warning: Non-UTF-8 character(s) detected, but no encoding declared.
Encode the file in UTF-8 or add "%% coding: latin-1" at the beginning of the file.
Retrying with latin-1 encoding.
ERROR: compile failed while processing d:/server/six/deps/mysql: rebar_abort
lager_transform宸插姞鍏rl_opts.
灝唋ager鍦╠eps鍒楄〃涓彁鍒扮涓浣嶅彲瑙e喅銆?br />
{deps, [{lager, ".*", {git, "https://github.com/basho/lager.git"}},
{mysql, ".*", {git, "https://github.com/dizzyd/erlang-mysql-driver.git"}} ...
rebar浠呬粎鏄寜渚濊禆欏歸『搴忕紪璇戙?br />涔熷彲浠ラ鍏堢紪璇憀ager錛岀劧鍚庡啀rebar compile.
鍙傝冿細
http://stackoverflow.com/questions/20813513/configuring-lager-i-get-this-error-undefined-parse-transform-lager-transform
]]>
浣跨敤rebar doc鏉ョ敓鎴愰」鐩枃妗c?br />浣嗘槸褰揺rl婧愭枃浠剁洰褰晄rc涓嬪緩绔嬪瓙鐩綍錛屽茍鏂板緩erlang鏂囦歡鍚庯紝灝辨棤娉曠敓鎴愭枃妗c?br />
==> six (doc)
ERROR: doc failed while processing D:/six: {'EXIT',{function_clause,[{edoc,expan
d_sources,
[[{tttt,"dd_util.erl","./src/tttt"},
{'',"gateway_http.erl","./src"},
{'',"six.erl","./src"},
{'',"six_app.erl","./src"},
{'',"six_sup.erl","./src"}],
".erl",
{set,0,16,16,8,80,48,
{[],[],[],[],[],[],[],[],[],[],[],[],[],
[],[],[]},
{{[],[],[],[],[],[],[],[],[],[],[],[],
[],[],[],[]}}},
[],[]],
[{file,"edoc.erl"},{line,459}]},
{edoc,run,3,[{file,"edoc.erl"},{line,378}]},
{rebar_edoc,doc,2,
[{file,"src/rebar_edoc.erl"},{line,63}]},
{rebar_core,run_modules,4,
[{file,"src/rebar_core.erl"},
{line,491}]},
{rebar_core,execute,6,
[{file,"src/rebar_core.erl"},
{line,416}]},
{rebar_core,maybe_execute,8,
[{file,"src/rebar_core.erl"},
{line,300}]},
{rebar_core,process_dir1,7,
[{file,"src/rebar_core.erl"},
{line,259}]},
{rebar_core,process_commands,2,
[{file,"src/rebar_core.erl"},
{line,91}]}]}}
D:\six>
鍦╮ebar.config涓坊鍔犲弬鏁皗packages, false}瑙e喅浜嗐?br />
{deps, [{mysql, ".*", {git, "https://github.com/dizzyd/erlang-mysql-driver.git"}},
{lager, ".*", {git, "https://github.com/basho/lager.git"}},
{mochiweb, ".*", {git, "https://github.com/mochi/mochiweb.git"}}]}.
{erl_opts, [{parse_transform, lager_transform}]}.
{edoc_opts, [{packages, false}]}.
澶ф鏄疎rlang澶氬眰鐩綍浼氬緩绔?#8220;subpackages”錛屽簲璇ュ氨鏄ā鍧楀悕瀛楃┖闂達細
If the source code is organized in a hierarchy of subdirectories although it does not use packages, use no_packages
浣嗘槸娌℃湁鎵懼埌鐩稿叧鐨勬枃妗o紝涓嶇煡閬撳浣曞緩绔嬪瓙鍖呫?br />
鍙傝冿細
http://www.erlang.org/documentation/doc-5.8.4/lib/edoc-0.7.8/doc/html/edoc.html#run-3
http://www.erlang.org/documentation/doc-5.8.4/lib/edoc-0.7.8/doc/html/chapter.html#Running_EDoc
]]>
Erlang鑺傜偣鐩稿悓cookie鍏ㄤ簰鑱旀垚涓轟竴涓泦緹わ紙cluster錛?
濡傛灉2涓泦緹や笉鍚宑ookie, 鐒跺悗鍏朵腑鏈夎妭鐐硅繛鎺ュ埌瀵規柟闆嗙兢鐨勮妭鐐癸紝
榪?涓泦緹や細鍚堝茍鎴愪竴涓泦緹ゅ悧錛?br />
榪炴帴鍒板彟涓涓泦緹ゆ椂錛岄渶瑕佸厛璁劇疆cookie錛屼笉鐒朵細琚嫆緇濄?br />erlang:set_cookie(Node2, DiffCookie)
闆嗙兢aaaa鏈夎妭鐐筧1, a2, cookie涓?cookie_aaaa.
闆嗙兢bbbb鏈夎妭鐐筨1, b2, cookie涓?cookie_bbbb.
>erl -sname a1 -setcookie cookie_aaaa
...
>erl -sname a2 -setcookie cookie_aaaa
Eshell V6.3 (abort with ^G)
(a2@jinqing)3> net_adm:ping(a1@jinqing).
pong
(a2@jinqing)4> nodes().
[a1@jinqing]
>erl -sname b1 -setcookie cookie_bbbb
...
>erl -sname b2 -setcookie cookie_bbbb
(b2@jinqing)2> net_adm:ping(b1@jinqing).
pong
(b2@jinqing)3> nodes().
[b1@jinqing]
bbbb鑺傜偣鏃犳硶鐩存帴榪瀉aaa鑺傜偣
(b2@jinqing)4> net_adm:ping(a1@jinqing).
pang
b2鑺傜偣鏇存敼cookie鍚庯紝浠嶄繚鎸佷笌b1鐨勮繛鎺ャ?br />(b2@jinqing)6> erlang:get_cookie().
cookie_bbbb
(b2@jinqing)7> erlang:set_cookie(node(), abcd).
true
(b2@jinqing)8> erlang:get_cookie().
abcd
(b2@jinqing)9> nodes().
[b1@jinqing]
(b2@jinqing)10>
b2璁劇疆cookie騫惰繛鎺2鍚庯紝b2榪涘叆浜哸aaa闆嗙兢, 鍚屾椂鍙堝湪bbbb闆嗙兢銆?br />(b2@jinqing)10> erlang:set_cookie(node(), cookie_aaaa).
true
(b2@jinqing)11> erlang:get_cookie().
cookie_aaaa
(b2@jinqing)12> nodes().
[b1@jinqing]
(b2@jinqing)13> net_adm:ping(a2@jinqing).
pong
(b2@jinqing)14> nodes().
[b1@jinqing,a2@jinqing,a1@jinqing]
(b2@jinqing)15>
瀹為檯涓婃槸aaaa闆嗙兢鐜版湁3涓妭鐐癸細a1, a2, b2.
bbbb闆嗙兢浠嶇劧鏄?涓妭鐐癸細b1, b2.
(a1@jinqing)2> nodes().
[a2@jinqing,b2@jinqing]
(a2@jinqing)5> nodes().
[a1@jinqing,b2@jinqing]
(b1@jinqing)3> nodes().
[b2@jinqing]
姝ゆ椂 a2 ping b2 鏄氱殑錛屼絾鏄笉浼氬姞鍏?bbbb 闆嗙兢銆?br />(a2@jinqing)6> net_adm:ping(b2@jinqing).
pong
(a2@jinqing)7> nodes().
[a1@jinqing,b2@jinqing]
(a2@jinqing)8>