HELLO を表示する Web Server を作成する

"HELLO" を表示するページを送り返す「単純な Web Server」を作成します。
上の画像のように「IEを起動して呼び出す」と "HELLO" のページが表示されます。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プロジェクトの設定

  1. このプログラムは、私が作成した Wsock Object Class を使用します。
    新規プロジェクトを作成して、次のファイルをプロジェクトのフォルダーに格納して下さい。
    ファイル 説明
    Main.cpp メインプログラムファイル
    Wsock.h Wsock Object Class のヘッダファイル
    Wsock.lib Wsock Object Class のライブラリ
  2. 次の DialogBox を作成して下さい。
    BOX キャプション ID
    DialogBox TCP Server IDD_DIALOG1
    EditControl PORT番号 IDC_PORT
    EditControl IDC_MSG
    Button Start UP IDC_STARTUP
    Button Listen IDC_LISTEN
    Button 終了 IDCANCEL
  3. Start UP ボタンをクリックすると Object Class が初期化されます。
    Listen ボタンをクリックすると Client からの接続待ち状態で Server が待機します。
    ページ先頭の画像を参考にしてIEのアドレスに「http://127.0.0.1:12345/」をタイプして下さい。
    先頭画像のように "HELLO" が表示されたら完成です。

プログラムの説明

  1. Wsock.h をインクルードして、ws2_32.lib と Wsock.lib をリンクして下さい。
    ID_TIMER はタイマのID定義です。
        /**************************************************/
        /*★ HTTP Server  Wsock Object Class    前田 稔 ★*/
        /**************************************************/
        #include    <windows.h>
        #include    "Wsock.h"
        #include    "resource.h"
        #pragma     once
        #pragma     comment(lib,"ws2_32.lib")
        #pragma     comment(lib,"Wsock.lib")
        #define     ID_TIMER    32767
        
  2. Server から Client にメッセージを送る関数 SendMsg(char *com) は次のように宣言されています。
        virtual int SendMsg(char *com);
    
        //★ COMMAND を解析してメッセージを送信する virtual 関数
        int Wsock::SendMsg(char *com)
        {   int     n;
    
            // メッセージを送信します
            n = send(sockw,"HELLO",5,0);
            if (n < 1)
            {   strcpy(szMSG,"send に失敗しました");
                return -1;
            }
            strcpy(szMSG,"Client に送信しました");
            return 0;
        }
        
  3. 今回のように "HELLO" を表示するホームページを送るには SendMsg() をオーバーライドしなければなりません。
    そこで Wsock Object Class を継承した WebServer Object Class を作成して、その中で SendMsg() をオーバーライドします。
    Object Class の継承は イメージ画像(花札.bmp)を入力して、一枚のカードを表示する を参照して下さい。
    httpmsg[ ] は "HELLO" を表示するホームページの TEXT DATA です。
        //★ WebServer Object Class   SendMsg() をオーバーライド
    
        char        httpmsg[2048]=
        { "HTTP/1.0 200 OK\r\nContent-Length: 20\r\nContent-Type: text/html\r\n\r\nHELLO\r\n" };
    
        class WebServer : public Wsock
        {
          public:
            WebServer();            //Constructor
            ~WebServer();           //Destructor
    
            int     SendMsg(char *com);
        };
    
        // WebServer Object Class 関数
        WebServer::WebServer() : Wsock()
        {
        }
    
        WebServer::~WebServer()
        {
        }
    
        //★ COMMAND を解析して Send Message を作成
        int  WebServer::SendMsg(char *com)
        {   int     n;
            // メッセージを送信します
            n = send(sockw,httpmsg,strlen(httpmsg),0);
            if (n < 1)
            {   strcpy(szMSG,"send に失敗しました");
                return -1;
            }
            strcpy(szMSG,"Client に送信しました");
            return 0;
        }
        
  4. WinMain() では DialogBox を表示するだけです。
  5. WM_INITDIALOG で WebServer Object Class を生成します。
    EditBox に PORT の初期値を表示します 。
    正式な Web server のポート番号は 80 なので競合しないように 12345 を使っています。
        Wsock       *App= NULL;     //Wsock Object Class
        int         PORT= 12345;
        char        buf[1024];
    
        case WM_INITDIALOG:
            App= new WebServer();
            wsprintf(buf,"%d",PORT);
            SetDlgItemText(hDlg,IDC_PORT,buf);
            break;
        
  6. Start UP ボタンのクリックで Object Class の初期化を行います。
    この操作は、最初に一度だけ実行します。
        case WM_COMMAND:
            switch(LOWORD(wParam))
            {   case IDC_STARTUP:
                    KillTimer(hDlg, ID_TIMER);
                    App->Startup();
                    SetDlgItemText(hDlg,IDC_MSG,App->szMSG);
                    break;
        
  7. Listen ボタンがクリックされると、タイマ割り込みで Client からの接続の監視を始めます。
    Server では、何時 Client が接続してきても応答出来るように監視しなけれななりません。
                case IDC_LISTEN:
                    PORT= GetDlgItemInt(hDlg,IDC_PORT,NULL,FALSE);
                    rc= App->StartSrv(PORT);
                    SetDlgItemText(hDlg,IDC_MSG,App->szMSG);
                    if (rc==0)  SetTimer(hDlg, ID_TIMER, 300, NULL);
                    break;
        
  8. タイマ割り込みで Client からの接続を監視します。
    Client から接続要求があると SendMsg(char *com) で "HELLO" を表示するホームページを送信します。
            case WM_TIMER:
                KillTimer(hDlg, ID_TIMER);
                rc= App->CheckSrv(buf,1024);
                SetDlgItemText(hDlg,IDC_MSG,App->szMSG);
                SetTimer(hDlg, ID_TIMER, 300, NULL);
                break;
        
  9. WM_CLOSE では Wsock Object Class を開放して下さい。
            case WM_CLOSE:
                SAFE_DELETE(App);
                EndDialog(hDlg, TRUE); 
                return TRUE;
        

【補足】

当初、何故かIEがサーバーを認識してくれませんでした。
本来ならばクライアントからの要求内容に従って応答も変わるのでしょうが、今回は常に "HELLO" を表示するホームページを 送り返すだけなので、IEからのメッセージを受け取っても意味が無いと思い受け取らなかったのですが、メッセージを 受け取らないとIEが「すねて (^_^;」ページを表示してくれませんでした。
    sockw = accept(sock0, (struct sockaddr *)&client, &len);
    if  {  //sockw のエラーチェック  }

    // 送られてきたメッセージ(COMMAND)を受け取ります
    memset(buf,0,blen);
    recv(sockw,buf,blen,0);

超初心者のプログラム入門(Win32API C++)