SSブログ

HTML文書にGIFを埋め込んでみた [ColdFire V2]このエントリーを含むはてなブックマーク#

1990557

付録基板のhttpサーバは、SilentMoonというオペレーティング・システム上で動作していることがわかっています。 どのくらいの能力を持っているのか、確認してみましょう。

HTML文書は、これだ

HTML文書として用意したのは、これです。

<html><head>
<title>RiverSea</title>
<style>
table.board {text-align:center;}
table.board td {width:40px;height:40px;background:#0F0;}
</style>
</head><body>
<h1 style="text-align:center;">RiverSea</h1>
<form action="RiverSeaAction.htm" style="text-align:center;">
<table cellpadding="10" style="margin:0 auto;">
<td>
<table border="1" cellpadding="2" cellspacing="1" class="board">
<tr><th colspan="14"/></tr>
<tr>
<th rowspan="12"/><th/><th rowspan="12"/>
<th>A</th><th>B</th><th>C</th><th>D</th>
<th>E</th><th>F</th><th>G</th><th>H</th>
<th rowspan="12"/>
</tr>
<tr><th/><th colspan="8"/></tr>
<tr><th>1</th>
<td/><td/><td/><td/><td/><td/><td/><td/>
</tr>
<tr><th>2</th>
<td/><td/><td/><td/><td/><td/><td/><td/>
</tr>
<tr><th>3</th>
<td/><td/><td/><td/><td/><td/><td/><td/>
</tr>
<tr><th>4</th>
<td/><td/><td/>
<td><img src="W.gif"/></td>
<td><img src="B.gif"/></td>
<td/><td/><td/>
</tr>
<tr><th>5</th>
<td/><td/><td/>
<td><img src="B.gif"/></td>
<td><img src="W.gif"/></td>
<td/><td/><td/>
</tr>
<tr><th>6</th>
<td/><td/><td/><td/><td/><td/><td/><td/>
</tr>
<tr><th>7</th>
<td/><td/><td/><td/><td/><td/><td/><td/>
</tr>
<tr><th>8</th>
<td/><td/><td/><td/><td/><td/><td/><td/>
</tr>
<tr><th colspan="14"/></tr>
</table>
</td>
</form>
</body></html>

GIFファイルは、これだ

GIFファイルとして用意したのは、W.gifB.gifです。

表示できたかな?

WS000164.png

ブラウザでHTML文書を呼び出すと文書本体もGIF画像もうまく表示されました。

パケット・モニタで通信状況を観測する

それでは、どんな通信が飛んでいるのかをパケット・モニタで確認します。

#1	0.000000	192.168.1.2	192.168.1.10
	TCP	1538 > 80 [SYN] Seq=0 Win=16384 Len=0 MSS=1460
#2	0.000372	192.168.1.10	192.168.1.2
	TCP	80 > 1538 [SYN, ACK] Seq=0 Ack=1 Win=1454 Len=0
#3	0.000448	192.168.1.2	192.168.1.10
	TCP	1538 > 80 [ACK] Seq=1 Ack=1 Win=16616 Len=0

まずは、3ウェイ・ハンドシェイクから。

#4	0.007597	192.168.1.2	192.168.1.10
	TCP	1538 > 80 [PSH, ACK] Seq=1 Ack=1 Win=16616 Len=429
	HTTP	GET /RiverSeaTemplate.htm HTTP/1.1 
#5	0.008578	192.168.1.10	192.168.1.2
	TCP	80 > 1538 [ACK] Seq=1 Ack=430 Win=1454 Len=0
#6	0.012538	192.168.1.10	192.168.1.2
	TCP	80 > 1538 [PSH, ACK] Seq=1 Ack=430 Win=1454 Len=1377
	HTTP	HTTP/1.1 200 OK  (text/html)

まず、#4でブラウザからHTML文書が要求されます。 ColdFireは、#5で一旦受信確認を送り、続いて#6で要求されたHTML文書を送ります。

#7	0.072102	192.168.1.2	192.168.1.10
	TCP	1538 > 80 [PSH, ACK] Seq=430 Ack=1378 Win=16616 Len=435
	HTTP	GET /W.gif HTTP/1.1 
#8	0.073084	192.168.1.10	192.168.1.2
	TCP	80 > 1538 [ACK] Seq=1378 Ack=865 Win=1454 Len=0
#9	0.073135	192.168.1.10	192.168.1.2
	TCP	80 > 1538 [FIN, ACK] Seq=1378 Ack=865 Win=1454 Len=0
#10	0.073193	192.168.1.2	192.168.1.10
	TCP	1538 > 80 [ACK] Seq=865 Ack=1379 Win=16616 Len=0
#11	0.075050	192.168.1.2	192.168.1.10
	TCP	1538 > 80 [FIN, ACK] Seq=865 Ack=1379 Win=16616 Len=0
#12	0.075376	192.168.1.10	192.168.1.2
	TCP	80 > 1538 [ACK] Seq=1379 Ack=866 Win=1454 Len=0

続いて、ブラウザは、#7で同じポート番号を使い、GIFファイル W.gif を要求します。 これに対して、ColdFireは、#8で受信確認を送るのですが、すぐに#9で切断要求を出します。 これは、#4から#6でHTML文書の送信が終了したためであると思われます。 以下、#12まででこのコネクションは、終了します。

#13	0.080873	192.168.1.2	192.168.1.10
	TCP	1541 > 80 [SYN] Seq=0 Win=16384 Len=0 MSS=1460
#14	0.081243	192.168.1.10	192.168.1.2
	TCP	80 > 1541 [SYN, ACK] Seq=0 Ack=1 Win=1454 Len=0
#15	0.081336	192.168.1.2	192.168.1.10
	TCP	1541 > 80 [ACK] Seq=1 Ack=1 Win=16616 Len=0
#16	0.083014	192.168.1.2	192.168.1.10
	TCP	1542 > 80 [SYN] Seq=0 Win=16384 Len=0 MSS=1460
#17	0.083376	192.168.1.10	192.168.1.2
	TCP	80 > 1542 [SYN, ACK] Seq=0 Ack=1 Win=1454 Len=0
#18	0.083444	192.168.1.2	192.168.1.10
	TCP	1542 > 80 [ACK] Seq=1 Ack=1 Win=16616 Len=0

ブラウザは、再度GIFファイルを要求するためにコネクションを試みます。 ところが、今度は様子が違います。 ポート番号1541と1542の二つのポートからほぼ同時にコネクションを張ろうとしています。 ColdFireも、#14と#17で双方のポートに対してコネクションを張ったように見えます。 これがうまく働けば、ColdFireも「並行サーバ」であると言えるはずです。

#19	0.085585	192.168.1.2	192.168.1.10
	TCP	1541 > 80 [PSH, ACK] Seq=1 Ack=1 Win=16616 Len=435
	HTTP	GET /W.gif HTTP/1.1 
#20	0.086568	192.168.1.10	192.168.1.2
	TCP	80 > 1541 [ACK] Seq=1 Ack=436 Win=1454 Len=0
#21	0.087908	192.168.1.10	192.168.1.2
	TCP	80 > 1541 [PSH, ACK] Seq=1 Ack=436 Win=1454 Len=425
	HTTP	HTTP/1.1 200 OK  (GIF89a)

ブラウザは、まず#19でGIFファイル W.gif を要求します。 ColdFireも#20と#21でこれに応えます。

#22	0.091548	192.168.1.2	192.168.1.10
	TCP	1542 > 80 [PSH, ACK] Seq=1 Ack=1 Win=16616 Len=435
	HTTP	GET /B.gif HTTP/1.1 
#23	0.092544	192.168.1.10	192.168.1.2
	TCP	80 > 1542 [ACK] Seq=1 Ack=436 Win=1454 Len=0
#24	0.093880	192.168.1.10	192.168.1.2
	TCP	80 > 1542 [PSH, ACK] Seq=1 Ack=436 Win=1454 Len=415
	HTTP	HTTP/1.1 200 OK  (GIF89a)

ブラウザは、続いて#22でGIFファイル B.gif を要求します。 ColdFireは、#23と#24でこれに応えます。

#25	0.192704	192.168.1.2	192.168.1.10
	TCP	1541 > 80 [ACK] Seq=436 Ack=426 Win=16191 Len=0
#26	0.193082	192.168.1.10	192.168.1.2
	TCP	80 > 1541 [FIN, ACK] Seq=426 Ack=436 Win=1454 Len=0
#27	0.193163	192.168.1.2	192.168.1.10
	TCP	1541 > 80 [ACK] Seq=436 Ack=427 Win=16191 Len=0
#28	0.293303	192.168.1.2	192.168.1.10
	TCP	1542 > 80 [ACK] Seq=436 Ack=416 Win=16201 Len=0
#29	0.293723	192.168.1.10	192.168.1.2
	TCP	80 > 1542 [FIN, ACK] Seq=416 Ack=436 Win=1454 Len=0
#30	0.293837	192.168.1.2	192.168.1.10
	TCP	1542 > 80 [ACK] Seq=436 Ack=417 Win=16201 Len=0
#31	8.846858	192.168.1.2	192.168.1.10
	TCP	1542 > 80 [FIN, ACK] Seq=436 Ack=417 Win=16201 Len=0
#32	8.847122	192.168.1.2	192.168.1.10
	TCP	1541 > 80 [FIN, ACK] Seq=436 Ack=427 Win=16191 Len=0

二つのGIFファイルを送受信する間、二つのポートは共にコネクションされたままの状態です。 ブラウザが#25でポート1541の受信確認を送ると、#26でColdFireが切断を要求します。 これに対して、ブラウザは、#27と#32で切断を受諾しますが、それに対してColdeFireからは最後のACKが返ってきません。 これは、おかしいな。 ブラウザの切断受諾に8秒以上時間がかかっているのも妙です。

ブラウザは、#25のポート1541の受信確認の0.1秒後に#28でポート1542の受信確認を送ります。 ColdFireは、#29で切断を要求し、ブラウザが#30と#31で切断を受諾します。 これに対してもColdFireからは最後のACKが返ってきませんでした。

#33	11.257293	192.168.1.2	192.168.1.10
	TCP	1542 > 80 [FIN, ACK] Seq=436 Ack=417 Win=16201 Len=0
#34	11.257325	192.168.1.2	192.168.1.10
	TCP	1541 > 80 [FIN, ACK] Seq=436 Ack=427 Win=16191 Len=0

そのため、ブラウザは、双方のポートから最後の"FIN"を再送し続けるのですが、もうColdFireは、返答しません。 やっぱり、おかしいな。

本日の考察

  1. ブラウザが、複数のGETリクエストを同一のポートから出した、つまりコネクションを使い回しした場合、ColdFireは、二回目のリクエストに受信確認を出した後すぐにコネクションを切断してしまう。
  2. ColdFireのhttpサーバは、ブラウザからの要求に対して少なくとも二つコネクションを張ることが出来る。
  3. 複数のコネクションが張られたとき、コネクションの切断に必要なhttpサーバからのACKをColdFireは返さない。

TCP/IPの仕様として、どんな振る舞いがふさわしいのか理解していないので、ブラウザとColdFireのhttpサーバのどちらに問題があるのか、私には判断出来ません。

参考文献

Interface (インターフェース) 2008年 09月号 [雑誌]

Interface (インターフェース) 2008年 09月号 [雑誌]

  • 作者:
  • 出版社/メーカー: CQ出版
  • 発売日: 2008/07/25
  • メディア: 雑誌

nice!(0)  コメント(5)  トラックバック(0)  このエントリーを含むはてなブックマーク#

nice! 0

コメント 5

hamayan

おお!早速実験されている。

SilentCはHTTP 1.1と言っているのでブラウザ側はKeep Aliveが有効とみなして、切断を待たずに同一ポート番号から再びリクエストを発行しているにも関わらず、SilentCは切断処理に入ってしまう。
つまり基本的にHTTP 1.0を名乗るべきではないのかと。
これはTCP/IPの動作ではなくhttpプロトコルの動作ですね。

3.番はよく判らないですね
by hamayan (2008-09-30 23:47) 

hamayan

どっちかと言えばブラウザ側が8秒掛かっている点が気になりますね。

本来FINは切断を意味するのではなく、「もうこちらからは送るデータは無いよ!」と言う意味です。
なのでFINを送信後も受信は可能です。
お互いにFINを送信する事で、双方で送るデータが無くなったのだから切断しようと言う流れです。と言っても私もそこまで実装を作り込んではいませんが。

ブラウザのFINの送信が遅れているのは、まだ何か送るつもりなのでしょうか?。
それに対してSilentCはタイムアウトしてしまっている様な感じですか。

by hamayan (2008-10-01 00:12) 

noritan

やっぱり、HTTP/1.0と名乗る程度の実装だということですね。じゃあ、次はパッチを当ててみよう。

確かに、ブラウザが"FIN"を送るまでに8秒かかる理由は無いですね。GIFファイルの解析にそんなに時間がかかるとも思えない。ウィルスチェック?

ColdFireが送った#26と#29の"FIN"に対して、#27と#30で"ACK"が返ってきているのでColdFireは最後の"FIN"を待たずに、または時間切れでポートを閉じちゃったのだと思います。

ブラウザの"FIN"が遅れたのは、この後を考えて、HTMLにFORMタグを入れたことに理由があるのかも知れません。つまり、人間の反応が無いことを確認するために8秒間待っていたと。しかし、人間にとっては8秒間は短いな。それに、ブラウザがColdFireから到着した"FIN"を事実上、無視したことも解せない。

ColdFire「FINに対するACKが来たから、もうポート閉めちゃえ。」
ブラウザ「SUBMIT要求が無いからコネクションを切断しよう。」
ColdFire「FINが来たけど、このポートは無効だよね。棄てちゃオ。」
ブラウザ「FINを送ったのにACKが来ない。再送するか。」
ColdFire「FINが来たけど、このポートは無効だよね。棄てちゃオ。」
:
以下、続く

by noritan (2008-10-01 09:00) 

hamayan

htmlをコピーしてファイルにしてみました。
http://hamayan.ddo.jp/~hamayan/noritan.htm

うん、うん、これは楽しみだ。
オセロの前に3目並べはどうですか、名前をジョシュアとか付けて。
http://www.h2.dion.ne.jp/~mine/movie-0061.htm

by hamayan (2008-10-01 11:37) 

noritan

300baudの音響カプラで電話をかけてくる、Dr.Falkenの息子さんですね。

by noritan (2008-10-01 14:03) 

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

トラックバックの受付は締め切りました

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