SSブログ

したらばワシもSilentCでTCPをやってみよう 2 [SilentC]

前回は受信を中心に動作確認してみたので、今回は送信をメインに。
マニュアルに拠るとSilentCは970bytesまでデータの送信が可能と言う事で、こんなプログラムを作成してみました。
相手は自作のDISCARD(破棄)サーバーです。
dis_cli()
{
  int i;
  char soc = CreateSocket( 1 );
  long dip = GetIP( "192.168.1.30" )
  Connect( soc, dip, 9 );
  for( i = 0; i < 10; i++ )
  {
    if( Write( soc, "hello", 100 ) < 0 ) break;
    if( WaitWriteComplete( soc ) < 0 ) break;
  }
  CloseSocket( soc );
}

つまり”hello”から続く100bytesのデータを10回送信してみようと。ちなみに”hello”だけの時は成功しています。
例によってパケットモニタも仕掛けてあります。
すると、あれ???、いきなりチェックサムエラーが発生している。
<< パケット 60 >>
--- TCPヘッダ [1024] → [9] -------------------------------------------------
【発信元ポート番号】1024 
【発信先ポート番号】9 (DISCARD)
【シーケンス番号】623055264 (0x252311A0)
【応答番号】1701643170 (0x656D03A2)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】1【RST】0【SYN】0【FIN】0
【ウィンドウ】1454 (0x05AE) バイト
【チェックサム】0xD4A6 (NG)
【緊急ポインタ】0
【オプション】なし

---【データ】100 (0x0064) バイト --------------------------------- SJIS -------
0000  68 65 6C 6C 6F 00 00 00 - 00 00 05 A2 00 06 00 05  hello......「....
0010  57 61 69 74 57 72 69 74 - 65 43 6F 6D 70 6C 65 74  WaitWriteComplet
0020  65 00 00 00 00 06 00 05 - 04 00 00 09 25 23 11 A0  e...........%#..
0030  65 6D 03 A2 50 18 05 AE - D4 A6 00 00 00 00 00 00  em.「P..ョヤヲ......
0040  50 72 53 74 72 28 20 22 - 67 65 74 20 2F 2E 5C 72  PrStr( "get /.\r
0050  5C 6E 22 20 29 3B 0D 0A - 20 20 20 20 57 72 69 74  \n" );..    Writ
0060  65 28 20 6E                                        e( n

<< パケット 62 >>
--- TCPヘッダ [1024] → [9] -------------------------------------------------
【発信元ポート番号】1024 
【発信先ポート番号】9 (DISCARD)
【シーケンス番号】623055264 (0x252311A0)
【応答番号】1701643170 (0x656D03A2)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】1【RST】0【SYN】0【FIN】0
【ウィンドウ】1454 (0x05AE) バイト
【チェックサム】0x000B (OK)
【緊急ポインタ】0
【オプション】なし

---【データ】100 (0x0064) バイト --------------------------------- SJIS -------
0000  68 65 6C 6C 6F 00 00 00 - 00 00 05 A2 00 06 00 05  hello......「....
0010  57 61 69 74 57 72 69 74 - 65 43 6F 6D 70 6C 65 74  WaitWriteComplet
0020  65 00 00 00 00 00 00 00 - 04 00 00 09 25 23 11 A0  e...........%#..
0030  65 6D 03 A2 50 18 05 AE - D4 A6 00 00 00 00 00 00  em.「P..ョヤヲ......
0040  50 72 53 74 72 28 20 22 - 67 65 74 20 2F 2E 5C 72  PrStr( "get /.\r
0050  5C 6E 22 20 29 3B 0D 0A - 20 20 20 20 57 72 69 74  \n" );..    Writ
0060  65 28 20 6E                                        e( n

全然送信が進みません。
しかし極偶に成功したりします。同じ内容なのに???。※上の解析結果は、同じ内容での失敗と成功例です。

まあ一応970bytesでもやってみますか。
<< パケット 507 >>
--- TCPヘッダ [1024] → [9] -------------------------------------------------
【発信元ポート番号】1024 
【発信先ポート番号】9 (DISCARD)
【シーケンス番号】523522464 (0x1F3451A0)
【応答番号】2341297110 (0x8B8D5BD6)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】1【RST】0【SYN】0【FIN】0
【ウィンドウ】1454 (0x05AE) バイト
【チェックサム】0xF85A (NG)
【緊急ポインタ】0
【オプション】なし

---【データ】970 (0x03CA) バイト --------------------------------- SJIS -------
0000  68 65 6C 6C 6F 00 00 00 - 00 00 05 09 00 04 00 03  hello...........
0010  00 00 00 02 00 00 00 05 - C0 A8 01 1E 00 0C 00 0B  ........タィ......
0020  02 05 04 18 00 00 00 00 - 00 00 00 00 20 00 39 98  ............ .9.
0030  03 CA 04 00 00 09 00 00 - C0 A8 01 1E 1F 34 51 A0  .ハ......タィ...4Q.
0040  8B 8D 5B D6 00 00 00 00 - 07 0E 0D 01 00 07 00 06  牛[ヨ............
0050  02 69 00 02 00 00 04 73 - 6F 63 00 01 05 04 64 69  .i.....soc....di
0060  70 00 04 C0 A8 01 1E 00 - 00 06 00 05 31 39 32 2E  p..タィ.......192.
0070  31 36 38 2E 31 2E 33 30 - 00 20 00 39 9E 0C 00 00  168.1.30. .9....
0080  00 06 00 05 57 61 69 74 - 57 72 69 74 65 43 6F 6D  ....WaitWriteCom
0090  70 6C 65 74 65 00 00 00 - 00 06 00 05 04 00 00 09  plete...........
00A0  1F 34 51 A0 8B 8D 5B D6 - 50 18 05 AE F8 5A 00 00  .4Q.牛[ヨP..ョ..
00B0  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
00C0  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
00D0  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
00E0  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
00F0  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0100  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0110  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0120  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0130  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0140  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0150  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0160  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0170  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0180  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0190  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
01A0  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
01B0  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
01C0  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
01D0  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
01E0  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
01F0  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0200  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0210  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0220  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0230  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0240  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0250  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0260  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0270  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0280  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0290  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
02A0  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
02B0  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
02C0  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
02D0  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
02E0  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
02F0  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0300  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0310  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0320  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0330  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0340  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0350  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0360  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0370  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0380  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
0390  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
03A0  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
03B0  00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00  ................
03C0  00 00 00 00 00 00 00 00 - 00 00                    ..........

orzワシだけか?、きっとワシだけなんだろうな。


マスタリングTCP/IP 入門編 第4版

マスタリングTCP/IP 入門編 第4版

  • 作者: 竹下 隆史
  • 出版社/メーカー: オーム社
  • 発売日: 2007/02/24
  • メディア: 大型本



詳解TCP/IP〈Vol.1〉プロトコル

詳解TCP/IP〈Vol.1〉プロトコル

  • 作者: W.リチャード スティーヴンス
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2000/12
  • メディア: 単行本



マスタリングTCP/IP 応用編

マスタリングTCP/IP 応用編

  • 作者: Philip Miller
  • 出版社/メーカー: オーム社
  • 発売日: 1998/05
  • メディア: 単行本



したらばワシもSilentCでTCPをやってみよう [SilentC]

noritanさんの所でSilentCの関数リストを作成されて居られたのでフムフムと参考にさせて頂いたのですが、その中の”GetDefMtu”と言う関数に目が止まりました。今までUDPしか使っていなかったので、こんな関数が有る事に全然気付きませんでした。

”Mtu”って、あのMTUですよね。通常MTUはIPデータグラム全体の最大長を言っており、MSSとはMTU-40=MSSの関係が有ります。※MSSは最大長なので、実際のデータ長はもっと小さくなる可能性が有りますが。

”GetDefMtu”の2番目の引数に0を入れて置くと、戻り値として現在のMTUを返してくれる様です。そこでそれを表示させてみると、
DisMTU()
{
  char soc = CreateSocket( 1 );
  int mtu = GetDefMtu( soc, 0 );
  PrNum( mtu ); 
  CloseSocket( soc );
}

576ではなく1454と言う数字が返って来ました。これって、、、1454と言う数字の出自ですが、もしかしてフレッツADSLのMTU?。(※576と言うのは、オプションの交換をしない為に、PC側はデフォルトのMSS値である536を使うから、それを見越しているのではと期待していた。)
ではMTUを変化させてみると、
SetMTU()
{
  char soc = CreateSocket( 1 );
  GetDefMtu( soc, 1500 );
  int mtu = GetDefMtu( soc, 0 );
  PrNum( mtu ); 
  CloseSocket( soc );
}

今度は1500に設定できました。1500はEthernet上の最大です。
前にSilentCはコネクション時にオプションの交換を行っていないと書いた訳ですが、
http://hamayan.blog.so-net.ne.jp/2008-09-14-2
もしかしてこれでオプションを交換するようになるか!と思い、物凄く出鱈目なhttpサーバーを書いてみました。
ポート番号は8080にしています。内部でループしていないので、一回リクエストに答えたら終了します。
http()
{
  char soc = CreateSocket( 1 );
  char newsoc,*buf;
  int len;

  GetDefMtu( soc, 1500 );
  Bind( soc, 8080, 1 );
  newsoc = Accept( soc, -1 );
  len = Read( newsoc, -1 );
  if( len == -3 )
  {
    PrStr( "closed by other.\r\n" );
    CloseSocket( newsoc );
    return;
  }
  buf = GetReceiveBuffer( newsoc, 1 );
  if( StrStr( buf, "GET /" ) != 0 )
  {
    PrStr( "get /.\r\n" );
    Write( newsoc, "hello world", 11 );
    WaitWriteComplete( newsoc );
  }
  MemoryFree( buf );
  CloseSocket( newsoc );
}

結果は、ブラウザ上には無事”hello world”が表示されました。パケットをキャプチャしてみるとコネクションの所は、(※全部掲載すると長いので、TCPヘッダーとデータの一部のみ)
<< パケット 1 >>
--- TCPヘッダ [1546] → [8080] ----------------------------------------------
【発信元ポート番号】1546 
【発信先ポート番号】8080 
【シーケンス番号】906374635 (0x36062DEB)
【応答番号】0 (0x00000000)
【データオフセット】28 (0x1C)
【フラグ】【URG】0【ACK】0【PSH】0【RST】0【SYN】1【FIN】0
【ウィンドウ】16384 (0x4000) バイト
【チェックサム】0x35BF (OK)
【緊急ポインタ】0
【オプション】
【オプション番号】2 (最大受信セグメント長 = 1460 (0x05B4) バイト)
【オプション番号】1 (オペレーションなし)
【オプション番号】1 (オペレーションなし)
【オプション番号】4 (SACK許可)

<< パケット 2 >>
--- TCPヘッダ [8080] → [1546] ----------------------------------------------
【発信元ポート番号】8080 
【発信先ポート番号】1546 
【シーケンス番号】441227935 (0x1A4C9A9F)
【応答番号】906374636 (0x36062DEC)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】0【RST】0【SYN】1【FIN】0
【ウィンドウ】1500 (0x05DC) バイト
【チェックサム】0xE7A9 (OK)
【緊急ポインタ】0
【オプション】なし

<< パケット 3 >>
--- TCPヘッダ [1546] → [8080] ----------------------------------------------
【発信元ポート番号】1546 
【発信先ポート番号】8080 
【シーケンス番号】906374636 (0x36062DEC)
【応答番号】441227936 (0x1A4C9AA0)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】0【RST】0【SYN】0【FIN】0
【ウィンドウ】16616 (0x40E8) バイト
【チェックサム】0xAC9E (OK)
【緊急ポインタ】0
【オプション】なし

あれ!、やっぱりオプションは交換しないみたいです。それより何故かWindowサイズを1500と答えています???。
続いてESTABLISHED中と後、
<< パケット 4 >>
--- TCPヘッダ [1546] → [8080] ----------------------------------------------
【発信元ポート番号】1546 
【発信先ポート番号】8080 
【シーケンス番号】906374636 (0x36062DEC)
【応答番号】441227936 (0x1A4C9AA0)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】1【RST】0【SYN】0【FIN】0
【ウィンドウ】16616 (0x40E8) バイト
【チェックサム】0x4BEE (OK)
【緊急ポインタ】0
【オプション】なし

---【データ】394 (0x018A) バイト --------------------------------- SJIS -------
0000  47 45 54 20 2F 20 48 54 - 54 50 2F 31 2E 31 0D 0A  GET / HTTP/1.1..
0010  55 73 65 72 2D 41 67 65 - 6E 74 3A 20 4F 70 65 72  User-Agent: Oper

<< パケット 5 >>
--- TCPヘッダ [8080] → [1546] ----------------------------------------------
【発信元ポート番号】8080 
【発信先ポート番号】1546 
【シーケンス番号】441227936 (0x1A4C9AA0)
【応答番号】906375030 (0x36062F76)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】0【RST】0【SYN】0【FIN】0
【ウィンドウ】1500 (0x05DC) バイト
【チェックサム】0xE620 (OK)
【緊急ポインタ】0
【オプション】なし

<< パケット 6 >>
--- TCPヘッダ [8080] → [1546] ----------------------------------------------
【発信元ポート番号】8080 
【発信先ポート番号】1546 
【シーケンス番号】441227936 (0x1A4C9AA0)
【応答番号】906375030 (0x36062F76)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】1【RST】0【SYN】0【FIN】0
【ウィンドウ】1500 (0x05DC) バイト
【チェックサム】0x543F (OK)
【緊急ポインタ】0
【オプション】なし

---【データ】11 (0x000B) バイト ---------------------------------- SJIS -------
0000  68 65 6C 6C 6F 20 77 6F - 72 6C 64                 hello world

<< パケット 7 >>
--- TCPヘッダ [1546] → [8080] ----------------------------------------------
【発信元ポート番号】1546 
【発信先ポート番号】8080 
【シーケンス番号】906375030 (0x36062F76)
【応答番号】441227947 (0x1A4C9AAB)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】0【RST】0【SYN】0【FIN】0
【ウィンドウ】16605 (0x40DD) バイト
【チェックサム】0xAB14 (OK)
【緊急ポインタ】0
【オプション】なし

<< パケット 8 >>
--- TCPヘッダ [8080] → [1546] ----------------------------------------------
【発信元ポート番号】8080 
【発信先ポート番号】1546 
【シーケンス番号】441227947 (0x1A4C9AAB)
【応答番号】906375030 (0x36062F76)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】0【RST】0【SYN】0【FIN】1
【ウィンドウ】1500 (0x05DC) バイト
【チェックサム】0xE614 (OK)
【緊急ポインタ】0
【オプション】なし

<< パケット 9 >>
--- TCPヘッダ [1546] → [8080] ----------------------------------------------
【発信元ポート番号】1546 
【発信先ポート番号】8080 
【シーケンス番号】906375030 (0x36062F76)
【応答番号】441227948 (0x1A4C9AAC)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】0【RST】0【SYN】0【FIN】0
【ウィンドウ】16605 (0x40DD) バイト
【チェックサム】0xAB13 (OK)
【緊急ポインタ】0
【オプション】なし

<< パケット 10 >>
--- TCPヘッダ [1546] → [8080] ----------------------------------------------
【発信元ポート番号】1546 
【発信先ポート番号】8080 
【シーケンス番号】906375030 (0x36062F76)
【応答番号】441227948 (0x1A4C9AAC)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】0【RST】0【SYN】0【FIN】1
【ウィンドウ】16605 (0x40DD) バイト
【チェックサム】0xAB12 (OK)
【緊急ポインタ】0
【オプション】なし

<< パケット 11 >>
--- TCPヘッダ [8080] → [1546] ----------------------------------------------
【発信元ポート番号】8080 
【発信先ポート番号】1546 
【シーケンス番号】441227948 (0x1A4C9AAC)
【応答番号】906375031 (0x36062F77)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】0【RST】0【SYN】0【FIN】0
【ウィンドウ】1500 (0x05DC) バイト
【チェックサム】0xE613 (OK)
【緊急ポインタ】0
【オプション】なし

無事データの交換からコネクションの切断まで完了しています。ブラウザからは394bytesのデータが送られているのですが、SilentC側の受信バッファはその程度のデータにはものともせず、やっぱりWindowサイズが1500bytesです。
ちなみにPC側は11bytes受けたら、きっちりその分減っています。

実はこの後httpサーバーアプリケーションは停止しているにも関わらず、すっかり忘れてブラウザのリロードボタンを押してしまいました。まあコネクションを受け付けない状態になっている筈なので、こう言った場合はRSTを返してくるでしょう、、、あれ???。
<< パケット 12 >>
--- TCPヘッダ [1547] → [8080] ----------------------------------------------
【発信元ポート番号】1547 
【発信先ポート番号】8080 
【シーケンス番号】3462719371 (0xCE64E78B)
【応答番号】0 (0x00000000)
【データオフセット】28 (0x1C)
【フラグ】【URG】0【ACK】0【PSH】0【RST】0【SYN】1【FIN】0
【ウィンドウ】16384 (0x4000) バイト
【チェックサム】0xE3BE (OK)
【緊急ポインタ】0
【オプション】
【オプション番号】2 (最大受信セグメント長 = 1460 (0x05B4) バイト)
【オプション番号】1 (オペレーションなし)
【オプション番号】1 (オペレーションなし)
【オプション番号】4 (SACK許可)

<< パケット 13 >>
--- TCPヘッダ [8080] → [1547] ----------------------------------------------
【発信元ポート番号】8080 
【発信先ポート番号】1547 
【シーケンス番号】484341600 (0x1CDE7760)
【応答番号】3462719372 (0xCE64E78C)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】0【RST】0【SYN】1【FIN】0
【ウィンドウ】1500 (0x05DC) バイト
【チェックサム】0xB656 (OK)
【緊急ポインタ】0
【オプション】なし

<< パケット 14 >>
--- TCPヘッダ [1547] → [8080] ----------------------------------------------
【発信元ポート番号】1547 
【発信先ポート番号】8080 
【シーケンス番号】3462719372 (0xCE64E78C)
【応答番号】484341601 (0x1CDE7761)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】0【RST】0【SYN】0【FIN】0
【ウィンドウ】16616 (0x40E8) バイト
【チェックサム】0x7B4B (OK)
【緊急ポインタ】0
【オプション】なし

<< パケット 15 >>
--- TCPヘッダ [1547] → [8080] ----------------------------------------------
【発信元ポート番号】1547 
【発信先ポート番号】8080 
【シーケンス番号】3462719372 (0xCE64E78C)
【応答番号】484341601 (0x1CDE7761)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】1【RST】0【SYN】0【FIN】0
【ウィンドウ】16616 (0x40E8) バイト
【チェックサム】0xC99A (OK)
【緊急ポインタ】0
【オプション】なし

---【データ】437 (0x01B5) バイト --------------------------------- SJIS -------
0000  47 45 54 20 2F 20 48 54 - 54 50 2F 31 2E 31 0D 0A  GET / HTTP/1.1..
0010  55 73 65 72 2D 41 67 65 - 6E 74 3A 20 4F 70 65 72  User-Agent: Oper

<< パケット 16 >>
--- TCPヘッダ [8080] → [1547] ----------------------------------------------
【発信元ポート番号】8080 
【発信先ポート番号】1547 
【シーケンス番号】484341601 (0x1CDE7761)
【応答番号】3462719809 (0xCE64E941)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】0【RST】0【SYN】0【FIN】0
【ウィンドウ】1500 (0x05DC) バイト
【チェックサム】0xB4A2 (OK)
【緊急ポインタ】0
【オプション】なし

コネクション受け付けちゃったので、ブラウザはリクエストを発行し、SilentCはちゃんと受け取ってしまいました、、。
ですが、その後当然ながら”hello World”は返して来ません。

ブラウザはずっと受信待ち状態になっているので、仕方が無いのでバツボタンでコネクション切断です。
<< パケット 17 >>
--- TCPヘッダ [1547] → [8080] ----------------------------------------------
【発信元ポート番号】1547 
【発信先ポート番号】8080 
【シーケンス番号】3462719809 (0xCE64E941)
【応答番号】484341601 (0x1CDE7761)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】0【RST】0【SYN】0【FIN】1
【ウィンドウ】16616 (0x40E8) バイト
【チェックサム】0x7995 (OK)
【緊急ポインタ】0
【オプション】なし

<< パケット 18 >>
--- TCPヘッダ [8080] → [1547] ----------------------------------------------
【発信元ポート番号】8080 
【発信先ポート番号】1547 
【シーケンス番号】484341601 (0x1CDE7761)
【応答番号】3462719810 (0xCE64E942)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】0【RST】0【SYN】0【FIN】0
【ウィンドウ】1500 (0x05DC) バイト
【チェックサム】0xB4A1 (OK)
【緊急ポインタ】0
【オプション】なし

<< パケット 19 >>
--- TCPヘッダ [8080] → [1547] ----------------------------------------------
【発信元ポート番号】8080 
【発信先ポート番号】1547 
【シーケンス番号】484341601 (0x1CDE7761)
【応答番号】3462719810 (0xCE64E942)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】0【RST】0【SYN】0【FIN】1
【ウィンドウ】1500 (0x05DC) バイト
【チェックサム】0xB4A0 (OK)
【緊急ポインタ】0
【オプション】なし

<< パケット 20 >>
--- TCPヘッダ [1547] → [8080] ----------------------------------------------
【発信元ポート番号】1547 
【発信先ポート番号】8080 
【シーケンス番号】3462719810 (0xCE64E942)
【応答番号】484341602 (0x1CDE7762)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】0【RST】0【SYN】0【FIN】0
【ウィンドウ】16616 (0x40E8) バイト
【チェックサム】0x7994 (OK)
【緊急ポインタ】0
【オプション】なし

切断はできるようです。

さて、問題はここから。
再度telnetでhttp出鱈目サーバーを起動し、ブラウザからアクセスしてみます。
<< パケット 3 >>
--- TCPヘッダ [1555] → [8080] ----------------------------------------------
【発信元ポート番号】1555 
【発信先ポート番号】8080 
【シーケンス番号】2268105760 (0x87308C20)
【応答番号】0 (0x00000000)
【データオフセット】28 (0x1C)
【フラグ】【URG】0【ACK】0【PSH】0【RST】0【SYN】1【FIN】0
【ウィンドウ】16384 (0x4000) バイト
【チェックサム】0x8656 (OK)
【緊急ポインタ】0
【オプション】
【オプション番号】2 (最大受信セグメント長 = 1460 (0x05B4) バイト)
【オプション番号】1 (オペレーションなし)
【オプション番号】1 (オペレーションなし)
【オプション番号】4 (SACK許可)

<< パケット 4 >>
--- TCPヘッダ [1555] → [8080] ----------------------------------------------
【発信元ポート番号】1555 
【発信先ポート番号】8080 
【シーケンス番号】2268105760 (0x87308C20)
【応答番号】0 (0x00000000)
【データオフセット】28 (0x1C)
【フラグ】【URG】0【ACK】0【PSH】0【RST】0【SYN】1【FIN】0
【ウィンドウ】16384 (0x4000) バイト
【チェックサム】0x8656 (OK)
【緊急ポインタ】0
【オプション】
【オプション番号】2 (最大受信セグメント長 = 1460 (0x05B4) バイト)
【オプション番号】1 (オペレーションなし)
【オプション番号】1 (オペレーションなし)
【オプション番号】4 (SACK許可)

<< パケット 5 >>
--- TCPヘッダ [1555] → [8080] ----------------------------------------------
【発信元ポート番号】1555 
【発信先ポート番号】8080 
【シーケンス番号】2268105760 (0x87308C20)
【応答番号】0 (0x00000000)
【データオフセット】28 (0x1C)
【フラグ】【URG】0【ACK】0【PSH】0【RST】0【SYN】1【FIN】0
【ウィンドウ】16384 (0x4000) バイト
【チェックサム】0x8656 (OK)
【緊急ポインタ】0
【オプション】
【オプション番号】2 (最大受信セグメント長 = 1460 (0x05B4) バイト)
【オプション番号】1 (オペレーションなし)
【オプション番号】1 (オペレーションなし)
【オプション番号】4 (SACK許可)

もう、こちらからの接続要求には全く応じません。RSTも来ません。ブラウザは接続を諦めてしまいました。

マスタリングTCP/IP 入門編 第4版

マスタリングTCP/IP 入門編 第4版

  • 作者: 竹下 隆史
  • 出版社/メーカー: オーム社
  • 発売日: 2007/02/24
  • メディア: 大型本



詳解TCP/IP〈Vol.1〉プロトコル

詳解TCP/IP〈Vol.1〉プロトコル

  • 作者: W.リチャード スティーヴンス
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2000/12
  • メディア: 単行本



SilentCのhttpサーバー [SilentC]

某所で、Interface誌付録基板へtelnetでの接続は可能だが、ブラウザでアクセスすると「サーバーが見つからない」云々のメッセージが出てしまい、えらい困ったと言う話になっています。
http://micon.arrow.jp/modules/newbb/viewtopic.php?topic_id=868&forum=1&viewmode=flat&order=ASC&start=30

今回は別にこの事を解決するとかではなく、httpサーバーにtelnetで接続した場合にどうなるのかを試してみました。
普通telnetクライアントはtelnetのサーバー(ポート番号23)に接続したりしますが、勿論別のポート番号にも接続可能で、ネットワークアプリケーションの簡易的な動作確認にも使用できます。

例えばWindowsのコマンドプロンプトで以下の様にタイプします。
telnet 192.168.1.100 80
するとhttpサーバーはコネクションを受け入れてくれて、それ以降のメソッド待ちとなります。試しに適当なhttpサーバーに接続してみてください。
telnetでは接続完了後、入出力待ち画面となっていますので、以下の様にタイプします。
GET /
※エコーバックされないので、こちらから送った文字は見えません。
これでindex.htmかindex.htmlまたはindex.shtmlなどが存在すればそのファイルの内容を、無ければエラー情報を送り返してくれるでしょう。相手はWindows版のApacheです。
x-ctu_09.png


では同じ事をSilentCのhttpサーバーに行ってみます。
x-ctu_10.png
”G”をタイプしたとたんいきなり切断されてしまいました。

telnetクライアントの様に人間がタイプしたデータを転送する場合、どうしても人間のタイプのスピードが遅いので、1文字、1文字パケットで送っているのが実情です。「GET /」までを一気に送る事は人間には無理でしょう。
以下にPacMonでキャプチャして、パケットの解析を行った出力を貼って置きます。なお、全部の情報を載せると長いので、TCPヘッダー、TCPデータのみ掲載しています。
※解析結果をそのまま掲載しているので、半角カナが使われています。正しく表示できない環境もあるかもしれません。
<< パケット 1 >>
--- TCPヘッダ [1464] → [80] ------------------------------------------------
【発信元ポート番号】1464 
【発信先ポート番号】80 (WWW)
【シーケンス番号】2716876110 (0xA1F03D4E)
【応答番号】0 (0x00000000)
【データオフセット】28 (0x1C)
【フラグ】【URG】0【ACK】0【PSH】0【RST】0【SYN】1【FIN】0
【ウィンドウ】16384 (0x4000) バイト
【チェックサム】0xDA05 (OK)
【緊急ポインタ】0
【オプション】
【オプション番号】2 (最大受信セグメント長 = 1460 (0x05B4) バイト)
【オプション番号】1 (オペレーションなし)
【オプション番号】1 (オペレーションなし)
【オプション番号】4 (SACK許可)

<< パケット 2 >>
--- TCPヘッダ [80] → [1464] ------------------------------------------------
【発信元ポート番号】80 (WWW)
【発信先ポート番号】1464 
【シーケンス番号】559858079 (0x215EC19F)
【応答番号】2716876111 (0xA1F03D4F)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】0【RST】0【SYN】1【FIN】0
【ウィンドウ】1454 (0x05AE) バイト
【チェックサム】0x5E0C (OK)
【緊急ポインタ】0
【オプション】なし

<< パケット 3 >>
--- TCPヘッダ [1464] → [80] ------------------------------------------------
【発信元ポート番号】1464 
【発信先ポート番号】80 (WWW)
【シーケンス番号】2716876111 (0xA1F03D4F)
【応答番号】559858080 (0x215EC1A0)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】0【RST】0【SYN】0【FIN】0
【ウィンドウ】16616 (0x40E8) バイト
【チェックサム】0x22D3 (OK)
【緊急ポインタ】0
【オプション】なし

<< パケット 4 >>
--- TCPヘッダ [1464] → [80] ------------------------------------------------
【発信元ポート番号】1464 
【発信先ポート番号】80 (WWW)
【シーケンス番号】2716876111 (0xA1F03D4F)
【応答番号】559858080 (0x215EC1A0)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】1【RST】0【SYN】0【FIN】0
【ウィンドウ】16616 (0x40E8) バイト
【チェックサム】0xDBC9 (OK)
【緊急ポインタ】0
【オプション】なし

---【データ】1 (0x0001) バイト ----------------------------------- SJIS -------
0000  47                                                 G

<< パケット 5 >>
--- TCPヘッダ [80] → [1464] ------------------------------------------------
【発信元ポート番号】80 (WWW)
【発信先ポート番号】1464 
【シーケンス番号】559858080 (0x215EC1A0)
【応答番号】2716876112 (0xA1F03D50)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】0【RST】0【SYN】0【FIN】0
【ウィンドウ】1454 (0x05AE) バイト
【チェックサム】0x5E0C (OK)
【緊急ポインタ】0
【オプション】なし

<< パケット 6 >>
--- TCPヘッダ [80] → [1464] ------------------------------------------------
【発信元ポート番号】80 (WWW)
【発信先ポート番号】1464 
【シーケンス番号】559858080 (0x215EC1A0)
【応答番号】2716876112 (0xA1F03D50)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】0【RST】0【SYN】0【FIN】1
【ウィンドウ】1454 (0x05AE) バイト
【チェックサム】0x5E0B (OK)
【緊急ポインタ】0
【オプション】なし

<< パケット 7 >>
--- TCPヘッダ [1464] → [80] ------------------------------------------------
【発信元ポート番号】1464 
【発信先ポート番号】80 (WWW)
【シーケンス番号】2716876112 (0xA1F03D50)
【応答番号】559858081 (0x215EC1A1)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】0【RST】0【SYN】0【FIN】0
【ウィンドウ】16616 (0x40E8) バイト
【チェックサム】0x22D1 (OK)
【緊急ポインタ】0
【オプション】なし

<< パケット 8 >>
--- TCPヘッダ [1464] → [80] ------------------------------------------------
【発信元ポート番号】1464 
【発信先ポート番号】80 (WWW)
【シーケンス番号】2716876112 (0xA1F03D50)
【応答番号】559858081 (0x215EC1A1)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】0【RST】0【SYN】0【FIN】1
【ウィンドウ】16616 (0x40E8) バイト
【チェックサム】0x22D0 (OK)
【緊急ポインタ】0
【オプション】なし

<< パケット 9 >>
--- TCPヘッダ [80] → [1464] ------------------------------------------------
【発信元ポート番号】80 (WWW)
【発信先ポート番号】1464 
【シーケンス番号】559858081 (0x215EC1A1)
【応答番号】2716876113 (0xA1F03D51)
【データオフセット】20 (0x14)
【フラグ】【URG】0【ACK】1【PSH】0【RST】0【SYN】0【FIN】0
【ウィンドウ】1454 (0x05AE) バイト
【チェックサム】0x5E0A (OK)
【緊急ポインタ】0
【オプション】なし

別にだからどうと言った話ではなく、「人によって実装が異なるのは面白いなぁ!」と言う話でした。

※それとは別に、SilentCはコネクション時にオプションを返さない仕様みたいないので、コネクション時に相手MSSを取得する様に作られている方は、注意が必要かもしれません。

あれの開発記 31ページ目 饒舌なSilentC [SilentC]

Img_0672.jpgと言う訳でSilentC側には全然問題無かったので、修正版のDT2Numを再アップ。
これで本番当日に何度も電源入り切りをせずに済みます。noritanさん有難う。
※あれー、頻度は落ちたけれど、やっぱりまだ固まるなぁ。


int DT2Num( char *s, char soc )
{
  int ret;
  char *buf = MemoryAlloc( 4 );
  char *p,*src = MemoryAlloc( 30 );

  if( (ret = dg_daytime_cli( s, src, soc )) <= 0 )
  {
    MemoryFree( buf );
    MemoryFree( src );
    return ret;
  }
  p = src;
  BufCopy( buf, p, 4 ); 
  *(buf + 3) = 0;
  if( StrCmp( buf, "Sun" ) == 0 ){ weeks = 0;}
  else if( StrCmp( buf, "Mon" ) == 0 ){ weeks = 1;}
  else if( StrCmp( buf, "Tue" ) == 0 ){ weeks = 2;}
  else if( StrCmp( buf, "Wed" ) == 0 ){ weeks = 3;}
  else if( StrCmp( buf, "Thu" ) == 0 ){ weeks = 4;}
  else if( StrCmp( buf, "Fri" ) == 0 ){ weeks = 5;}
  else if( StrCmp( buf, "Sat" ) == 0 ){ weeks = 6;}
  p = p + 4;

  BufCopy( buf, p, 4 ); 
  *(buf + 3) = 0;
  if( StrCmp( buf, "Jan" ) == 0 ){ mons = 1; }
  else if( StrCmp( buf, "Feb" ) == 0 ){ mons = 2; }
  else if( StrCmp( buf, "Mar" ) == 0 ){ mons = 3; }
  else if( StrCmp( buf, "Apr" ) == 0 ){ mons = 4; }
  else if( StrCmp( buf, "May" ) == 0 ){ mons = 5; }
  else if( StrCmp( buf, "Jun" ) == 0 ){ mons = 6; }
  else if( StrCmp( buf, "Jul" ) == 0 ){ mons = 7; }
  else if( StrCmp( buf, "Aug" ) == 0 ){ mons = 8; }
  else if( StrCmp( buf, "Sep" ) == 0 ){ mons = 9; }
  else if( StrCmp( buf, "Oct" ) == 0 ){ mons = 10; }
  else if( StrCmp( buf, "Nov" ) == 0 ){ mons = 11; }
  else if( StrCmp( buf, "Dec" ) == 0 ){ mons = 12; }
  p = p + 4;
  MemoryFree( buf );

  days = *p++ - '0';
  if( *p != ' ' )
  {
    days *= 10;
    days += *p++ - '0';
  }
  p++;

  hours = *p++ - '0';
  if( *p != ':' )
  {
    hours *= 10;
    hours += *p++ - '0';
  }
  p++;

  mins = *p++ - '0';
  if( *p != ':' )
  {
    mins *= 10;
    mins += *p++ - '0';
  }
  p++;

  secs = *p++ - '0';
  if( *p != ' ' )
  {
    secs *= 10;
    secs += *p++ - '0';
  }
  p++;

  p += 2;
  years = *p++ - '0';
  years *= 10;
  years += *p - '0';

  MemoryFree( src );
  return 1;
}

あれの開発記 30ページ目 沈黙のSilentC [SilentC]

Img_0672.jpgUDPで通信を連続して行っていると、数分で突如SilentCが反応しなくなる。この時このボードに向けてPINGを打っても応答無しとなる。(※応答を返さないし、LED2も点滅しない。)
うーん、困ったなぁ。

特にスクリプトの中では無限ループに陥る様には記述していないし(多分)、特にアクションを起こさない場面では”SystemSleep”を入れているし。
そもそも別で動いている筈のPINGの応答等も止まっている所からしておかしい。
なんだろうね、内部的にデッドロックでもしているのかなぁ。


Main:
char years,mons,days,weeks,hours,mins,secs;
int temper,bright;

main( void )
{
#stop 0
  int len,mode;
  char c,*p;
  char *s_buf = MemoryAlloc( 128 );
  char *basic = MemoryAlloc( 32 );
  char soc = CreateSocket( 0 );

  SCI::HardFlowSet();
  mode = 0;
  for(;;)
  {
    while( (c = Getc( 0 )) > 0 )
    {
      if( c == 0x1b )
      {
        CloseSocket( soc );
        MemoryFree( basic );
        MemoryFree( s_buf );
        return;
      }
      else if( c == 0x02 )
      {
        mode = 1;
        len = 1;
        p = s_buf;
        *p++ = c;
      }
      else if( c == 0x03 )
      {
        if( mode == 1 )
        {
          len++;
          *p = c;
          if( *(s_buf + 3) == 0x01 && *(s_buf + 1) == netcfg::MyID() )
          {
            if( DTutil::DT2Num( "192.168.1.30", soc ) <= 0 )
            {
              CloseSocket( soc );
              Sleep( 10 );
              soc = CreateSocket( 0 );
            }
            else
            {
              temper = Analog::GetTemper();
              bright = Analog::GetBright();
              ResFrame( basic, *(s_buf + 2) );
              SCI::BlkSend( basic, 31 );
            }
          }
        }
        mode = 0;
      }
      else
      {
        if( mode == 1 )
        {
          len++;
          *p++ = c;
        }
      }
    }
    SystemSleep();
  }
  CloseSocket( soc );
  MemoryFree( basic );
  MemoryFree( s_buf );
}

ResFrame( char *buf, char did )
{
  *buf = 0x02;
  *(buf + 1) = did;
  *(buf + 2) = netcfg::MyID();
  *(buf + 3) = 0x01;
  *(buf + 4) = '1';
  *(buf + 5) = '6';
  DTutil::DtStr( buf + 6 );
  *(buf + 18) = ',';
  GetDigit( Analog::GetTemper(), buf + 19 );
  *(buf + 23) = ',';
  GetDigit( Analog::GetBright(), buf + 24 );
  strutil::CheckSum( buf + 28, buf + 1, 27 );
  *(buf + 30) = 0x03;
}

DTutil:
int dg_daytime_cli( char *s, char *dst, char soc )
{
  char *buf;
  long dip = GetIP( s );
  int len;
  len = SendTo( soc, dip, 13, "hello", 6 );
  if( len == 0 )
  {
    Sleep( 10 );
    if( (len = SendTo( soc, dip, 13, "hello", 6 )) <= 0 ) return len;
  }
  if( (len = RecvFrom( soc, 2 )) > 0 )
  {
    buf = GetReceiveBuffer( soc, 1 );
    BufCopy( dst, buf, 30 );
    MemoryFree( buf );
  }
  else return (-1);

  return 1;
}

int DT2Num( char *s, char soc )
{
  int ret;
  char *buf = MemoryAlloc( 4 );
  char *src = MemoryAlloc( 30 );

  if( (ret = dg_daytime_cli( s, src, soc )) <= 0 )
  {
    MemoryFree( buf );
    MemoryFree( src );
    return ret;
  }
  BufCopy( buf, src, 4 ); 
  *(buf + 3) = 0;
  if( StrCmp( buf, "Sun" ) == 0 ){ weeks = 0;}
  else if( StrCmp( buf, "Mon" ) == 0 ){ weeks = 1;}
  else if( StrCmp( buf, "Tue" ) == 0 ){ weeks = 2;}
  else if( StrCmp( buf, "Wed" ) == 0 ){ weeks = 3;}
  else if( StrCmp( buf, "Thu" ) == 0 ){ weeks = 4;}
  else if( StrCmp( buf, "Fri" ) == 0 ){ weeks = 5;}
  else if( StrCmp( buf, "Sat" ) == 0 ){ weeks = 6;}
  src = src + 4;

  BufCopy( buf, src, 4 ); 
  *(buf + 3) = 0;
  if( StrCmp( buf, "Jan" ) == 0 ){ mons = 1; }
  else if( StrCmp( buf, "Feb" ) == 0 ){ mons = 2; }
  else if( StrCmp( buf, "Mar" ) == 0 ){ mons = 3; }
  else if( StrCmp( buf, "Apr" ) == 0 ){ mons = 4; }
  else if( StrCmp( buf, "May" ) == 0 ){ mons = 5; }
  else if( StrCmp( buf, "Jun" ) == 0 ){ mons = 6; }
  else if( StrCmp( buf, "Jul" ) == 0 ){ mons = 7; }
  else if( StrCmp( buf, "Aug" ) == 0 ){ mons = 8; }
  else if( StrCmp( buf, "Sep" ) == 0 ){ mons = 9; }
  else if( StrCmp( buf, "Oct" ) == 0 ){ mons = 10; }
  else if( StrCmp( buf, "Nov" ) == 0 ){ mons = 11; }
  else if( StrCmp( buf, "Dec" ) == 0 ){ mons = 12; }
  src = src + 4;
  MemoryFree( buf );

  days = *src++ - '0';
  if( *src != ' ' )
  {
    days *= 10;
    days += *src++ - '0';
  }
  src++;

  hours = *src++ - '0';
  if( *src != ':' )
  {
    hours *= 10;
    hours += *src++ - '0';
  }
  src++;

  mins = *src++ - '0';
  if( *src != ':' )
  {
    mins *= 10;
    mins += *src++ - '0';
  }
  src++;

  secs = *src++ - '0';
  if( *src != ' ' )
  {
    secs *= 10;
    secs += *src++ - '0';
  }
  src++;

  src += 2;
  years = *src++ - '0';
  years *= 10;
  years += *src - '0';

  MemoryFree( src );
  return 1;
}

char *DtStr( char *dst )
{
  strutil::I2ASC02( dst, years );
  strutil::I2ASC02( dst + 2, mons );
  strutil::I2ASC02( dst + 4, days );
  strutil::I2ASC02( dst + 6, hours );
  strutil::I2ASC02( dst + 8, mins );
  strutil::I2ASC02( dst + 10, secs );
  *(dst + 12) = 0;

  return dst;
}


SCI:
void HardFlowSet( void )
{
  char *ptapar = 0x4010006E;
  *ptapar = 0;
}

void BlkSend( char *src, int size )
{
  char *setta = 0x4010003E;

  for( ; size > 0; size-- )
  {
    while( *setta & 0x02 ) SystemSleep();
    PrChar( *src++ );
  }
}

Analog:
int GetTemper( void ){ InitAd( 0x03 ); return GetAd( 0 ); }
int GetBright( void ){ InitAd( 0x03 ); return GetAd( 1 ); }

strutil:
char I2HEX01( int value )
{
  if( value <= 9 ) return value + '0';
  return value + 55;
}

void I2HEX02( char *dst, int value )
{
  *dst++ = I2HEX01( value / 16 );
  *dst = I2HEX01( value % 16 );
}

void I2ASC02( char *dst, int value )
{
  *dst++ = (value / 10) + '0';
  *dst = ( value % 10 ) + '0';
}

int CheckSum( char *dst, char *src, int size )
{
  int i,c_sum = 0;

  for( i = 0; i < size; i++ ) c_sum += *src++;
  c_sum = (-c_sum) & 0xff;
  I2HEX02( dst, c_sum );
  return c_sum;
}


あれの開発記 29ページ目 ARPの件、再び [SilentC]

投票感謝キャンペーンは以下のアドレスで行っています。
http://hamayan.blog.so-net.ne.jp/2008-09-01-2
Img_0672.jpgUDPでの一発目の送信で必ずこける話を以下のアドレスでやりましたが、
http://hamayan.blog.so-net.ne.jp/2008-08-31-4
実は最初の一回目だけではなかったと言う話です。

通常ARPキャッシュのデータには生存時間が設定され、古いデータは使われなくなります。
多分SilentCの生存時間は6分と思われますが、そこまで散々パケットの交換を行ってきているにも関わらず、6分経過すると自動的にARPキャッシュの該当データが無効となるのか、再びARP要求を行う為に、やはりそこでパケットは送出できず仕舞いとなります。
つまりUDPで送信する時は何時如何なる時も送信リザルトをチェックした方が良いと言う事になります。

※UDPはベストエフォートとは言え、原因が判っていてlostしてしまうのは、ちょっと使い辛いのではないかい?。

※同様の事がTCPでも起きる可能性が有るのだけれど、その場合タイムアウトして再送となるのかな。

※えーと、汎用OSによっては生存時間が切れた時点でUDPやTCPに関係無くARP要求を掛けて情報を更新している物もあります。なので特に汎用OS上でこう言った不都合を感じた事は無いと思います。SilentCのアルゴリズムは、6分経過後の最初のUDPなりTCPなりのパケットの送出に合わせてARP要求を行う様です。うーむ。

※ちなみにNavajoは、ARPキャッシュに情報が無かったり、古かったりした場合は、パケットの送出を一旦ペンディングしてからARP要求を掛けて、それを100ms置きに10回リトライを行い、まあ通常は数msで応答が帰ってきますので、ペンディングしたパケットを送出します。または、10回のリトライでも応答が無ければ、アプリケーション側に通知を行います。また、有効なIPパケットを受信した場合は、常にその情報をARPテーブルに格納し、生存時間の更新を行っていますので、パケットの交換が生存時間以内に連続して行われている場合は、自ら要求を掛ける事は無いです。


マスタリングTCP/IP 入門編 第4版

マスタリングTCP/IP 入門編 第4版

  • 作者: 竹下 隆史
  • 出版社/メーカー: オーム社
  • 発売日: 2007/02/24
  • メディア: 大型本



詳解TCP/IP〈Vol.1〉プロトコル

詳解TCP/IP〈Vol.1〉プロトコル

  • 作者: W.リチャード スティーヴンス
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2000/12
  • メディア: 単行本



この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。