ソケット通信をあーだこーだしてrcssserver3dにkick offさせる

GAを使ってrobocup 3D agentの動作を生成したい。評価のために、勝手にサーバを起動してクライアントを接続してエージェント走らせて評価値を書き出して死ぬクライアントを作る必要が生じている(もう長いことこの要求は放置されている)。 で、クライアント(C++)でとりあえずパラメータをテキストから読み込むようにして、GA部分はPerlのAI::Geneticに丸投げする。あとは、Perlからサーバを上げてクライアントを走らせて評価値をとってくるだけ(言うのは簡単だ)。 で、rcssserver3dにkick offの命令を出さないといけないのだが、rcssmonitor3dから出す以外に方法がよくわからなかった。サーバ側にコマンドからキックオフする機能は特に見あたらない(例によって調べるのがめんどい)のだが、いちいちモニタまで上げてたのではただでさえ遅いGAが耐え難い遅さになってしまう。 というわけで、rcssmonitor3dにキックオフ命令を出させた時に流れてるパケットをキャプチャして、同じように送ってやれば良いのではないかと思ったのでやってみた。 ソケットで送ってることはまぁわかっているので、tcpdumpでloをdumpする。この辺のがわからんってtwitterに言ってみたら何人かが教えてくれた。持つべきものはすごい友人達ですね。ありがとう。 tcpdump -i lo -w hoge -vvv -s0 とすると、loを通るパケットがhogeに吐き出される。いけてる。 これをwiresharkで開くといい感じにパケットの中身が見られるので、kickoffとかで検索をかけて、クライアント→サーバのパケットから目的のものを探す。 00 00 00 0e 28 6b  69 63 6b 4f 66 66 20 4c   ….(k ickOff L 65 66 74 29                                        eft) 目的のパケットのdata部はこんな感じだった。とりあえず (kickOff Left)という文字列を送ればいいものかと思い、適当にぐぐりつつPerlでport 3200に送りつけてみた。が、うまく動かない。 やはりdata部をそのままコピーするしかないと悟り、16進数で送るようにしてみた。 use IO::Socket::INET; my $c = IO::Socket::INET->new( PeerAddr => “localhost”, PeerPort => 3200, Proto    => “tcp” ) or die $!; my $msg = pack(“H*”, “0000000e286b69636b4f6666204c65667429”); $c->print($msg); $c->getline; $c->close; serverを立ち上げて、このスクリプトを走らせるとkickoffされるではないか。なんかひたすら蛇足でしかない気がするが、思うように動いたのでとてもうれしい。 0000  00 00 00 00 00 00 00 00  00 00 00 00 08 00 45 00   …….. ……E. 0010  00 46 7e 18 40 00 40 06  be 97 7f 00 00 01 7f 00   .F~.@.@. ……..

Read more