i/* Author: bhw EMail: bhwshx@163.com Date: Thu 12 Mar 2009 03:17:15 PM CST*/ /*实现最简单的HTTP服务器*/ #include<stdio.h> #include<string.h> #include<stdlib.h> #include<unistd.h> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> #include<sys/stat.h> #include<fcntl.h> #define BACKLOG 3 #define BUFSIZE 1024*4 /*char *resp_head = "HTTP/1.1 200 OK/r/n" / "Content-Type: text/html/r/n" / "Content-Length:%d/r/n" / "/r/n"; */ char *not_found = "HTTP/1.1 404 Not Found/r/n" / "Content-Type: text/html/r/n" / "Content-Length: 40/r/n" / "/r/n" / "<HTML><BODY>File not found</BODY></HTML>"; char *bad_request = "HTTP/1.1 400 Bad Request/r/n" / "Content-Type: text/html/r/n" / "Content-Length: 39/r/n" / "/r/n" / "<h1>Bad Request (Invalid Hostname)</h1>"; /*char *moved_permanently = "HTTP/1.1 301 Moved Permanently/r/n"/ "Content-Length: 147/r/n" / "Content-Type: text/html/r/n" / "Location: %s/r/n" / "/r/n" / "<head><title>Document Moved</title></head><body><h1>Object Moved</h1>This document may be found <a HREF="/" mce_HREF="/""%s/">here</a></body>"; */ char *head_analysis(char *p); void read_send(const char *p, char *pbuf, int connfd); int main(void) { int listenfd; struct sockaddr_in servAddr; unsigned port = 80; printf("HTTP Server is starting at port %d.../n", port); listenfd = socket(AF_INET, SOCK_STREAM, 0); if(listenfd == -1) { printf("Invalid socket!/n"); return 1; } bzero(&servAddr, sizeof(servAddr)); servAddr.sin_family = AF_INET; servAddr.sin_port = htons(port); servAddr.sin_addr.s_addr = htonl(INADDR_ANY); printf("Server is listening.../n"); if(bind(listenfd, (struct sockaddr *)&servAddr, sizeof(struct sockaddr)) != 0) { close(listenfd); printf("Binding error/n"); return 1; } printf("Binding server to port %d successfully./n", port); if(listen(listenfd, BACKLOG) != 0) //accept BACKLOG clients at the same time { close(listenfd); printf("listen error/n"); return 1; } printf("Waiting client.../n"); while(1) { struct sockaddr_in cliAddr; size_t cliAddrLen = sizeof(cliAddr); pid_t pid; char *p = NULL, from[20], file_name[100] = "/home/LinuxC/", rcvbuf[1024], sendbuf[BUFSIZE]; int connfd = accept(listenfd, (struct sockaddr *)&cliAddr, &cliAddrLen); if(connfd < 0) { close(listenfd); printf("accept error/n"); return 1; } pid = fork(); if(pid == 0) //child process responsible for dealing with client { close(listenfd); strcpy(from, inet_ntoa(cliAddr.sin_addr)); printf("/n/nclient %s CONNECTED./n", from); if(recv(connfd, rcvbuf, sizeof(rcvbuf), 0) > 0) { printf("client command:%s/n", rcvbuf); p = head_analysis(rcvbuf); } else exit(0); if(p != NULL) { strcat(file_name, p); printf("FILE NAME :%s/n", file_name); read_send(file_name, sendbuf, connfd); } else send(connfd, bad_request, strlen(bad_request), 0); close(connfd); printf("DISCONNECTION TO CLIENT/n"); exit(0); } else if(pid > 0) close(connfd);//father process only responsible for accepting clients else return 1; }//while(1)'s close(listenfd); return 0; } char *head_analysis(char *p) { char *ptmp = p; if(strncmp(ptmp, "GET /", 5) == 0) { ptmp += 5; while(*ptmp != ' ') ptmp++; *ptmp++ = '/0'; if(strncmp(ptmp, "HTTP/", 5) == 0) return p+5; else return NULL; } else return NULL; } void read_send(const char *p, char *pbuf, int connfd) { int fd; size_t rdLen; fd = open(p, O_RDONLY); if(fd != -1) { send(connfd, "HTTP/1.1 200 OK/r/nContent-Type:text/html/r/n/r/n", strlen("HTTP/1.1 200 OK/r/nContent-Type:text/html/r/n/r/n"), 0); while((rdLen = read(fd, pbuf, BUFSIZE)) > 0) send(connfd, pbuf, rdLen, 0); printf("WRITE TO CLIENT FINISHED/n"); close(fd); } else send(connfd, not_found, strlen(not_found), 0); }