WiFi経由のhttpの改善
WiFi経由で画像を取り込むプログラムを作っているときに、httpプロトコルのプログラムを改善して、もう少し応用がきくようにしてみました。
httpプログラム改造版
改造版を下記に示します。
//************************************************** // HttpFileGet構造体の初期化 //************************************************** void HttpFileGetIni( void ) { HttpHeader.RecvTime = 2000000L; HttpHeader.Portnum = 80; HttpHeader.Get = NULL; HttpHeader.Host = NULL; HttpHeader.UserAgent = NULL; HttpHeader.Referer = NULL; }
初期化では、待ちタイム2秒とポートを80に設定しています。下記のHttpFileGet()を呼ぶ前に変更すれば、そのポートにアクセスします。
HttpFileGet()は、取得したデータを保存するファイルのファイルポインタ以外に、引数として、ヘッダファイルと接続ホスト名を持たせました。ホスト名がNULLのときは、HttpHeader.Hostを参照します。
また、headerファイルポインタがNULLで無いときには、このファイルをhttpプロトコルとして転送します。この機能を利用すると、汎用的にHttpFileGet()が使えます。これらは、昨日、NDS Program RoomにアップしたDS時計プログラムにソースが含まれています。
//************************************************** // 指定httpサーバから指定ファイルを取得します // false:取得失敗 true:成功 //************************************************** bool HttpFileGet( FILE *fpd, FILE *header, char *host ) { char toptext[512]; int i, j; long recvd_len; int ret = false; if( host==NULL ){ host = HttpHeader.Host; } //header使用の場合は、HttpHeader.Host==NULLもありえます if( header==NULL ){ //********** http GET コマンド生成 ********** strcpy( toptext, "GET " ); strcat( toptext, HttpHeader.Get ); strcat( toptext, " HTTP/1.1\r\n" ); strcat( toptext, "Host: " ); strcat( toptext, HttpHeader.Host ); strcat( toptext, "\r\n" ); strcat( toptext, "User-Agent: " ); strcat( toptext, HttpHeader.UserAgent ); strcat( toptext, "\r\n" ); strcat( toptext, "Referer: " ); strcat( toptext, HttpHeader.Referer ); strcat( toptext, "\r\n" ); strcat( toptext, "\r\n" ); //******************************************* } else{ fseek( header, 0, SEEK_END ); recvd_len = ftell( header ); rewind( header ); if( recvd_len>511 ){ recvd_len = 511; } fread( toptext, recvd_len, sizeof(char), header ); toptext[recvd_len] = 0; } //ShinoUpPrintBox( SubScreenA, (u8 *)toptext, 42, RGB(31,31,31), RGB(0,0,0), 1, RGB(0,0,0) ); //メモリの確保 char *incoming_buffer = (char*)malloc( sizeof(char*) * HTTPGETDATASIZE ); if(incoming_buffer==NULL ){ ShinoUpPrint( SubScreenA, (u8 *)"Malloc Error", RGB(31,0,0),RGB(0,0,0), 1,RGB(0,0,0) ); return( false ); } // サーバのIPアドレスを検索します struct hostent * myhost = gethostbyname( host ); //TCPソケットの生成 int my_socket = socket( AF_INET, SOCK_STREAM, 0 ); //ホストに接続するため、指定IPアドレスの指定ポートに接続します。 struct sockaddr_in sain; sain.sin_family = AF_INET; sain.sin_port = htons( HttpHeader.Portnum ); //ポート指定 sain.sin_addr.s_addr= *( (unsigned long *)(myhost->h_addr_list[0]) ); //IP指定 connect( my_socket,(struct sockaddr *)&sain, sizeof(sain) ); //接続先にファイル取得リクエストを飛ばします send( my_socket, toptext, strlen(toptext), 0 ); //データ取得 recvd_len = getRecvData( my_socket, incoming_buffer, HTTPGETDATASIZE, 0, HttpHeader.RecvTime ); //recvd_lenが-1だったり、返事が 200 OK であるかどうか調べる if( strexist( incoming_buffer, (char *)"200", 20)==true && strexist( incoming_buffer, (char *)"OK", 20)==true && recvd_len>0 ){ //*** メッセージの送受信成功 *** //最初のパケットが"HTTP/1.x 200 OK"のみかどうか調べます if( recvd_len<=15 ){ //15バイト以下だったら再読み込みする recvd_len = getRecvData( my_socket, incoming_buffer, HTTPGETDATASIZE, 0, HttpHeader.RecvTime ); } //[0x0D][0x0A][0x0D][0x0A]の4バイトを探す for( j=0; j<recvd_len-3; j++ ){ if( incoming_buffer[j]==0x0d && incoming_buffer[j+1]==0x0a && incoming_buffer[j+2]==0x0d && incoming_buffer[j+3]==0x0a ){ //見つかった for( i=j+4; i<recvd_len; i++ ){ incoming_buffer[i-(j+4)] = incoming_buffer[i]; } recvd_len -= (j+4); break; } } ret = true; } //*** 受信データを保存 *** fwrite( incoming_buffer, recvd_len, sizeof(char), fpd ); //データサイズが0になるまで、データを取得します while( ( recvd_len = getRecvData( my_socket, incoming_buffer, HTTPGETDATASIZE, 0, HttpHeader.RecvTime ) ) != 0 ){ if( recvd_len>0 ){ swiWaitForVBlank(); fwrite( incoming_buffer, recvd_len, sizeof(char), fpd ); } } //メモリの開放 free( incoming_buffer ); //ソケットをシャットダウンします shutdown(my_socket,0); //少し間をおく(こうしないとソケットが切れない・・・) for( i=0; i<20; i++ ){ swiWaitForVBlank(); } //ソケットを閉じます closesocket( my_socket ); return( ret ); }
HttpFileGet応用例
先ほど、下記のようなヘッダを作り、DSからtwitterのIDに発言してみました。
POST /statuses/update.xml?status=TEST HTTP/1.1 Host: twitter.com User-Agent: Nintendo DS Referer: http://twitter.com/ Authorization: Basic =======秘=密=======
このヘッダをHttpFileGet()で送信してやると、OKとxmlファイルが戻ってきて、無事、twitterにTESTと発言できました。
興味のある方は、色々と試してみてください。DSボットを作ろうかな・・・。
今日はこの辺で・・・。
本当にやりたいことリスト
(ブログの終わりにやりたいことを書いておきたいと思います)
- 求職活動・・・このブログで興味を持った人一声かけてください。m(_ _)m
- Androidプログラム
- Web系のプログラム