という感じになります。
- ソケットの作成を行う。
- Webサーバに接続する。
- Webサーバに"GET"リクエストを行う。
- Webサーバから送信されたデータをすべて受信する。
- ソケットを破棄する。
#define WSOCK_GETHOST WM_USER + 1 /* ホスト情報のイベントを通知するメッセージ */ #define WSOCK_SELECT WM_USER + 2 /* ソケットイベントを通知するメッセージ */ /*--------------------------------------------------- ソケットイベントの通知を設定する関数 ---------------------------------------------------*/ BOOL SocketSelect(int sSoc,HWND hWnd) { /* 接続、受信、切断のソケットイベントを通知させるように設定する */ /* ソケットイベントは、ウィンドウにWSOCK_SELECTメッセージで通知されるように設定する */ if(WSAAsyncSelect(sSoc, hWnd, WSOCK_SELECT, FD_CONNECT | FD_READ | FD_CLOSE) == SOCKET_ERROR){ return FALSE; } return TRUE; } /*--------------------------------------------------- サーバに接続要求を出す関数 ---------------------------------------------------*/ BOOL ConnectServer(int cSoc,unsigned long cIPaddr,int cPort) { struct sockaddr_in serversockaddr; /* サーバのアドレスの構造体にサーバのIPアドレスとポート番号を設定します */ serversockaddr.sin_family = AF_INET; serversockaddr.sin_addr.s_addr = cIPaddr; /* IPアドレス */ serversockaddr.sin_port = htons((unsigned short)cPort); /* ポート番号 */ memset(serversockaddr.sin_zero,(int)0,sizeof(serversockaddr.sin_zero)); /* サーバにコネクトする */ if(connect(cSoc,(struct sockaddr *)&serversockaddr,sizeof(serversockaddr)) == SOCKET_ERROR){ if(WSAGetLastError() != WSAEWOULDBLOCK){ return FALSE; } } return TRUE; } /*--------------------------------------------------- ソケットを破棄する関数 ---------------------------------------------------*/ void SocketClose(HWND hWnd) { /* WSAAsyncGetHostByName関数の非同期なタスクがある場合はキャンセルする */ if(hGetHost != NULL){ WSACancelAsyncRequest(hGetHost); hGetHost = NULL; } /* ソケットイベントの通知を取り消す */ WSAAsyncSelect(soc, hWnd, 0,0); /* ソケットを破棄する */ closesocket(soc); soc = -1; SetWindowText(hBTNGET,"GO"); } /*--------------------------------------------------- ソケットのエラー処理関数 ---------------------------------------------------*/ void SocketError(HWND hWnd,char *msgbuf) { /* ソケットを破棄する */ SocketClose(hWnd); /* エラーメッセージ */ MessageBox(hWnd,msgbuf,"Error",MB_OK | MB_ICONERROR); } /*--------------------------------------------------- HTTPセッションの開始 ---------------------------------------------------*/ void HTTPStart(HWND hWnd,char *buf) { unsigned long serveraddr; /* サーバのIPアドレス */ /* URLからサーバ名とパスを取得する */ Port = GetURL(buf,SvName,Path); if(Port == -1){ MessageBox(hWnd, "URLが不正です。", "Error", MB_OK | MB_ICONERROR); SetWindowText(hBTNGET,"GO"); return; } /* socにソケットを作成します */ soc = socket(PF_INET, SOCK_STREAM, 0); if(soc == INVALID_SOCKET){ MessageBox(hWnd, "ソケットの作成に失敗しました。", "Error", MB_OK | MB_ICONERROR); soc = -1; SetWindowText(hBTNGET,"GO"); return; } /* svNameにドットで区切った10進数のIPアドレスが入っている場合、serveraddrに32bit整数のIPアドレスが返ります */ serveraddr = inet_addr((char*)SvName); if(serveraddr == -1){ /* サーバ名からサーバのホスト情報を取得する */ /* ホスト情報が取得できると、ウィンドウにWSOCK_GETHOSTが通知されるようにする */ hGetHost = WSAAsyncGetHostByName(hWnd,WSOCK_GETHOST,SvName,gHostEnt, MAXGETHOSTSTRUCT); if(hGetHost == 0){ SocketError(hWnd,"サーバのIPアドレスの取得に失敗しました。"); return; } return; } /* 接続、受信、切断のイベントをウィンドウメッセージで通知されるようにする */ if(SocketSelect(soc, hWnd) == FALSE){ SocketError(hWnd,"ソケットイベントを通知させる設定に失敗しました。"); return; } /* サーバに接続する */ if(ConnectServer(soc,serveraddr,Port) == FALSE){ SocketError(hWnd,"サーバへの接続に失敗しました。"); } } /*--------------------------------------------------- IPアドレスを取得して接続開始する ---------------------------------------------------*/ void HTTPGetHostToIPaddr(HWND hWnd, WPARAM wParam, LPARAM lParam) { struct hostent FAR *HostEntry; /* ホスト情報 */ unsigned long serveraddr; /* サーバのIPアドレス */ /* エラーの判定 */ if(WSAGETASYNCERROR(lParam) != 0){ SocketError(hWnd,"サーバのIPアドレスの取得に失敗しました。"); return; } /* WSAAsyncGetHostByNameの戻り値である非同期なタスクのハンドルか判定*/ if(hGetHost != (HANDLE)wParam){ return; } HostEntry = (struct hostent FAR *)gHostEnt; serveraddr = *((unsigned long *)((HostEntry->h_addr_list)[0])); /* IPアドレスを取得する */ hGetHost = NULL; /* ソケットイベントをウィンドウメッセージで通知されるようにする */ if(SocketSelect(soc, hWnd) == FALSE){ SocketError(hWnd,"ソケットイベントを通知させる設定に失敗しました。"); return; } /* サーバに接続する */ if(ConnectServer(soc,serveraddr,Port) == FALSE){ SocketError(hWnd,"サーバへの接続に失敗しました。"); return; } } /*--------------------------------------------------- HTTPリクエストを送信する ---------------------------------------------------*/ void HTTPSendRequest(HWND hWnd) { char SendBuf[BUFSIZE]; /* 送信するバッファ */ /* HTTPリクエストの作成 */ wsprintf(SendBuf,"GET %s HTTP/1.0\r\nHost: %s:%d\r\nUser-Agent: httpcex/0.0\r\n\r\n",Path,SvName,Port); /* データを送信する */ if(send(soc, SendBuf, lstrlen(SendBuf), 0) == SOCKET_ERROR){ SocketError(hWnd,"送信に失敗しました。"); return; } strcpy(OUT_BUF,""); } /*--------------------------------------------------- データを受信して蓄積する ---------------------------------------------------*/ void HTTPRecvData(HWND hWnd) { char RecvBuf[RECVSIZE]; /* 受信するバッファ */ int buf_len; /* 受信したバイト数 */ /* データを受信する */ buf_len = recv(soc, RecvBuf, RECVSIZE - 1, 0); if (buf_len == SOCKET_ERROR ){ SocketError(hWnd,"受信に失敗しました。"); return; } RecvBuf[buf_len] = '\0'; /* 受信するバッファの後ろにヌル文字を付加する */ if((strlen(OUT_BUF) + buf_len) < OUTSIZE){ strcat(OUT_BUF,RecvBuf); /* バッファに受信文字列を蓄積する */ } } /*--------------------------------------------------- サーバから切断する ---------------------------------------------------*/ void HTTPClose(HWND hWnd) { char RecvBuf[RECVSIZE]; /* 受信するバッファ */ int buf_len; /* 受信したバイト数 */ /* 受信バッファにデータがあればすべて受信する */ while((buf_len = recv(soc, RecvBuf, RECVSIZE - 1, 0)) > 0 ){ RecvBuf[buf_len] = '\0'; /* バッファの後ろにヌル文字を付加する */ strcat(OUT_BUF,RecvBuf); } /* ソケットを破棄する */ SocketClose(hWnd); /* エディットボックスに文字列の表示を行う */ ConvBuf(OUT_BUF); /* 文字列を整形する */ SendMessage(HEdit,WM_SETTEXT,0,(LPARAM) ((LPSTR)OUT_BUF)); } /*--------------------------------------------------- メインウィンドウのプロシージャ ---------------------------------------------------*/ LONG APIENTRY MainProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { char buf[BUFSIZE]; RECT WinRec; switch (uMsg) { case WM_CREATE: /* ウィンドウ作成時 */ /* ウィンドウ内のコントロールを作成する */ URLEdit = CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT",(LPSTR)NULL,WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,5,10,300,25,hWnd,(HMENU)ID_EDIT_URL,g_hinst,NULL); hBTNGET = CreateWindow("BUTTON",(LPSTR)"GO",WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,310,10,50,25,hWnd,(HMENU)ID_GO,g_hinst,NULL); HEdit = CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT",(LPSTR)NULL,WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP | ES_NOHIDESEL | ES_MULTILINE | ES_LEFT | ES_READONLY,0,40,0,0,hWnd,(HMENU)ID_EDIT_VIEW,g_hinst,NULL); /* 初期化 */ soc = -1; hGetHost = NULL; break; case WSOCK_GETHOST: /* サーバのホスト情報関数のイベント */ /* ホスト情報からIPアドレスを取得して接続を開始する */ HTTPGetHostToIPaddr(hWnd,wParam,lParam); break; case WSOCK_SELECT: /* ソケットイベントのメッセージの場合(WSAAsyncSelect関数にて登録) */ /* エラーの判定 */ if(soc != -1 && WSAGETSELECTERROR(lParam) != 0){ SocketError(hWnd,"ソケットイベントの通知でエラーが発生しました。"); break; } /* 処理すべきソケットか判定 */ if(soc != (int)wParam){ break; } /* ソケットイベント毎の処理を行う */ switch(WSAGETSELECTEVENT(lParam)) { case FD_CONNECT: /* サーバへの接続が完了した事を示すイベント */ /* HTTPリクエストを送信する */ HTTPSendRequest(hWnd); break; case FD_READ: /* 受信バッファにデータがある事を示すイベント */ /* データを受信して蓄積する */ HTTPRecvData(hWnd); break; case FD_CLOSE: /* サーバへの接続が終了した事を示すイベント */ /* 接続を終了する */ HTTPClose(hWnd); break; } break; case WM_COMMAND: switch(LOWORD(wParam)){ case ID_GO: if(soc != -1){ /* 既に通信中の場合はキャンセルする */ /* ソケットを破棄する */ SocketClose(hWnd); }else{ /* 通信を開始する */ /* URLを取得する */ SendMessage(URLEdit,WM_GETTEXT,BUFSIZE - 1,(LPARAM)buf); SetWindowText(hBTNGET,"Cancel"); /* HTTPセッションを開始する */ HTTPStart(hWnd,buf); } break; } break; : :
httpcex00.zipこのプログラムは、GUIベースで動作します。
- httpcex.c
- httpcex.rc
- resource.h
Res
- icon1.ico
- httpcex.exe