HTTPクライアントの作成(TCPクライアントサンプル)
ここでは、クライアントの例としてインチキHTTPクライアントを作ります。 HTTPは日ごろ良く使っていて、馴染みも深いと思います。 ただし、ここで紹介するインチキHTTPクライアントはHTTPメッセージを表示するだけの簡単なものです。
HTTPクライアントサンプル
以下にインチキHTTPクライアントを示します。
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
int
main(int argc, char *argv[])
{
struct sockaddr_in server;
int sock;
char buf[32];
char *deststr;
unsigned int **addrptr;
if (argc != 2) {
printf("Usage : %s dest\n", argv[0]);
return 1;
}
deststr = argv[1];
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket");
return 1;
}
server.sin_family = AF_INET;
server.sin_port = htons(80); /* HTTPのポートは80番です */
server.sin_len = sizeof(server);
server.sin_addr.s_addr = inet_addr(deststr);
if (server.sin_addr.s_addr == 0xffffffff) {
struct hostent *host;
host = gethostbyname(deststr);
if (host == NULL) {
if (h_errno == HOST_NOT_FOUND) {
/* h_errnoはexternで宣言されています */
printf("host not found : %s\n", deststr);
} else {
/*
HOST_NOT_FOUNDだけ特別扱いする必要はないですが、
とりあえず例として分けてみました
*/
printf("%s : %s\n", hstrerror(h_errno), deststr);
}
return 1;
}
addrptr = (unsigned int **)host->h_addr_list;
while (*addrptr != NULL) {
server.sin_addr.s_addr = *(*addrptr);
/* connect()が成功したらloopを抜けます */
if (connect(sock,
(struct sockaddr *)&server,
sizeof(server)) == 0) {
break;
}
addrptr++;
/* connectが失敗したら次のアドレスで試します */
}
/* connectが全て失敗した場合 */
if (*addrptr == NULL) {
perror("connect");
return 1;
}
} else {
if (connect(sock,
(struct sockaddr *)&server, sizeof(server)) != 0) {
perror("connect");
return 1;
}
}
/* HTTPで「/」をリクエストする文字列を生成 */
memset(buf, 0, sizeof(buf));
snprintf(buf, sizeof(buf), "GET / HTTP/1.0\r\n\r\n");
/* HTTPリクエスト送信 */
int n = write(sock, buf, (int)strlen(buf));
if (n < 0) {
perror("write");
return 1;
}
/* サーバからのHTTPメッセージ受信 */
while (n > 0) {
memset(buf, 0, sizeof(buf));
n = read(sock, buf, sizeof(buf));
if (n < 0) {
perror("read");
return 1;
}
/* 受信結果を標準出力へ表示(ファイルディスクリプタ1は標準出力) */
write(1, buf, n);
}
close(sock);
return 0;
}
折角なので、作成したHTTPクライアントを使ってみたいと思います。 www.google.co.jpに接続すると以下のようになります。 (ただし、下記例では表示スペースに押し込むために一部結果を削ってあります。何となくこんな感じかなぁ程度に見てください。)
username$ a.out www.google.co.jp
HTTP/1.0 302 Found
Location: http://www.google.co.jp/cxfer?c=PREF%3D:TM%3D1105:S%3DrItK7m&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>