HTTP 1
引数に指定したURLの情報とソースを表示するプログラム.
適切なエラー処理がところどころしていませんので, 引数を指定する際は注意してください.
/* http.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 80
int main(int argc, char **argv)
{
int sock;
int http_val = 0;
int https_val = 0;
socklen_t len = 0;
ssize_t byte;
char *tmp;
char *ch;
char send_buff[256];
char buff[512];
struct hostent *host_name;
struct servent *service;
struct sockaddr_in addr;
if(argc != 2) {
fprintf(stderr, "Usage: %s [URL]\n", argv[0]);
exit(EXIT_FAILURE);
}
tmp = (char *)malloc(sizeof(char) * 256);
http_val = strcmp(argv[1], "http://");
https_val = strcmp(argv[1], "https://");
if(http_val > https_val) {
sscanf(argv[1], "http://%s", tmp);
}
else if(https_val > http_val) {
sscanf(argv[1], "https://%s", tmp);
}
else if(https_val && https_val)
strcpy(tmp, argv[1]);
if((ch = strchr(tmp, '/')) != NULL) {
*ch = '\0';
}
printf("tmp = %s\n", tmp);
if((host_name = gethostbyname(tmp)) == NULL) {
perror("gethostbyname(3)");
exit(EXIT_FAILURE);
}
printf("h_name = %s\n", host_name->h_name);
printf("h_addrtype = %d\n", host_name->h_addrtype);
printf("h_length = %d\n", host_name->h_length);
if((service = getservbyname("http", "tcp")) == NULL) {
perror("getservbyname(3)");
exit(EXIT_FAILURE);
}
printf("s_name = %s\n", service->s_name);
printf("s_port = %d\n", service->s_port);
printf("s_proto = %s\n", service->s_proto);
bcopy(host_name->h_addr, &addr.sin_addr, host_name->h_length);
addr.sin_family = AF_INET;
addr.sin_port = service->s_port;
if((sock = socket(AF_INET, SOCK_STREAM, 0)) == EOF) {
perror("socket(2)");
exit(EXIT_FAILURE);
}
len = sizeof(addr);
if(connect(sock, (struct sockaddr *)&addr, len) == EOF) {
perror("connect(2)");
exit(EXIT_FAILURE);
}
sprintf(send_buff, "GET: %s HTTP/1.0\r\n", tmp);
printf("send_buff = %s", send_buff);
write(sock, send_buff, strlen(send_buff));
sprintf(send_buff, "HOST: %s:%d\r\n", tmp, PORT);
printf("send_buff = %s", send_buff);
write(sock, send_buff, strlen(send_buff));
sprintf(send_buff, "Reference: %s\r\n", argv[1]);
printf("send_buff = %s\n", send_buff);
write(sock, send_buff, strlen(send_buff));
sprintf(send_buff, "\r\n");
write(sock, send_buff, strlen(send_buff));
printf("\n ~~~ Get Message %s Server ~~~ \n\n", tmp);
free(tmp);
while(1) {
if((byte = read(sock, buff, 512)) == EOF) {
perror("read(2)");
exit(EXIT_FAILURE);
}
if(byte == 0)
break;
if(write(1, buff, byte) == EOF) {
perror("write(2)");
exit(EXIT_FAILURE);
}
}
close(sock);
return 0;
}
実行例:
$ ./http https://www.google.co.jp
tmp = google.co.jp
h_name = google.co.jp
h_addrtype = 2
h_length = 4
s_name = http
s_port = 20480
s_proto = tcp
send_buff = GET: google.co.jp HTTP/1.0
send_buff = HOST: google.co.jp:80
send_buff = Reference: https://google.co.jp/index.html
~~~ Get Message google.co.jp Server ~~~
HTTP/1.0 405 Method Not Allowed
Content-Type: text/html; charset=UTF-8
Content-Length: 959
Date: Fri, 15 Mar 2013 05:45:50 GMT
Server: GFE/2.0
<!DOCTYPE html>
<html lang=en>
<meta charset=utf-8>
<meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
<title>Error 405 (Method Not Allowed)!!1</title>
<style>
*{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}
</style>
<a href=//www.google.com/><img src=//www.google.com/images/errors/logo_sm.gif alt=Google></a>
<p><b>405.</b> <ins>That’s an error.</ins>
<p>The request method <code>GET:</code> is inappropriate for the URL <code>/</code>. <ins>That’s all we know.</ins>