第六日目 サブルーチン





//------------------------------------------------------------

// サブルーチン

//------------------------------------------------------------







// HTTPヘッダーを返す関数

void getHeader(char* header, int statusCode, int length){



 // 現在の時間関連変数

 time_t timeNow;

 char strNow[60];



 // 送信ヘッダ関連変数

 char message[1024];

 char contentType[1024];

 char format[HTTP_HEADER_SIZE];



 // 現在の時間を取得

 time(&timeNow);

 strftime(strNow, sizeof(strNow),

   "%a, %d %b %Y %H:%M:%S GMT",

   gmtime(&timeNow));



 // エラーヘッダーの作成

 strcpy(contentType, "text/html");

 switch (statusCode){

 case (200):

  strcpy(message, "HTTP/1.1 200 OK");

  strcpy(contentType, "application/rss+xml");

  break;

 case (404):

  strcpy(message, "HTTP/1.1 404 Not Found");

  break;

 case (501):

  strcpy(message, "HTTP/1.0 501 Not Implemented");

  break;

 default:

  strcpy(message, "HTTP/1.1 404 Not Found");

  break;

 }



 // ヘッダーを作成

 strcpy(format,

     "%s\r\n"

     "Date: %s\r\n"

     "Content-Length: %d\r\n"

     "Last-Modified: %s\r\n"

     "Content-Type: %s\r\n"

    "Accept-Charset: utf-8\r\n"

     "\r\n"

  );



  sprintf(header, format, message,

              strNow,

              length,

              strNow,

              contentType);




  return;

}



// エラーデータを返す関数

void getError(WSCstring& contentBuffer, int statusCode) {

 switch (statusCode){

 case (404):

  contentBuffer = "404 Not Found";

  break;

 case (501):

  contentBuffer = "501 Not Implemented";

  break;

 default:

  contentBuffer = "404 Not Found";

  break;

 }



 return;

}



// RSSデータを返す関数

void getRss(WSCstring& rssBuffer, WSCstring* pPath) {

 // 固定のデータを設定

 rssBuffer.setString(

   "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n"

   "<rss version=\"2.0\">\r\n"

   "<channel>\r\n"

    " <title>RSS配信</title>\r\n"

   " <description>固定の文字を配信する。</description>\r\n"

   " <link>http://localhost</link>\r\n"

   " <lastBuildDate>Wed, 21 Oct 2009 16:28:16 GMT</lastBuildDate>\r\n"

   " <pubDate>Wed, 21 Oct 2009 16:28:16 GMT</pubDate>\r\n"

   " <generator>rss generator v0.1</generator>\r\n"

   " <docs>http://localhost</docs>\r\n"

   " <language>ja</language>\r\n"

   " <item>\r\n"

  "</channel>\r\n"

   "</rss>");





 return;

}





補足



  現状では、固定の情報。

  いろいろ変更できるといいな。




第六日目





  ここまでのソースを





#include <WScom.h>

#include <WSCfunctionList.h>

#include <WSCbase.h>

//----------------------------------------------------------

//Function for the event procedure

//----------------------------------------------------------



#include <WSCvssocket.h>

#include <time.h>



#define INPUT_BUFFER_SIZE 4096 // 一時バッファのサイズ

#define HTTP_HEADER_SIZE 512 // HTTPヘッダーのサイズ



// HTTPヘッダーを返す関数

// 第一引数:HTTPヘッダー

// 第二引数:ステータスコード

// 第三引数:コンテンツサイズ

void getHeader(char*, int, int);



// エラーデータを返す関数

// 第一引数:コンテンツ

// 第二引数:ステータスコード

void getError(WSCstring&, int);



// RSSデータを返す関数

// 第一引数:コンテンツ

// 第二引数:ファイルパス

void getRss(WSCstring&, WSCstring*);



// 受信・送信処理 メイン

void local_server(WSCbase* object) {

// サーバーソケット

WSCvssocket* objSocket


   = (WSCvssocket*)object->cast("WSCvssocket");



// 受信関連変数

char input[INPUT_BUFFER_SIZE]; // 一時バッファ

WSCstring inBuffer; // 受信内容

WSCstring lineBuffer; // 受信内容の最初の一行

WSCstring method; // 受信メソッド

WSCstring path; // 受信パス

WSCstring version; // 受信バージョン



// HTTPヘッダー

char header[HTTP_HEADER_SIZE];



// コンテンツ関連変数

WSCstring contentBuffer;



// 送信関連変数

int statusCode; // ステータスコード

WSCstring outBuffer; // 送信内容

char* output; // 一時バッファ



// 受信

inBuffer = "";

while (objSocket->read((WSCuchar*)input,


              INPUT_BUFFER_SIZE) > 0) {

inBuffer += input;

if (strlen(input) < INPUT_BUFFER_SIZE) {

break;

}

}



// 最初の一行を取り出す

lineBuffer = inBuffer.getWord(0,"\r\n");



// 最初の一行を分解する

method = path = version = "";

if (lineBuffer.getWords() == 3) {

method = lineBuffer.getWord(0);

path = lineBuffer.getWord(1);

version = lineBuffer.getWord(2);

}



// 最初の一行を解析する

if (method.isExist("GET") == -1


   || version.isExist("HTTP/1.1") == -1) {

// GETリクエスト以外は、サポートしない

// HTTP 1.1以外は、サポートしない

statusCode = 501;

} else if (path.isExist("/rss") == -1) {

// パスは、「/rss」固定

statusCode = 404;

} else {

// 正常

statusCode = 200;

}



if (statusCode == 200) {

// RSSデータを取得。

getRss(contentBuffer, &path);

} else {

// エラーデータを取得。

getError(contentBuffer, statusCode);

}



// HTTPヘッダーを取得。

getHeader(header, statusCode,


         (int)strlen(contentBuffer.getString()));



// 送信内容の作成

outBuffer.setString(header);

outBuffer.addString(contentBuffer);

output = outBuffer.getString();



// 送信

objSocket->write((WSCuchar*)output, strlen(output));



return;

}

static WSCfunctionRegister


     op("local_server",(void*)local_server);




補足


 


  適当なところに、改行を入れてあります。


第五日目





     WideStudio 固有の話





     RSSの表示が遅いので、


     各行、実行にかかった秒数を表示してみた。





     そしたら、読込みに30秒かかっている。





     30秒…。





     タイムアウトの時間と同じだ!





     タイムアウトの時間を5秒に。





     速くなった。





     タイムアウトの時間は、


      WSCvssocket クラス


      WSNtimeout  プロパティ


     を変更する。





     もちろん、WideStudio ですから、


     GUIで変更できます。 





補足





     WideStudio には、トレース表示がある。


     これだと、各行の秒数も簡単に表示できる。





     だけど、好みの問題だが、printf がいい。





     デバッグモードでビルドして、実行すると


     実行画面の他に、もう1枚ウィンドウが開く。


     そのウィンドウに、printfの値が表示される。





     もちろん、C++だから、printf でなくても出力はできるが。