C言語でHTTPクライアント
戻る
::::::::::::::
Makefile
::::::::::::::
# $Id: HttpClientTest.html,v 1.1 2009/06/22 16:11:45 kishi Exp kishi $
CFLAGS = -c -Wall -O2
OBJECT = HttpClient.o getConnection.o getTokens.o
EXE = HttpClient.exe
$(EXE): $(OBJECT)
gcc $(OBJECT) -o $(EXE) && strip $(EXE)
HttpClient.o: HttpClient.c common.h
gcc $(CFLAGS) HttpClient.c
getConnection.o: getConnection.c
gcc $(CFLAGS) getConnection.c
getTokens.o: getTokens.c
gcc $(CFLAGS) getTokens.c
clean:
rm -f *.o *.exe *~ *.bak *.orig
indent:
indent -br *.c
::::::::::::::
common.h
::::::::::::::
// $Id: HttpClientTest.html,v 1.1 2009/06/22 16:11:45 kishi Exp kishi $
int getConnection(char* hostname, int portNumber);
char **getTokens (char *input, char *pattern, int count);
::::::::::::::
HttpClient.c
::::::::::::::
/*
* $Id: HttpClientTest.html,v 1.1 2009/06/22 16:11:45 kishi Exp kishi $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include "./common.h"
#define BUF_LEN 8192
int
main (int argc, char *argv[])
{
int sock;
char buf[BUF_LEN];
char *URL;
char *hostname;
char *path;
int portNumber;
if (argc != 2) {
printf ("Usage: %s [URL]\n", argv[0]);
exit (1);
}
URL = argv[1];
///////////////////////////////////////////////////////////////////////
// URLから、ホスト名、ポート番号、パスを求める
///////////////////////////////////////////////////////////////////////
char **tokens =
getTokens (URL, "http://([[:alnum:].~?&%#_=-\\:]+)(\\/?.*)", 5);
if (tokens == NULL) {
perror ("invalid URL!");
exit (1);
}
hostname = tokens[1];
path = tokens[2];
tokens = getTokens (hostname, "(.+):(.+)", 5);
if (tokens != NULL) {
hostname = tokens[1];
portNumber = atoi (tokens[2]);
}
else {
portNumber = 80;
}
fprintf (stderr, "hostname=%s\n", hostname);
fprintf (stderr, "path=%s\n", path);
fprintf (stderr, "portNumber=%d\n", portNumber);
//---------------------------------------------------------------------------
// コネクションの取得
//---------------------------------------------------------------------------
sock = getConnection (hostname, portNumber);
FILE *fp = fdopen (sock, "r+");
if (fp == NULL) {
fprintf (stderr, "fdopen failed ...\n");
return 1;
}
// Bufferingしない
setvbuf (fp, NULL, _IONBF, 0);
// HTTPリクエスト
fprintf (fp, "GET / HTTP/1.0\r\n");
fprintf (fp, "Host: %s\r\n", hostname);
fprintf (fp, "\r\n");
//////////////////////////////////////////////////
// HTTPレスポンスヘッダを取得
//////////////////////////////////////////////////
while (1) {
if (fgets (buf, sizeof (buf), fp) == NULL) {
break;
}
// レスポンスヘッダをリストに格納する
// --- TO BE IMPLEMENTED --
printf ("%s", buf);
// CRLFが来たらヘッダ終了
if (buf[0] == 0x0d && buf[1] == 0x0a) {
break;
}
}
//////////////////////////////////////////////////
// HTTPレスポンスボディを取得
//////////////////////////////////////////////////
memset (buf, 0, sizeof (buf));
int len;
while ((len = read (sock, buf, BUF_LEN)) > 0) {
printf ("%s", buf);
memset (buf, 0, sizeof (buf));
}
printf ("%s", buf);
fclose (fp);
close (sock);
return 0;
}
::::::::::::::
getConnection.c
::::::::::::::
/*
* $Id: HttpClientTest.html,v 1.1 2009/06/22 16:11:45 kishi Exp kishi $
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
int
getConnection (char *hostname, int portNumber)
{
struct sockaddr_in addr;
struct hostent *he;
int sock;
if ((sock = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
perror ("socket");
exit (1);
}
bzero ((char *) &addr, sizeof (addr));
if ((he = gethostbyname (hostname)) == NULL) {
perror ("No such host");
exit (1);
}
bcopy (he->h_addr, &addr.sin_addr, he->h_length);
addr.sin_family = AF_INET;
addr.sin_port = htons (portNumber);
if (connect (sock, (struct sockaddr *) &addr, sizeof (addr)) < 0) {
perror ("connect");
exit (2);
}
return sock;
}
::::::::::::::
getTokens.c
::::::::::::::
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <regex.h>
/** $Id: HttpClientTest.html,v 1.1 2009/06/22 16:11:45 kishi Exp kishi $ */
char **
getTokens (char *input, char *pattern, int count)
{
int regsuccess; /* パターンマッチングの成功フラグ */
regex_t reg; /* regexパターンバッファ */
regmatch_t match[count]; /* マッチした場所格納用 */
char **tokens = (char **) malloc (count * sizeof (char *));
regcomp (®, pattern, REG_EXTENDED);
regsuccess = regexec (®, input, count, match, 0);
regfree (®);
if (regsuccess != 0) {
return NULL;
}
char **ptr = tokens;
int i;
for (i = 0; i < count; i++) {
int len = (int) (match[i].rm_eo - match[i].rm_so + 1);
*ptr = (char *) malloc (len + 1);
memset (*ptr, 0, len);
memcpy (*ptr, input + match[i].rm_so, len - 1);
++ptr;
}
return tokens;
}
戻る