procket/examples/sendmsg_recvmsg_echo.erl 動かしてみた
結果から書くと、動いた?となる。
まず、自身の現時点の知識だと、何故動いているのか、理解していない。
だから、ここで、理屈を書く事はできない。
あくまでも、動いたソースの保存として書いておく。
将来何かで実装するときは、こう書かないかも知れない。
-module(sample). -export([start/0]). -define(PORT, 8854). -define(SIZEOF_SOCKADDR, sizeof(sockaddr)). start() -> {ok, FD} = procket:socket(inet, dgram, udp), io:format("SIZEOF_SOCKEADDR: ~p~n", [?SIZEOF_SOCKADDR]), ok = procket:setsockopt(FD, 'SOL_SOCKET', 'SO_REUSEPORT', <<1:32>>), Family = procket:family(inet), io:format("inet family ~p~n", [Family]), SA = <<(procket:sockaddr_common(inet, 16)):2/bytes, ?PORT:16/integer-unsigned-big, 192, 168, 0, 1, 0:64>>, io:format("SA: ~p~n", [SA]), ok = procket:bind(FD, SA), loop(FD). loop(FD) -> %% recv a packet up to 512 bytes long, along with 512 bytes of control %% data case procket:recvmsg(FD, 512, 0, 512, ?SIZEOF_SOCKADDR) of {error, eagain} -> loop(FD); {ok, Buf, Flags, CtrlData, From} -> io:format("Buffer ~p, From ~p, Ctrldata ~p Flags ~p~n", [Buf, From, CtrlData, Flags]), %% echo the packet back, but set the destination address to the %% 'from' of the previous packet, and send the previous message's %% control data so that the source address is set to the %% destination address of the previous packet ok = procket:sendmsg(FD, Buf, 0, CtrlData, From), loop(FD) end. sizeof(sockaddr) -> case os:type() of {unix,sunos} -> 32; {unix,_} -> 28 end.
検索しまくっていろいろブックマークをしまくったけど、大半、知識不足で理解できなかった_| ̄|○
https://github.com/msantos/procket/issues/27
どうも、procketの作者さん自身が答えてくれているらしいが、IP4での接続周りは、これで解消できました。
あとは、あんまり弄ってません。でも、2日掛かりました。
さて、自分が分かってない部分。
SAの変数で扱っている関数、procket:sockaddr_common、0:64
recvmsg, sendmsgの詳しい動き、sockaddrとかいうアトムとか・・・
'SOL_SOCKET', 'SO_REUSEPORT'とか、ちんぷんかんぷん。
http://umezawa.dyndns.info/wordpress/?p=2609
より、ヒントをもらって、書いたけど、分かってないです。
(´ヘ`;)ウーム…情けない。
TCP周りは、ちゃんと勉強しないと駄目ですな。
mongodb-erlang + cowboy 情報なさ過ぎ
題名の通り。
不人気言語は分かるけど、海外のサイトでも見つからんとか、どうなってんの。
と言うことで、いろいろ分かった備忘録。
まずは、Erlangとmongodbのドライバは、今の所mongodb-erlangがグーグル様での人気上位らしい。
https://github.com/comtihon/mongodb-erlang
その他もあって、嘗て、mongopoolを使っていたのだけれど、更新をやってないらしく、諦める。
https://github.com/hachreak/mongopool
後者は、SQLのJoinぽい事が簡単にできた記憶があるのだが、仕方ない。
そして、Google様ご推奨の方はというと、これまたReadmeがしょぼくて、上手く動かない。取り敢えず、以下のようにしないと動かない。
MongoConfig = [ {auth_source, <<"test">>}, %% ソースを見るとこれがdatabase {database, <<"test">>}, %% ← ソースだとadminに固定? {login, <<"mongo_user">>}, {password, <<"password">>}, {w_mode, safe}, {host, "host_name"}, {port, 27017} ], {ok, Connection} = mc_worker_api:connect(MongoConfig), Collection = <<"users">>, Selection = {}, {ok, Userdata} = mc_worker_api:find(Connection, Collection, Selection), Result = mc_cursor:rest(Userdata), mc_cursor:close(Userdata), io:format(" users data ~p ~n", [Result]),
auth_sourceって何よ!酷いよ。
次に、mongopool見たいな使い方だけど、Readmeを読むとmongocというライブラリを使えと来ている。素直に従うと、ちっとも動かない。結局以下のようにしないと、動かなかった。
Seeds = {single, "hostname:27017"}, Options = [{name, mongopool}, {register, mongotopology}, {pool_size, 2},{rp_mode, primary}, {rp_tags, [{tag,1}]}], WorkerOptions = [ {auth_source, <<"test">>}, %% ソースを見るとこれがdatabase {database, <<"test">>}, %% 将来切り替わるはず(今は、auth_source) {login, <<"mongo_user">>}, {password, <<"password">>}, {w_mode, safe} ], {ok, Topology} = mongoc:connect(Seeds, Options, WorkerOptions), Collection = <<"users">>, Selection = #{}, Projector = #{}, {ok, Userdata} = mongo_api:find(Topology, Collection, Selection, Projector), Result = mc_cursor:rest(Userdata), mc_cursor:close(Userdata), io:format(" users data ~p ~n", [Result]),
Seedsは、Readmeだと複数設定しか書いていない。また、リストの方を一つにしても動かない。
mongoc:connectじゃないとgen_serverが起動しない。mongo_api:connectは罠?
mongo_api:findは、アリティが4しかない。最後の引数の説明が何処にもない。何これ?取り敢えず、エラーメッセージからマップ型と判断されたので、それをセット。何コレ?
Optionでnameを使っているが、何処で使うのか不明。Topologyと言う変数には、Pidが帰ってくるが、コレを保持しないとcowboyで使えない。何コレ。
erlydtl コンパイル erlydtl_preparser.hrl: no such file or directory
Procketの話題は、また別の機会に。
erlydtlってのは、Django風のビューテンプレートって事らしい。
https://github.com/erlydtl/erlydtl
ErlyDTL compiles Django Template Language to Erlang bytecode.
と書いているが、実は、以前に使った事あり。しかし、どうしたことか、rebar.configに書いただけだと、コンパイルが通らない。
ちなみにHexにあるのが、以下のような簡単な記述
{erl_opts, [debug_info]}. {deps, [ : {erlydtl, "0.12.1"}, :
だけど、これじゃコンパイルエラーがでる。
_build/default/plugins/erlydtl/src/include/erlydtl_preparser.hrl: no such file or directory
===> Compiling _build/default/plugins/erlydtl/src/erlydtl_parser.yrl failed
結論から言うと、src/include/erlydtl_parser.yrl を作り、以下のページからソースをコピペする。
https://github.com/erlydtl/erlydtl/blob/master/include/erlydtl_preparser.hrl
なんでやろ?issueにも上がってないし、あっしの特有の問題でしょうかね。
Procket エコーサンプル 動いた でも、これじゃ駄目
この内容は、実は、コンパイルが通った次の日に書いたもの。
なかなか、順風満帆な書きっぷりだが、実は、このサンプルは、将来に渡って使えないサンプルになります。
事前に知っていて、直ぐに解決できるわ!フフン♪とか思っていたのですが、そんなに甘くはなかったのでした。
ErlangでProcketを使っているのは、以下のブログがあったから
gen_udp/tcp:send がボトルネックなときにやること
さて、昼飯食ってウトウトしつつ、以下のサンプルを転記でて動かす。
https://github.com/msantos/procket/blob/master/examples/echo.erl
ここで、問題が発生する。基本通り、Supervisor経由で起動すると、gen_udp:openでコケてしまう。エラーログも、crash reportも何を訴えているのか異次元の主張。仕方無くググってみるが、これまたGoogle先生が無言に。
仕方無いので、shellから直接、コマンド叩いて起動する。
すんなり起動。
・・・・・アレ?
これ、どうやってテストすんの?telnetできんの?最近調子が悪いGoogle先生に再び質問すると、ncとかいうツールを紹介される。
・・・・同じ端末だと、ポート競合するでしょ!
と言うことで、数ヶ月ぶりにFusionのLinuxを起動。
ncコマンドなんて入ってねー。
と言うことで以下のHPを参考にncを導入。
yum で CentOS に nc(netcat) をさくっとインストールする手順
それじゃ、遠慮無くコマンドを入力して、エコーチャットをしてみると、おお、出来るじゃないですか。と言うことで第一段階はクリア?と言うことで。
Procket コンパイルできた 自己解決
仕事中に、こそこそGoogle先生に聞いてみる。
兎に角Procketのインストール関連の話が出てこない。仕方無いので、エラーログでGoogle先生に問い合わせる。すると、次のページにぶち当たる。
Unable to compile on OS X El Captain 10.11.6 #1531
Makefileの中身を変えろって事らしい。んで、今し方中身を確認。
UNAME_SYS := $(shell uname -s)
ifeq ($(UNAME_SYS), Darwin)
CC ?= cc
CFLAGS ?= -O3 -std=c99 -arch x86_64 -finline-functions -Wall -Wmissing-prototypes
CXXFLAGS ?= -O3 -arch x86_64 -finline-functions -Wall
LDFLAGS ?= -arch x86_64 -flat_namespace -undefined suppress
さっきのページそのまま。テンプレなんですかな。
UNAME_SYS := $(shell uname -s)
ifeq ($(UNAME_SYS), Darwin)
CC ?= cc
CFLAGS += -O3 -std=c99 -arch x86_64 -finline-functions -Wall -Wmissing-prototypes
CXXFLAGS += -O3 -arch x86_64 -finline-functions -Wall
LDFLAGS += -arch x86_64 -flat_namespace -undefined suppress
そのまま?を+にする。
$ rebar3 shell ===> Verifying dependencies... ===> Compiling procket /Applications/Xcode.app/Contents/Developer/usr/bin/make -f /Users/<user_name>/<project_name>/erlang/nanisyon/_build/default/lib/procket/c_src/Makefile.ancillary make[1]: Nothing to be done for `all'. cc -m64 -g -Wall -o /Users/<user_name>/<project_name>/erlang/nanisyon/_build/default/lib/procket/priv/procket -L/Users/<user_name>/<project_name>/erlang/nanisyon/_build/default/lib/procket/c_src procket_cmd.c -lancillary cc /Users/<user_name>/<project_name>/erlang/nanisyon/_build/default/lib/procket/c_src/procket.o -L/usr/local/opt/openssl/lib -arch x86_64 -flat_namespace -undefined suppress -shared -L/Users/<user_name>/<project_name>/erlang/nanisyon/_build/default/lib/procket/c_src -lancillary -L /Users/<user_name>/kerl/installs/21.1/lib/erl_interface-3.10.4/lib -lerl_interface -lei -o /Users/<user_name>/<project_name>/erlang/nanisyon/_build/default/lib/procket/c_src/../priv/procket.so ===> Compiling jsone ===> Compiling nanisyon Erlang/OTP 21 [erts-10.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] Eshell V10.1 (abort with ^G)
あっさり、出来ちゃいマスタ。
XCode疑って済みません。本当に(o_ _)o
結局64bitのライブラリ?オブジェクト?が読み込めない?or見つからないというエラーなんだろうかね。
Procket コンパイルできねぇ 俺 困憊る
一通り、広く浅く、ネットワーク周りの知識を漁ったので、UDPを使った、デスクトップチャットでも作ろうかと考える。ここ最近、本ばかり読んで頭でっかち、いざ手を動かそうとすると、それまで出来ていた事が、すっぽり抜けて、なかなか前に進めない。とは言え、まずは、開発環境を整える事とした。
サーバ側は、勿論Erlangでやってみるぞ、コノヤローと一人いきんで、rebar3をアップデート、さらに、Erlangの21.1を入れておく。久々のkerlだが、勿論、覚えているわけが無く、昔のログを見ながら何とか成功。備忘録最高。
さて、取り敢えず、プロジェクトが無いと始まらないので、適当な名前でプロジェクトを作成。ここまでは、何とかなった。
問題は、ここから。rebar.configの中を以下のように編集。
{deps, [ {jsone, {git, "https://github.com/sile/jsone.git", {tag, "master"}}}, {procket, "0.9.3"} ]}.
$ rebar3 shell ===> Verifying dependencies... ===> Compiling procket /Applications/Xcode.app/Contents/Developer/usr/bin/make -f /Users/<user_name>/<project_name>/_build/default/lib/procket/c_src/Makefile.ancillary make[1]: Nothing to be done for `all'. cc -m64 -g -Wall -o /Users/<user_name>/<project_name>/_build/default/lib/procket/priv/procket -L/Users/<user_name>/<project_name>/_build/default/lib/procket/c_src procket_cmd.c -lancillary cc /Users/<user_name>/<project_name>/_build/default/lib/procket/c_src/procket.o -L/usr/local/opt/openssl/lib -shared -L/Users/<user_name>/<project_name>/_build/default/lib/procket/c_src -lancillary -L /Users/<user_name>/kerl/installs/21.1/lib/erl_interface-3.10.4/lib -lerl_interface -lei -o /Users/<user_name>/<project_name>/_build/default/lib/procket/c_src/../priv/procket.so Undefined symbols for architecture x86_64: "_enif_alloc_binary", referenced from: _nif_accept in procket.o _nif_read in procket.o _nif_ioctl in procket.o 〜 略 〜 ... "_enif_release_binary", referenced from: _nif_read in procket.o _nif_recvmsg in procket.o _nif_recvfrom in procket.o "_enif_release_resource", referenced from: _nif_alloc in procket.o "_erl_errno_id", referenced from: _nif_fdrecv in procket.o _nif_close in procket.o _nif_accept in procket.o _nif_bind in procket.o _nif_connect in procket.o _nif_getsockname in procket.o _nif_getsockopt in procket.o ... ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) make: *** [/Users/<user_name>/<project_name>/_build/default/lib/procket/c_src/../priv/procket.so] Error 1 ===> Hook for compile failed!
ちょっと、何コレ_| ̄|○
Google先生も、何も答えてくれない。何故、どうして、こうなる。
怪しいのは、XCodeのmake当たりか?最近XCodeのバージョン上がったし、疑わざるを得ない。
誰かぁ!ご存じの方いたら、優しく教えて下さい。
macOS: Mojave 10.14
XCode 10.1
rebar3 3.7.0-rc2+build.4175.ref83d01b52 on Erlang/OTP 21 Erts 10.1
erlang 21.1
ちなみに、jsoneは、「入るかな?」のお試しです。此方は、問題なく入るのに。
英語が分かれば、直でissue出したいけど、無理っす。
Stun Turn と諸々
あ〜またもや数ヶ月。しかし、この間劇的な進展があったので、備忘録も含めて更新。
まず、Erlang周りが大分解決。勿論、オールクリアなんて事は、ありません。
・Socket通信 TCP通信
https://www.ymotongpoo.com/works/lyse-ja/ja/26_buckets_of_sockets.html#tcp
作者、訳とも凡人には、わかりにくい校正ながら、サンプルで何度も、反芻して何とか、いや何となく解決。
gen_tcpからgen_serverに発展とか、素人には、ウルトラ難しい。
【参考】https://dmathieu.com/articles/development/erlang-tcp-server/
つーか、これなかったら、全く分からんかった。
これから、Swift4へつないで、チャットサンプル作成。こちらは、また纏めて備忘録作成。
・Socket通信 udp通信
何となく、分かった気がしたけど、NAT越えをしないと、普通は使えない事が分かる。しらんかったのか!と驚く事なかれ。しらんかったのです。この年で、ちょっとだけ、脳に皺増えました。ありがとうございます。
WebRTC https://gist.github.com/voluntas/975bfa230e513d146965
ベクトルがぶっ飛び過ぎ!普通にNAT越え調べたら、こればっかり。
本買った。時雨堂さんって凄いのね。尊敬します。時雨堂さんご推奨本+α
- 作者: Alan B. Johnston,Daniel C. Burnett,内田直樹(監訳)
- 出版社/メーカー: リックテレコム
- 発売日: 2014/12/12
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
ハイパフォーマンス ブラウザネットワーキング ―ネットワークアプリケーションのためのパフォーマンス最適化
- 作者: Ilya Grigorik,和田祐一郎,株式会社プログラミングシステム社
- 出版社/メーカー: オライリージャパン
- 発売日: 2014/05/16
- メディア: 大型本
- この商品を含むブログ (4件) を見る
Real World HTTP ―歴史とコードに学ぶインターネットとウェブ技術
- 作者: 渋川よしき
- 出版社/メーカー: オライリージャパン
- 発売日: 2017/06/14
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (4件) を見る
高度過ぎて、「なるほど分からん状態」
但し、StunとTurnは、Erlangで組んであるものを発見。
●STUN and TURN library for Erlang / Elixir
https://github.com/processone/stun
rebar3でも動かせた。
あとは、コレをどうやって通信で使えば良いのか、サンプルを探しております。ヘッダーだけ、stunで取得したものを織り込んで、あとは、そのまま送りつけるの?カスタムヘッダーが云々あるけど、指定するんだろうかね。
(´ヘ`;)ウーム… 使いこなすには、まだ長い道のりが・・・。
●WebRTC
lambdaclass/webrtc-server
https://github.com/lambdaclass/webrtc-server
How to set up MongooseICE (ICE/TURN/STUN server)
https://www.erlang-solutions.com/blog/how-to-set-up-mongooseice-ice-turn-stun-server.html
単純にWebRTCを実現するなら、上記の物でも良い?のかも。
したのは、有名なものらしい。