インターネット上にC言語でソースコードをGETするサンプルは沢山ありましたが、Proxyに対応したものやHTTP1.1に対応したもの(暫定)が存在しなかったので紹介します。
スポンサードリンク
あるホストのWebページのソースコードを取得するプログラムです。
Proxyを利用しない場合は「#define SUPPORT_PROXY」を削除、HTTP1.1を利用しない場合は「#define HTTP_1_1」を削除してください。
#include <stdio.h> #include <sys/socket.h> #include <arpa/inet.h> #include <stdlib.h> #include <unistd.h> #include <netdb.h> #include <string.h> #define SUPPORT_PROXY #define HTTP_1_1 int create_tcp_socket(); char *get_ip(char *host); char *build_get_query(char *host, char *page); void usage(); #define PAGE "/" #define PORT 80 #define USERAGENT "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)" #define PROXY_HOST "xxx.xxx.xxx.xxx.xxx" #define PROXY_PORT xxxxxx int main(int argc, char **argv) { struct sockaddr_in *remote; int sock; int tmpres; char *ip; char *get; char buf[BUFSIZ+1]; char *host; char *page; if(argc == 1){ usage(); exit(2); } host = argv[1]; if(argc > 2){ page = argv[2]; }else{ page = PAGE; } sock = create_tcp_socket(); ip = get_ip(host); fprintf(stderr, "IP is %s\n", ip); remote = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in *)); remote->sin_family = AF_INET; tmpres = inet_pton(AF_INET, ip, (void *)(&(remote->sin_addr.s_addr))); if( tmpres < 0) { perror("Can't set remote->sin_addr.s_addr"); exit(1); }else if(tmpres == 0) { fprintf(stderr, "%s is not a valid IP address\n", ip); exit(1); } #ifdef SUPPORT_PROXY remote->sin_port = htons(PROXY_PORT); #else remote->sin_port = htons(PORT); #endif if(connect(sock, (struct sockaddr *)remote, sizeof(struct sockaddr)) < 0){ perror("Could not connect"); exit(1); } get = build_get_query(host, page); fprintf(stderr, "Query is:\n<<START>>\n%s<<END>>\n", get); //Send the query to the server int sent = 0; while(sent < strlen(get)) { printf("body =[%s]\n",get); tmpres = send(sock, get+sent, strlen(get)-sent, 0); if(tmpres == -1){ perror("Can't send query"); exit(1); } sent += tmpres; } //now it is time to receive the page memset(buf, 0, sizeof(buf)); int htmlstart = 0; char * htmlcontent; while((tmpres = recv(sock, buf, BUFSIZ, 0)) > 0){ if(htmlstart == 0) { htmlcontent = strstr(buf, "\r\n\r\n"); if(htmlcontent != NULL){ htmlstart = 1; htmlcontent += 4; } }else{ htmlcontent = buf; } if(htmlstart){ fprintf(stdout, "%s", htmlcontent); } memset(buf, 0, tmpres); } if(tmpres < 0) { perror("Error receiving data"); } free(get); free(remote); free(ip); close(sock); return 0; } void usage() { fprintf(stderr, "利用方法: htmlget host [page]\n\ \thost: the website hostname. ex: coding.debuntu.org\n\ \tpage: the page to retrieve. ex: index.html, default: /\n"); } int create_tcp_socket() { int sock; if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){ perror("Can't create TCP socket"); exit(1); } return sock; } char *get_ip(char *host) { struct hostent *hent; int iplen = 15; //XXX.XXX.XXX.XXX char *ip = (char *)malloc(iplen+1); memset(ip, 0, iplen+1); printf("%s\n",host); #ifdef SUPPORT_PROXY if((hent = gethostbyname(PROXY_HOST)) == NULL) #else if((hent = gethostbyname(host)) == NULL) #endif { herror("Can't get IP"); exit(1); } if(inet_ntop(AF_INET, (void *)hent->h_addr_list[0], ip, iplen) == NULL) { perror("Can't resolve host"); exit(1); } return ip; } char *build_get_query(char *host, char *page) { char *query; char *getpage = page; #ifdef HTTP_1_1 char *tpl = "GET /%s HTTP/1.1\r\nHost: %s\r\nUser-Agent: %s\r\nConnection: close\r\n\r\n"; #else char *tpl = "GET /%s HTTP/1.0\r\nHost: %s\r\nUser-Agent: %s\r\n\r\n"; #endif if(getpage[0] == '/'){ getpage = getpage + 1; fprintf(stderr,"Removing leading \"/\", converting %s to %s\n", page, getpage); } // -5 is to consider the %s %s %s in tpl and the ending \0 query = (char *)malloc(strlen(host)+strlen(getpage)+strlen(USERAGENT)+strlen(tpl)-5); sprintf(query, tpl, getpage, host, USERAGENT); return query; }
g++ -o htmlget httpget.cpp
スポンサードリンク
「ホスト名」と取得したい「ファイル名」を引数にすることでファイルが取得できます。
$ ./htmlget 利用方法: htmlget host [page] host: the website hostname. ex: coding.debuntu.org page: the page to retrieve. ex: index.html, default: / $ ./htmlget uguisu.skr.jp index.html
スポンサードリンク