RX65N TCPノンブロッキング クライント側としてのコールバックについて

いつもお世話になっております。Yoshiと申します。

別投稿では解決済みに至りましたことありがとうございました。

プログラムのベースは「RXファミリ 組み込み用 TCP/IP M3S-T4-Tiny 導入ガイド Firmware Integration Technology アプリケーションノート」にある「r20an0051xx0209-rx-t4-fit」の中の「rskrx65n_2mb_tcp_nonblocking」となり、TCP/IPのサーバー側、クライント側を搭載しようとしており、どちらの機能も通信自体は問題なく実現できています。

そこで、一つ気になる動作がありご確認をさせて頂きました。

接続相手はWindows PCになり、サーバー側はテストツールを使用して確認を進めています。

サーバー側が起動していない状態で、クライアント側としてtcp_con_cep()を実行しますと、設定したコールバック関数に飛んできます。
その時、イベントコードfncd=-518で、パラメータブロックp_parblk=0x23f8が入っており、

fncdのswitch文でdefaultへ遷移し、tcp_cls_cep()を処理します(サンプルコードのまま使用しています)

切断状態であれば再度tcp_con_cep()を実行する様にプログラムしていることもあり、コールバック⇒切断⇒tcp_con_cep()を繰り返す状態にあります。

ご確認事項としては、

・サーバーが起動していない状態でtcp_con_cep()を実行すると、コールバックへ飛んでくるのは正しい動作でしょうか?

 イベントコード、パラメータブロックの値で調べてみたものの、詳細が分からず投稿させて頂きました、、、

ちなみに、正常系の動作として、サーバーを起動した状態でtcp_con_cep()を実行すれば、
コールバックへ遷移しますが、正常接続された状態遷移として処理が成されます。

お忙しいところ恐縮ですがご教示のほど宜しくお願いいたします。

Parents
  • よしさん

    こんにちは、シェルティです。M3S-T4-Tiny (通称T4ライブラリ)の設計者です。ルネサスの中の人です。

    下記回答します。

    >>・サーバーが起動していない状態でtcp_con_cep()を実行すると、コールバックへ飛んでくるのは正しい動作でしょうか?

    はい、正しい挙動です。

    一般的にtcp_con_cep()等のTCPクライアントコネクション開始処理においてSYNフラグを含むTCPパケットをサーバに向けて送信したとき、サーバが起動していない(Linux等のOSは起動しているが、サーバアプリが起動していないと仮定)場合、サーバはRSTフラグを含むTCPパケットをクライアントに向けて返送します。このとき、T4ライブラリはtcp_con_cep()実行中にRSTフラグを受信する形になります。

    以下T4ライブラリのソースコードです。

    https://github.com/renesas/rx-driver-package/blob/master/source/r_t4_rx/r_t4_rx_vx.xx/r_t4_rx/make_lib/make_lib.zip

    T4ライブラリの内部では、_TCP_API_CONCPという状態になっておりRST受信時に_TCP_API_CONCP状態の場合、「コード1: RST受信処理」のようにエラーコードにE_CLSをセット(*(areq->error) = E_CLS;)し、_TCP_CB_CALL_CALLBACK()にてユーザ側のコールバック関数にイベント通知を行います。_TCP_CB_CALL_CALLBACK()の第2引数がTFN_TCP_CON_CEPで、第3引数が_tcp_tcbです。_TCP_CB_CALL_CALLBACK()の中で「コード2: _TCP_CB_CALL_CALLBACK()マクロ実装」のように_tcp_tcb->req.error (本動作の場合E_CLSが入ります)をコールバックにてユーザ通知します。

    ユーザ側は上記コールバック処理により、tcp_con_cep()発行後にサーバがRST応答を返してくると、コールバック関数の第2引数(イベントコード)にTFN_TCP_CON_CEP、第3引数(パラメータブロック)のポインタが指し示す先にE_CLSをそれぞれ受け取ることができます。

    上記状態の場合、一般的には「サーバが何らかの不調(電源は入っている)でRSTを返してくるので、クライアントとしてはもう一度接続を試みてみる」という動作が適切であり、RSTを受信するともう一度tcp_con_cep()を呼び出すようなサンプルにしてあります。ですがこれはシステム上で動作定義してもよく、RST受信の場合は10分間くらい再接続を試みるのをやめておく、や、RST受信するとシステムはシャットダウンする、といった動作でも良いかもしれません。

    コード1: RST受信処理@tcp.c

    コード2: _TCP_CB_CALL_CALLBACK()マクロ実装@tcp.h

    なお、イベントコードfncd=-518の見方ですが、T4は負数・16進数でイベントコードを表現していて-518 は -0x206 となりソースコード上のマクロ定義名はTFN_TCP_CON_CEP となります。

    https://github.com/renesas/rx-driver-package/blob/16c0de74501df2e91767db192b4879ab03caf114/source/r_t4_rx/r_t4_rx_vx.xx/r_t4_rx/lib/r_t4_itcpip.h#L243

    パラメータブロックの見方は少し面倒です。パラメータブロックはボイドポインタ型であり、何らかのポインタにキャストしてポインタの先を何らかの変数に代入して利用します。TCP関連コールバック処理の場合パラメータブロックの型はER型(エラーコードを意味する)ですので、以下のようにしてパラメータブロックからエラーコードを取り出せます。

    ER t4_tcp_callback(ID cepid, FN fncd, VP p_parblk)
    {
        ER parblk = *(ER *)p_parblk;

        :

    今回の動作ですと、parblkにはE_CLSが入っています。このエラーコードのマクロ定義は上述した r_t4_itcpip.h にあり、値としては-52 (こちらエラーコードは10進数表現) です。

    この粒度の動作の理解には、T4ライブラリ内部をソースコードレベルデバッグできるようにデバッグ環境を組んで、T4ライブラリ内部をステップ実行してく(最適化OFFにしてライブラリをビルドしなおすとより細かくデバッグしやすいです)とどのデータがどのように処理されていくかが分かりやすいと思います。ソースコードレベルデバッグに関しては、過去シェルティが開催していたT4ライブラリのセミナ資料の最期の方にある「TCP/IP内部のソースコードレベルデバッグの手法」をご参照ください。

    https://github.com/renesas/rx72n-envision-kit/wiki/1-Ether-TCP-IP#%E3%82%BB%E3%83%9F%E3%83%8A%E8%B3%87%E6%96%99

    また、ソースコードレベルデバッグのみならず、Ether回線上のパケット自体を観察することでもTCP/IPの挙動のパタンの多くを理解できると思います。そのためのツールとしてWiresharkというツールがおすすめです。

    https://www.wireshark.org/

    以上です

     

  • シェルティさま

    ご回答ありがとうございました。

    WiresharkでPCから応答が返されていたのは確認できていましたが、
    T4ライブラリ側がその応答に応じた正しい動作なのかが分からなかったのですが、
    非常に分かりやすく、理解が進みました。

    一連の動作につきましては、システム上で動作定義をしようと思います。
    頻繁なる割り込み継続状態を避けたいので、ご提案くださったように、一定時間後に再度tcp_con_cep()を実施してサーバーの状態を伺う。事にしたいと思います。

    いつも助言くださりありがとうございます。
    今後とも宜しくお願いいたします。

Reply
  • シェルティさま

    ご回答ありがとうございました。

    WiresharkでPCから応答が返されていたのは確認できていましたが、
    T4ライブラリ側がその応答に応じた正しい動作なのかが分からなかったのですが、
    非常に分かりやすく、理解が進みました。

    一連の動作につきましては、システム上で動作定義をしようと思います。
    頻繁なる割り込み継続状態を避けたいので、ご提案くださったように、一定時間後に再度tcp_con_cep()を実施してサーバーの状態を伺う。事にしたいと思います。

    いつも助言くださりありがとうございます。
    今後とも宜しくお願いいたします。

Children
No Data