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 (&reg, pattern, REG_EXTENDED);
  regsuccess = regexec (&reg, input, count, match, 0);
  regfree (&reg);

  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;
}
戻る

inserted by FC2 system