前提
Norti ver.4(μITRON系RTOS)を使って組込み制御プログラムを作っています。
Nortiにはミスポ製のTCP/IPプロトコルスタックが含まれているため、
今回はそれを用いてTCP通信を行います。
実現したいこと
今回作成するプログラムはTCPのサーバ側(リッスンする側)なので、
プログラム起動したらソケット(Nortiでは「通信端点」と呼ぶ)を作成し、
プロトコルスタックのAPI、tcp_acp_cep()を呼び出して当該通信端点のリッスンを開始します。
通信相手(クライアント側)からSYNが送信されてきたらプロトコルスタック内で自動的に3wayハンドシェイクが実施されてTCPコネクションがなされ、データの送受信を行います。
今回のプログラムはTCPサーバですので、いろいろなクライアントからの接続を受付けてデータ通信を実施します。(同時接続台数は1台のみです)
なお、クライアント側のTCP通信を行うアプリケーションはどんなクライアントでもすべて同一です。
データの受信はtcp_rcv_dat()を用いて行っています。
このAPIはノンブロッキング指定で呼び出すことで、相手からのデータの受信、もしくは相手との接続切断をコールバックにて教えてくれる仕様となっております。
発生している問題・エラーメッセージ
上記の通り、tcp_rcv_dat()はノンブロッキング指定呼出によって相手からのデータの受信、もしくは相手との接続切断をコールバックにて教えてくれる構造となっているのですが、通信相手となるクライアント側のPCによってコールバックが入ったり入らなかったりして大変困っています。
分かっていることは以下の通りです。
①データ受信or切断時、コールバックが入らないPCを相手にしていると必ずコールバックが入らず、コールバックが入るPCを相手にしていると必ずコールバックが入る。(再現度100%)
②PCのスペックは以下の通り。
●コールバックOKのPC
・OS:Windows10 Pro 64bit 21H1
・CPU:Corei5 8250U
・メモリ:8GB
・ネットワークアダプタIntel Ethernet Connection I219-V
●コールバックNGのPC
・OS:Windows10 Pro 64bit 1909
・CPU:Corei5 6200U
・メモリ:4GB
・ネットワークアダプタIntel Ethernet Connection I219-V
③コールバックが入るPCからのパケット、入らないPCからのパケット内容は以下の通り。
NG OK
以下イーサヘッダ
00 00 宛先MAC
25 25
28 28
11 11
11 11
60 60
ec 58 送信元MAC
21 27
e5 8c
08 bf
98 cc
28 05
08 08 タイプ
00 00
以下IPヘッダ
45 45 バージョン&ヘッダ長
00 00 サービス
00 00 パケット長
3b 3b
a8 d5 識別子
da fb
40 40 フラグ
00 00
80 80 TTL
06 06 プロトコル
00 00 チェックサム
00 00
ac ac 送信元IP
1b 1b
15 15
0b 32
ac ac 宛先IP
1b 1b
15 15
1e 1e
以下TCPヘッダ
c3 d4 送信元ポート
30 bb
ea ea 送信先ポート
60 60
09 fe シーケンスNo
f9 85
05 76
52 fc
08 08 応答No
a6 77
50 20
d1 d1
50 50 オフセット&CtrlFlg
18 18
fa fa ウィンドウサイズ
f0 f0
82 82 チェックサム
8d b4
00 00 緊急ポインタ
00 00
以下アプリ独自電文(TCPデータ部)
00 00
11 11
ff ff
00 00
01 01
00 00
01 01
00 00
01 01
ac ac
1b 1b
15 15
0b 32 ←データ部の違いはここのみ(この部位に送信元IPアドレスを格納しているため)
ac ac
1b 1b
15 15
1e 1e
00 00
01 01
④コールバックが入らないPCにおいても、クライアント側からの接続時のコールバックは入る。
つまり、サービスコールの機能コード「TFN_TCP_ACP_CEP」のコールバックは入るが、
「TFN_TCP_RCV_DAT」のコールバックは入らない。
該当のソースコード
サンプルソースコードをざっと作ってみました。以下に示します。
C
1/* 2 * コールバックからの受け渡し情報用グローバル変数 3 */ 4ID rcvCep; /* 受信CEP格納用 */ 5FN rcvFnCd; /* 受信機能コード格納用 */ 6VP rcvParblk; /* 受信処理結果格納用 */ 7unsigned char rcvBuf[2048]; /* 受信バッファ用 */ 8/* 9 受信する機能コードの種類はマニュアルによると以下の通り 10 11 TFN_TCP_ACP_CEP (-0x205) tcp_acp_cep 完了通知 12 TFN_TCP_CON_CEP (-0x206) tcp_con_cep 完了通知 13 TFN_TCP_CLS_CEP (-0x208) tcp_cls_cep 完了通知 14 TFN_TCP_SND_DAT (-0x209) tcp_snd_dat 完了通知 15 TFN_TCP_RCV_DAT (-0x20a) tcp_rcv_dat 完了通知 16 TFN_TCP_GET_BUF (-0x20b) tcp_get_buf 完了通知 17 TFN_TCP_RCV_BUF (-0x20d) tcp_rcv_buf 完了通知 18 TFN_UDP_SND_DAT (-0x223) udp_snd_dat 完了通知 19 TFN_UDP_RCV_DAT (-0x224) udp_rcv_dat 完了通知 20 */ 21 22 23/* 24 * メインルーチン 25 */ 26int mainRoutine(){ 27 T_TCP_CREP pk_crep; /* TCP受付口生成情報 */ 28 ID repid; /* TCP受付口ID */ 29 T_TCP_CCEP pk_ccep; /* TCP通信端点生成情報パケット */ 30 ID cepId; /* TCP通信端点ID */ 31 T_IPV4EP distAddr; /* 接続受付アドレス情報 */ 32 TMO tmout; /* タイムアウト指定 */ 33 34 int acpValidFlg = FALSE; //接続有効フラグ 35 36 // 37 //~~~このあたりに変数の初期化処理~~~ 38 // 39 40 /* TCP受付口生成呼び出し*/ 41 tcp_cre_rep(repid, &pk_crep); 42 43 /* TCP通信端点生成のシステムコール呼び出し */ 44 tcp_cre_cep(cepId, &pk_ccep); 45 46 /* リッスン開始 */ 47 tcp_acp_cep(cepId, repid, &distAddr, tmout); 48 49 // メインループ 50 while(1){ 51 52 //接続有効であればtcp_rcv_dat呼び出してデータ受信をノンブロッキングで呼び出す 53 if(acpValidFlg){ 54 tcp_rcv_dat(cepId, rcvBuf, 2048, TMO_NBLK); 55 } 56 57 //コールバックからのイベント通知を待つ(コールバック発生までここでブロッキングのイメージ) 58 waitMsg(); 59 60 /* サービスコールの機能コードに応じて分岐 */ 61 switch(rcvFnCd) 62 { 63 //接続完了 64 case TFN_TCP_ACP_CEP: //このイベントはNGなPCでもコールバックから拾える 65 //接続完了したら接続有効状態とする 66 acpValidFlg = TRUE; 67 break; 68 69 //クローズ完了 70 case TFN_TCP_CLS_CEP: 71 //クローズ完了したら再度リッスン開始 72 acpValidFlg = FALSE; //接続無効にする 73 tcp_acp_cep(cepId, repid, &distAddr, tmout); 74 break; 75 76 //送信完了 77 case TFN_TCP_SND_DAT: 78 //送信完了時の処理省略 79 break; 80 81 //受信完了 82 case TFN_TCP_RCV_DAT: //このイベント、NGなPCではコールバックから拾えない 83 //受信完了時の処理省略 84 break; 85 86 default: 87 break; 88 } 89 } 90 91 return 0; 92} 93 94 95/* 96 * Nortiからのコールバック関数 97 */ 98void callback(ID cepId, FN fnCd, VP parblk) 99{ 100 /* 受信CEPをセット */ 101 rcvCep = cepId; 102 103 /* 機能コードを格納 */ 104 rcvFnCd = fnCd; 105 106 /* 処理結果を格納 */ 107 rcvParblk = parblk; 108 109 /* イベント発生をmainRoutineに通知 */ 110 sendMsg(); 111 112 return; 113} 114
試したこと
①OKのPCとNGのPCでIPアドレスを入れ替えてみる ⇒ 変わらず
②NGのPCでネットワークアダプタをUSB接続の別のものに替えて試してみる ⇒ 変わらず
補足情報(FW/ツールのバージョンなど)
組み込みOS:Norti ver4
・NortiTCP/IPプロトコルスタックのマニュアルPDF
http://www.mispo.co.jp/document/n4nguid.pdf

あなたの回答
tips
プレビュー