課題4:HTTPクライアントの作成
ソケットおよびHTMLを使ってWWWサーバから任意のURLのページを取得し、標準出力に出力するプログラムを作成せよ。
プログラムソース
#include <stdio.h>>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/param.h>
#include <sys/uio.h>
#include <unistd.h>
#define BUF_LEN 256
int main(int argc, char *argv[]){
int s;
struct hostent *servhost;
struct sockaddr_in server;
struct servent *service;
FILE *fp;
char buf[BUF_LEN];
char host[BUF_LEN] = "www.yahoo.co.jp";
char path[BUF_LEN] = "/";
unsigned short port = 80;
if ( argc > 1 ){
char host_path[BUF_LEN];
if ( strlen(argv[1]) > BUF_LEN-1 ){
fprintf(stderr, "URL が長すぎます。\n");
return 1;
}
if ( strstr(argv[1], "http://") &&
sscanf(argv[1], "http://%s", host_path) &&
strcmp(argv[1], "http://" ) ){
char *p;
p = strchr(host_path, '/');
if ( p != NULL ){
strcpy(path, p);
*p = '\0';
strcpy(host, host_path);
} else {
strcpy(host, host_path);
}
p = strchr(host, ':');
if ( p != NULL ){
port = atoi(p+1);
if ( port <= 0 ){
port = 80;
}
*p = '\0';
}
} else {
fprintf(stderr,"URL は http://host/path の形式で指定してください。\n");
return 1;
}
}
printf("http://%s%s を取得します。\n\n",host, path);
servhost = gethostbyname(host);
if ( servhost == NULL ){
fprintf(stderr, "[%s] から IP アドレスへの変換に失敗しました。\n", host);
return 0;
}
bzero((char *)&server, sizeof(server));
server.sin_family = AF_INET;
bcopy(servhost->h_addr, (char *)&server.sin_addr, servhost->h_length);
if ( port != 0 ){
server.sin_port = htons(port);
} else {
service = getservbyname("http", "tcp");
if ( service != NULL ){
server.sin_port = service->s_port;
} else {
server.sin_port = htons(80);
}
}
if ( ( s = socket(AF_INET, SOCK_STREAM, 0) ) < 0 ){
fprintf(stderr,"ソケットの生成に失敗しました。\n");
return 1;
}
if ( connect(s, (struct sockaddr *)&server, sizeof(server)) == -1 ){
fprintf(stderr, "connect に失敗しました。\n");
return 1;
}
fp = fdopen(s, "r+");
if ( fp == NULL ){
fprintf(stderr, "fdopen に失敗しました。\n");
return 1;
}
setvbuf(fp, NULL, _IONBF, 0);
fprintf(fp, "GET %s HTTP/1.0\r\n", path);
printf("GET %s HTTP/1.0\r\n", path);
fprintf(fp, "Host: %s:%d\r\n", host, port);
printf("Host: %s:%d\r\n", host, port);
fprintf(fp, "\r\n");
printf("\r\n");
while (1){
if ( fgets(buf, sizeof(buf), fp) == NULL ){
break;
}
printf("%s", buf);
}
fclose(fp);
close(s);
return 0;
}
実行結果
22:21:/Users/j05059/jikken2/tcpip:%./htmlget
http://www.yahoo.co.jp/ を取得します。
GET / HTTP/1.0
Host: www.yahoo.co.jp:80
HTTP/1.1 200 OK
Date: Sun, 10 Dec 2006 13:21:55 GMT
P3P: policyref="http://privacy.yahoo.co.jp/w3c/p3p.xml", CP="CAO DSP COR CUR ADM
DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI
PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV"
Expires: -1
Pragma: no-cache
Cache-Control: no-cache
Connection: close
Content-Type: text/html; charset=euc-jp
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=euc-jp" >
---省略---
もどる