HTTPクライアントの作成(TCPクライアントサンプル)

ここでは、クライアントの例としてインチキHTTPクライアントを作ってみたいと思います。 HTTPは日ごろ良く使っていて、馴染みも深いと思います。 ただし、ここで紹介するインチキHTTPクライアントはHTTPメッセージを表示するだけの簡単なものです。

HTTPクライアントサンプル

以下にインチキHTTPクライアントを示します。


#include <stdio.h>
#include <winsock2.h>

int
main(int argc, char *argv[])
{
 WSADATA wsaData;
 struct sockaddr_in server;
 SOCKET sock;
 char buf[32];
 char *deststr;
 unsigned int **addrptr;

 if (argc != 2) {
	 printf("Usage : %s dest\n", argv[0]);
	 return 1;
 }
 deststr = argv[1];

 if (WSAStartup(MAKEWORD(2,0), &wsaData) != 0) {
	 printf("WSAStartup failed\n");
	 return 1;
 }

 sock = socket(AF_INET, SOCK_STREAM, 0);
 if (sock == INVALID_SOCKET) {
	 printf("socket : %d\n", WSAGetLastError());
	 return 1;
 }

 server.sin_family = AF_INET;
 server.sin_port = htons(80); // HTTPのポートは80番です

 server.sin_addr.S_un.S_addr = inet_addr(deststr);
 if (server.sin_addr.S_un.S_addr == 0xffffffff) {
	 struct hostent *host;

	 host = gethostbyname(deststr);
	 if (host == NULL) {
		 if (WSAGetLastError() == WSAHOST_NOT_FOUND) {
			 printf("host not found : %s\n", deststr);
		 }
		 return 1;
	 }

	 addrptr = (unsigned int **)host->h_addr_list;

	 while (*addrptr != NULL) {
		 server.sin_addr.S_un.S_addr = *(*addrptr);

		 // connect()が成功したらloopを抜けます
		 if (connect(sock,
				(struct sockaddr *)&server,
				sizeof(server)) == 0) {
			break;
		 }

		 addrptr++;
		 // connectが失敗したら次のアドレスで試します
	 }

	 // connectが全て失敗した場合
	 if (*addrptr == NULL) {
		 printf("connect : %d\n", WSAGetLastError());
		 return 1;
	 }
 } else {
	 if (connect(sock,
                     (struct sockaddr *)&server,
                     sizeof(server)) != 0) {
		 printf("connect : %d\n", WSAGetLastError());
		 return 1;
	 }
 }

 // HTTPで「/」をリクエストする文字列を生成
 memset(buf, 0, sizeof(buf));
 _snprintf(buf, sizeof(buf), "GET / HTTP/1.0\r\n\r\n");

 // HTTPリクエスト送信
 int n = send(sock, buf, (int)strlen(buf), 0);
 if (n < 0) {
	 printf("send : %d\n", WSAGetLastError());
	 return 1;
 }

 // サーバからのHTTPメッセージ受信
 while (n > 0) {
	 memset(buf, 0, sizeof(buf));
	 n = recv(sock, buf, sizeof(buf), 0);
	 if (n < 0) {
		 printf("recv : %d\n", WSAGetLastError());
		 return 1;
	 }

	 // 受信結果を表示
	 fwrite(buf, n, 1, stdout);
 }

 closesocket(sock);

 WSACleanup();

 return 0;
}

折角なので、作成したHTTPクライアントを使ってみたいと思います。 www.google.co.jpに接続すると以下のようになります。 (ただし、下記例では表示スペースに押し込むために一部結果を削ってあります。何となくこんな感じかなぁ程度に見てください。)


C:\> client.exe www.google.co.jp
HTTP/1.0 302 Found
Location: http://www.google.co.jp/cxfer?c=PREF%3D:TM%3D1105:S%3DrI6jLhtK7m&prev=/
Set-Cookie: PREF=ID=04f0a2d0a3400510:CR=1:TM=110515:LM=1105515:S=55PyTj
S-5evTiH; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com
Content-Type: text/html
Server: GWS/2.1
Content-Length: 217
Date: Mon, 10 Jan 2005 04:48:35 GMT
Connection: Keep-Alive

<HTML><HEAD>
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.co.jp/cxfer?c=PREF%3D:TM%315:S%3D6Gm&prev=/">here</A>.
</BODY></HTML>