2015年12月25日金曜日

Ether ShieldのW5100をSTM8Sから動かしてみる(7)TCP似非webサーバ

メリークリスマス.(メリーって何だろう?)

諸般の事情で家族で夕飯を食べれなかったため、家から歩いて2分ほどの「ノムネン」で夕食がてら奥さんと呑んだのですが、いつも混雑しているノムネンが今日はガラ空きでした.クリスマスイブのカップルはノムネンには来ないのか? 二次会でノムネンに来るカップルが居るかもと23時まで滞在しましたが、全てのカップルはホテルへチェックインしてしまったようで誰二人来店しませんでした.マスターの井上さんは早々と帰宅してしまうしw... クリスマスイブのカップルは恵比寿界隈で心と体を温め合っているのでしょうねぇ.
去年のクリスマスイブは「青の洞窟」効果によってノムネンの辺りにまで人が流れてきてたそうですが、今年は青の洞窟やらないのでホント静かなもんですわ.

------------
Ethernetの末端に置いたW5100を制御するために、webでW5100に接続してコマンドを与えたい.それがこの連載の目的です.そのためにW5100をweb serverとして立てたい.なのでW5100のTCPを実装し、かつserverモードで動かすのが最終型に近いです.その先は、TCP serverにHTTPのやりとりを実装すればより最終型に近づきます.

というわけで今回は、TCP serverでHTTPを送受信できるようにし、webブラウザでW5100に接続するところまでを動かします.

ところで、serverモードとclientモードはどう違うのか?

イメージを浮かべやすいのはserverモードだと思います.(下図の左側)
あらかじめW5100を起動し受信体勢(LISTEN)で待ち受けさせときます.clientはwebブラウザです.webブラウザのURLに例えば、
http://192.168.1.100:12340/
のように入力します.ここで192.168.1.100はW5100のIPアドレス、12340はW5100の待ちうけポート番号で、サンプルプログラムでそのように決め打ちしてあります.webブラウザがW5100に接続要求してW5100が接続許可するとデータ通信できます.通信が終わったら切断.あたりまえですがserverは先に起動していなくちゃいけません.

次にclientモードでは、下図右側のように、先んじてPCが起動(server)しているところへ、W5100が接続要求(client)します.以後同様.

以下は、serverモードで似非webサーバーを実装してみた結果ですが、webサーバですからTCPで通信する中身はHTTPのデータになります.

待ち受けしているW5100にwebブラウザが接続し、HTTPのやり取りをしているときのW5100の内部状態をUART経由でモニタしたのが以下です.なにやらいろいろとやり取りしているようで面白いです.
なお、今回のwebサーバはバカピーなのでいつもHello World!という応答しかしません.

STM8Sをリセット
   ↓
   中略
   ↓
(TCP 14 LISTEN)         W5100はTCP serverモードで待ち受け状態
(TCP 16 SYNRECV)       webブラウザから接続要求が来た
(TCP 17 ESTABLISHED)    W5100とwebブラウザが接続確立した
[TCP server recv] reg BYTE=356(0164)   ブラウザからW5100へ要求あり
GET / HTTP/1.1         ここから
Host: 192.168.1.100:12340
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ja,en-US;q=0.8,en;q=0.6     ここまで
[TCP server response]       W5100からブラウザへのレスポンス
HTTP/1.0 200 OK           ここから
Content-Type: text/html
Content-Length: 21
<h1>Hello World!</h1><HR>    ここまで   「Hello World!」が返答
     ↓
ブラウザにHello World!と表示される
     ↓
(TCP 1c CLOSE_WAIT)     ブラウザから切断要求が来た
(TCP 00 CLOSED)        W5100切断
(TCP 14 LISTEN)         再びW5100待ち受け状態へ
(TCP 16 SYNRECV)       webブラウザから接続要求が来た
(TCP 17 ESTABLISHED)    W5100とwebブラウザが接続確立した
[TCP server recv] reg BYTE=334(014e)   ブラウザからW5100へ届いた内容
GET /favicon.ico HTTP/1.1  ここから    faviconを送れという要求
Host: 192.168.1.100:12340
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36
Accept: */*
Referer: http://192.168.1.100:12340/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: ja,en-US;q=0.8,en;q=0.6     ここまで
[TCP server response]      W5100からブラウザへのレスポンス
HTTP/1.0 200 OK          ここから
Content-Type: text/html     
Content-Length: 21
<h1>Hello World!</h1><HR>  ここまで  バカピーなのでいつも「Hello WorlD!」を返す
(TCP 1c CLOSE_WAIT)      ブラウザから切断要求が来た
(TCP 00 CLOSED)         W5100切断
(TCP 14 LISTEN)          再びW5100待ち受け状態へ
    ↓
ブラウザがあきらめちゃって、以後は要求が来なくなる

上記の内部状態を見ると、
待ち受け→接続→HTTP要求→HTTPレスポンス→切断→待ち受け
という流れをグルグル廻る様がよくわかります.「HTTP要求→HTTP返答」の部分を賢くしてゆけば、賢いwebサーバーになるわけですね.(現状はバカピーですが)

このように実際に動かしてみると、OSI参照モデルにおける、Ethenet→ARP→IP→TCP→HTTPというスタック構造がよく見えて面白いもんです.
-----
今回のサンプルコードはこちらですが、このコードで受けたあなたの損害には関知しませんので、ハマったら素直に死んでください.開発環境とかハードウエアの解説は過去記事を参照してください.

解凍したフォルダの中にあるmain.cの中にある、この部分がTCP serverとICMPのルーチンを繰り返し呼び出しているところです.
  while (1)  // main loop
    {
      main_menu();
      TCP_server();
      ICMP();
    }
TCPはSOCKET1で、ICMPはSOCKET3で動かしています.ICMPが動いているのでpingが通ります.

TCP serverモードのキモのルーチンであるTCP_server()は、ip.cの中に記述があります.いつものようにベターっと記述してあるので、見苦しいですが判りやすいかと思いますが、やってることはW5100のデータシートに書かれている通りです.

6へ   8へ

かしこ


=== STMのアフィリエイト始めました ===
STM32のwelcome-kitです
        
試用レポはいずれまた...




人気ブログランキングへ

0 件のコメント:

コメントを投稿