実際にパケットの送受信を行ったのだが、どうも、思ったように動作しない。サーバー」の実装そして、その原因を追うと、内部のステータスが、何かの都合で変化しないとか、とにかく、不安定であるようだ。※使い方に問題があるのかもしれない。労しても、実りが少なく、時間だけ消費する。そんなこんなで、もう「ギブ」って感じになった。報を元に再学習してみた。当初の目的(良好で、安定なネット環境)を見失っていると言う事実・・・プロトコルを理解すると、ブラックボックス的思考が開けてきて、もう、いっそうのこと、全部創ればいいんじゃねぇか?とゆー結論に至り、全部ゼロから実装してみる事にした。※何故、最初からそうしなかったのか、プロトコルや運用をちゃんと理解すれば、ゼロから創っても、そんなに時間はかからないと思える。C++は、この手の実装に向いている、順調に進み、ARPプロトコル、ICMPプロトコルのサービスができる状態になり、外部から「ping」が通るようになった。※ネットエンディアンが、「ビック」なので、多少、強引な部分はあるが、それなりにスマートになっていると思う、プロトコル別にモジュール化してあり(ソースを分ける)拡張や改修もやりやすいように配慮した。※「dhcp_client.hpp」は、真似コードなので全面的に書き直す必要がある。・ARPプロトコルIPアドレスに対応するMACアドレスを返信する。使われる、送信、受信を確認するプロトコルとりあえず、以前のルネサスベースのスタック関係は、そのまま残し、新たに「net2」として始めた。これから実装するのだが、ルネサスのコードに比べると1/4くらいになると思われる、しかも、関数のプロトタイプの説明も既に入っている。低機能なのにあんなに巨大になるのか、不思議・・・-----以下のサイトを主に参考にした、実装には非常に助かった。通るようになったネット・スタックだが、その先が中々進まない。苦労して、デバッグをした結果、ようやく、動作するようになった。・ルネサスの、「r_socket_rx」にバグがあった。※アドレス構造体にポートを設定する部分は、ソケットの仕様では、ネットエンディアン(ビッグエンディアン)で行うのだが、それが逆だった。・「r_t4_rx」のチェックサム計算ソースに問題があった。「gcc」の場合、アセンブルは通るが、そのままでは正しく動作しないようだ。uint16上記のように、少し修正した。次に、ソケット関連だが、ソースコードを見ると、ノンブロックモードが用意されているようだが、実際はこのモードはまともに動作しない事が判った。(とりあえず、ブロックモードで行っている)ソケットのモジュールでは、BSDソケットとの互換を意識して、関数名や、構造体を同じにしているが、これが、オリジナル(POSIX)のソケット関係と当るので、それに準じた、名称に変更した。クラスを新規にコミットした。元のネットスタック関係をデバッグ中、色々問題がある部分が多く、それらに修正を加えた、なので、オリジナルソースとは違うものになっている。・ソースの色々な部分で、「extern」を使い、変数の型や、関数の型を宣言しているが、一つのソースで共有すべきなので、新たに、「global.h、global.c、config_tcpudp.h」を作成した。※まだ、みるに絶えない部分は沢山あるが、とりあえず・・・ネットスタック全体は以下のような構成になっている。ip_adrs.hppdhcp_client.hppnet_tools.hppnet_core.hppsocket.hpphttp_server.hppr_tcpip_private.[hc]r_config/r_t4_rx_config.hr_config/r_socket_rx_config.hr_t4_rx/src/config_tcpudp.[hc]r_t4_rx/T4_src/dhcp.[hc]r_t4_rx/T4_src/ether.[hc]r_t4_rx/T4_src/global.[hc]r_t4_rx/T4_src/igmp.[hc]r_t4_rx/T4_src/ip.[hc]r_t4_rx/T4_src/r_t4_itcpip.hr_t4_rx/T4_src/t4define.hr_t4_rx/T4_src/tcp.[hc]r_t4_rx/T4_src/tcp_api.cr_t4_rx/T4_src/type.hr_t4_rx/T4_src/udp.[hc]r_t4_rx/T4_src/checksum/rx/cksum_rx_little.sインサーネットのハードウェアーの定義は以下のようにする。層デバイスは共通部分が多いので、そのまま使える、他のデバイス用にカスタムする場合、「phy_base.hpp」を参考にして別のデバイス用を作成する。※「SDC」は、SDカードの操作を行うクラス。(「main.cpp」参照)※他に、ルネサスのネットスタックとの仕様を合わせるCの関数を定義する。(ソースコード「main.cpp」を参照)メインプログラムからHTTPサーバーを使う場合、以下のようにすれば良い。※「/」ルートページのレンダリング定義は、サンプルでは動的なプログラムで行う。調べたが、やはり「ルネサス」が提供するネット関連のソフトウェアーが一番ハードルが低いだろうと考えた。※自分でスクラッチから実装するには、時間がかかり過ぎるので、再利用させてもらう。使うにはそれなりの時間と労力がかかるだろうし、大抵、リアルタイムOSの下で動作するように設計されている、それはそれで、良いのだが、自分としては、OSに依存しない事がメリットになると考えており、パフォーマンスを引き出すのも作り方しだいと思うので、今回はそのような方針で行った。※多分、RXマイコンで、このような方向性で行っているプロジェクトは少ないと思う。-----まず、ルネサスのソフトウェアー郡から、an-r01an3467jj0111-rx-fitをダウンロードして精査した。※アーカイブはモジュール別になっており、必要なモジュールを展開した。移行r_t4_rx_v2.05r_socket_rx_v1.31※ドキュメントはしっかりしており、利用法やカスタマイズの方法も詳しく書かれているが、肝心のソースコードの品質はあまり良くない。コンパイルする事は出来ない。等、標準ライブラリーとの親和性が悪いまた、ハードウェアー定義の「iodefine.h」は使いたく無いので、ハードに依存した部分はC++で書き直した。※既に、インサーネット以外のハードウェアーリソースは十分あるので、元のシステムに依存する部分を書き換えている(そんなに多くは無い)※「r_ether_rx、r_t4_driver_rx」など他、タイマーの設定や、割り込み関係の制御など、ハードに依存する部分を分離して追い出し、書き換えた。このネットスタックは、インサーネットと、インサーネットDMAC、タイマーで動作するように実装されており、割とシンプルな構造となっている。※タイマーは10ms(100Hz)で動作させる前提になっている(変更可能)TCP/UDPのインターフェースは、まだ実装中なのだが、「r_socket_rx」があるので、これを利用しようと思う。(BSDソケットの縮小版らしい)※HTTPサーバーや、FTPサーバーも専用のモジュールがあるがソケットを使うコードで統一するので利用しない。通るようになったので、全体プロジェクトをコミットした。※以前に使った、GR-KAEDE、WEBプログラミング用コード(Arduino互換)は、順次廃止して、新しいスタックに移行する予定。hiraコメントするFTPサーバーの次は、HTTPサーバーも実装しているが、まだ機能が不足している、順次機能追加していく。登録タスクの実行としくみ:組み込みマイコンで動かすサーバーでは、固定されたページを単に送るだけでは無く、状況により動的に生成した構文を送る事ができる。その際、リンクパスと、関連する実行関数を登録出来ると、非常に利便性が高い。メモリーは潤沢なので、それでも問題は無いが、納得は出来ない。組み込みマイコンでC++を使う場合の難点は、巨大なクラスを使えない(使わない)事で、あらかじめ判っている事として、「iostream」関係がある。a24d0※なので、それに代わる「format」、「input」クラスなどを実装している。※「例外」と「rtti」は無効にしている。※コードは巨大で複雑なので、時間が出来た時にでも調査する事にするが、とりあえず、巨大にならないように工夫して実装するしか無い。hiraコメントする前回、「fixed_string」テンプレートを紹介したが、本題の「format」に移る。「format」クラスは、「boost::format」の組み込みマイコン向けに仕様を変更した俺俺クラスだ。他ライブラリに依存していない為、「format.hpp」のみで簡潔するようになっている。<unistd.h>最終的な出力は、「iostream」では無く、ターミナルへの文字出力で、「syscalls」の「write」を使っている。stdout)また、出力クラスは、テンプレートの引数で与えており、出力ファンクタを実装する事で、色々な出力形態に対応できる。作り、利用していたが、柔軟性が無く拡張しずらかった為文字列クラスを使える仕様に修正した。※出来てみると、よりシンプルな構造になり、使いやすく、判りやすくなった。クラスの型は、こんな感じだ。{※「CHAOUT」へは、基本1文字づつ追加する。}};「format」クラスの一番大きな変更は、「CHAOUT」をスタティックとした点で。basic_format<CHAOUT>::chaout_;文字出力が、都度、リセットされないので、追加などの制御がやりやすくなった。暗黙的な仕様として、「operator(char)」、「size()」があれば良い。※「clear()」は利便性の為用意してある。標準的な文字列クラスを使った場合は以下のように、文字の終端を制御するクラスも与える事で、内部的制御を一般化できる。}・・・};「TERM」クラスは、「STR」クラスへの文字追加が出来なくなる前に、挙動を制御する。}「flush()」関数と、「STR」クラスへの参照、「TERM」クラスへの参照を追加してある。※「format」クラスは、これらの関数を必要としない。クラスをスタティックにすると、一時的に確保した領域(スタック)などで使いたい場合に、使いにくくなってしまう。そこで、バッファのポインターとサイズを与えて処理を行えるように、コンストラクターを追加した。(これは以前に作ったものを部分的に作り直した。)リソースはスタティックなので、利便性を考えて関数をリセットする為の仕組みも追加した。:また、この場合に合わせて、「memory_chaout」クラスを用意した。}};これで、以下のように使える。サーバーを実装する過程で、マイクロソフトのIEだけ極めて遅い応答しかできない事が判った。1秒以下で表示できるページなのに、IE(最新版)だと、30秒、またはそれ以上の時間がかかる。デコードが遅延され、結果次のパケットを受け付けない。ヘッダーにある「Content-Length」が無い、又は正しくない場合に起こる挙動なのかもしれない。生成のタイミングでパケットを送信していた。※全体の長さは、最終文が来るまで判らないので、「Content-Length」は作成していないかった。この方法はメモリーの利用は最低限になるのだが、IEのように大きなパケットを前提にした、腐ったブラウザでは表示速度に問題が起こる。文を一旦メモリーに展開して貯めて、一気に転送する方法に変更する事にした。※完全に固定されたページでは無く、動的に生成している為ここで問題なのは、「utils::format」クラスの挙動で、基本、行単位の動作を前提にしている為、かなり大きく、柔軟に変更する必要がある事がわかり、仕様を検討した。そこで、固定サイズの配列で動作する文字列クラスを実装した。メモリーが潤沢に無い場合には、「std::string」は事実上利用出来ないからで、メモリーアロケーターが密接に関連したクラスは使う事が出来ない。※今まで何故作らなかったのか不思議・・・とりあえず、最低限の機能のみ実装してあり、必要になった機能を追加する。以下に、ソースの一部を示す。FTPサーバーを実装した。車輪の再発明的要素は高いが、学習的要素もあるしで、取り組んでみた。プログラムとネットの情報を参考とした。ソースは、自分的には気に入らない部分が多い、なので応答メッセージや、全体の流れなど参考とした。乖離しており、あまり使う気にならない。最近はあまり使わない、どうしても使う必要がある場合だけ使う)・テンプレートを使わないスタイル(テンプレートを使う事で、柔軟性と拡張性が導入できると思うので、最近は良く使うようになっている)・ヘッダーとソースに分かれている。定義と実装を分離する必要が無く、1つのソース(ヘッダー)のみで管理できる)・他、細かい部分で色々・・-----ある程度実装して、クライアントを接続してみた。