본문 바로가기
프로그래머의 길/리눅스

리눅스 http server

by 하늘아래. 2007. 11. 2.
반응형

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>

#define MAX_READY_QUEUE 100
#define HTTP_PORT 80
#define BUFFER_SIZE 512

void *conn_thread(void *arg)
{
 int sock_fd = (int)arg;
 int read_len, file_size;
 char buffer[BUFFER_SIZE];
 char *str_ptr, *tmp_ptr, *ctype = "txt/html";
 FILE *read_fp;

 while (1) {
  if ((read_len = read(sock_fd, buffer, BUFFER_SIZE - 1)) <= 0) {
   printf("socket read error\n");
   break;
  }
  buffer[read_len] = '\x00';

  if ((str_ptr = strstr(buffer, "GET")) == NULL) {
   continue;
  }

  strtok(str_ptr, " ?");
  str_ptr = strtok(NULL, " ?") + 1;

  printf("requested filename: %s\n", str_ptr);

  if ((read_fp = fopen(str_ptr, "rb")) == NULL) {
   printf("file not found\n");
   sprintf(buffer, "HTTP/1.1 400 Bad Request\n"
     "Content-length: 0\n\n");
   write(sock_fd, buffer, BUFFER_SIZE);
   break;
  }

  fseek(read_fp, 0, SEEK_END);
  file_size = ftell(read_fp);
  rewind(read_fp);

  tmp_ptr = strtok(str_ptr, "./");
  while (tmp_ptr) {
   str_ptr = tmp_ptr;
   tmp_ptr = strtok(NULL, "./");
  }
 
  printf("extension: %s\n", str_ptr);
  if (str_ptr != NULL) {
   if (strcasecmp(str_ptr, "gif") == 0) {
    ctype = "image/gif";
   } else if (strcasecmp(str_ptr, "jpg") == 0) {
    ctype = "image/jpeg";
   } else if (strcasecmp(str_ptr, "png") == 0) {
    ctype = "image/png";
   } else if (strcasecmp(str_ptr, "swf") == 0) {
    ctype = "application/x-shockwave-flash";
   }
  }

  sprintf(buffer, "HTTP/1.1 200 OK\n"
    "Content-length: %d\n"
    "Content-type: %s\n\n", file_size, ctype);

  write(sock_fd, buffer, strlen(buffer));

  while (!feof(read_fp)) {
   read_len = fread(buffer, 1, BUFFER_SIZE - 1, read_fp);
   if (read_len > 0) {
    write(sock_fd, buffer, read_len);
   }
  }

  fclose(read_fp);
 }

 close(sock_fd);
}

int main(void)
{
 struct sockaddr_in address;
 int    sock, conn, i, curr;
 size_t addrLength = sizeof(struct sockaddr_in);
 char   buff[512];

 if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
  printf("socket creation error\n");
  return -1;
 }

 memset(&address, 0, sizeof(address));
 address.sin_family  = AF_INET;
 address.sin_port = htons(HTTP_PORT);
 address.sin_addr.s_addr = htonl(INADDR_ANY);

 if (bind(sock, (struct sockaddr *)&address, sizeof(address)) == -1) {
  printf("bind address error\n");
  return -1;
 }

 if (listen(sock, MAX_READY_QUEUE)) {
  printf("listen error\n");
  return -1;
 }

 while (1) {
  pthread_t conn_tid;

  conn = accept(sock, (struct sockaddr *)&address, &addrLength);
  printf("new connection\n");

  pthread_create(&conn_tid, NULL, conn_thread, (void*)conn);
 }
}


반응형