■ソケットプログラミングといってもsocketでbindがlistenしてて、という話ではなく、ATmega128でTCP通信を処理するプログラムを書きやすいようにsocketがbindでlistenするライブラリをどう設計しようか、という話。
組み込みTCP/IPスタックといえば、uIPがあるんですけど、そこはそれ、趣味だから。
UNIXならsocketしてbindして(以下省略)わけですが、それもOSあっての世界。せいぜい割り込みぐらいしかタスクスイッチがない世界だから、httpサーバやsmtpサーバを並列稼動させて受信待ちにさせるようなことはできない。RTOSから、となるとちょっと重すぎるし。
パケットが到着してから、その中身を見てそれぞれの処理ルーチンにディスパッチさせるようにすればいいわけで、ICMPやARPならそれでコトが済む。到着したパケットに脊髄反射してやればいいから。UDPもそんなところがあるかな。
ただ、TCPだとそれでは足りない。
TCPはパケットをやり取りする中で自身の状態を変えていかなければならない、ステートマシンが必要とされるからで、ICMP/ARP/UDPの処理と比べるとだいぶ異質になる。
実際の通信場面ではいろんな種類のプロトコルパケットが飛び交い、かつアプリケーション層からは余分なプロトコルパケットは意識させたくなく、そしてシングルタスク、ということを考えると、組み込みプログラム全体のストップ・ゴーの鍵を握るのがパケット受信ロジックになるのは仕方ない。
そしてやっかいなのは、少なくともARPは処理できないとまずくて、それでいて上位アプリケーションにとってARPは意識されないという点。
ARPは特定のIPアドレスを持っているMACアドレスはどれかという問い合わせに関わるプロトコルで、TCPを使うアプリケーションにしてみれば、TCPセッションを張る前の先触れのような処理になる。それは必要だけど、意識されない。テーブルの上のコップを掴む時、腕の運動制御を意識しないように。
だから、受信ロジックとしては、ARPやICMPは受信ロジック内部で閉じて、上位アプリケーションに着信は伝えず、ただ所定のポートを狙ったTCPについては応答するような動きをさせることになる。
ARPやICMPエコー応答処理は割り込みで扱うのが良いのだろうけど、処理時間がどれくらいになるのか、まだわからないので、割り込みに収まるのかどうか、今はなんとも。
今のところ、POSIXライクなソケットプログラミングはできるような雰囲気を出せるように、socket,bind,listen,read,write,close相当のAPIは持たせようと計画中。ただ、具体的にどの関数をコールしたときに受信処理の実体を預けるか、とか、ちょっと思案中。普通に考えるならlistenコール時にステータスをCLOSEからLISTENに移行させるのだろうけど、受信を待ち受けるアプリケーションへはreadコール後にディパッチされるのだから、read関数にステートマシン機能を持たせるのが合理的ではないかと考えている。