目前状态仅仅是“能运行”。仅作为记录。
1 #include <unistd.h> 2 #include <fcntl.h> 3 #include <sys/socket.h> 4 #include <sys/mman.h> 5 #include <sys/stat.h> 6 #include <netinet/in.h> 7 #include <arpa/inet.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <errno.h> 12 #include <signal.h> 13 14 #include "rio/rio.h" 15 16 #define SA struct sockaddr 17 #define ERROR(msg) do{perror(msg);exit(-1);}while(0) 18 #define PORT 8080 19 #define MAXSIZE 8192 20 21 void process(int fd); 22 void process_request_body(rio_t *request); 23 void client_error(int fd, int no,const char *msg); 24 int process_uri(const char *uri, char *filename, char *filetype); 25 26 int main(int argc, char **argv) 27 { 28 int listenfd, connfd, err; 29 struct sockaddr_in servaddr; 30 31 signal(SIGPIPE, SIG_IGN); 32 33 if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 34 ERROR("SOCKET"); 35 36 memset(&servaddr, 0, sizeof(servaddr)); 37 servaddr.sin_family = AF_INET; 38 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 39 servaddr.sin_port = htons(PORT); 40 41 if((err = bind(listenfd, (SA *)&servaddr, sizeof(servaddr))) < 0) 42 ERROR("BIND"); 43 44 if((err = listen(listenfd, 256)) < 0) 45 ERROR("LISTEN"); 46 47 for(;;) 48 { 49 if((connfd = accept(listenfd, NULL, NULL)) < 0) 50 ERROR("ACCEPT"); 51 process(connfd); 52 } 53 exit(0); 54 } 55 56 void process(int fd) 57 { 58 char content[MAXSIZE], temp[MAXSIZE], method[MAXSIZE], uri[MAXSIZE], protocol[MAXSIZE]; 59 char filename[MAXSIZE], filetype[MAXSIZE]; 60 int err, ffd; 61 rio_t request; 62 char *handle; 63 struct stat sbuf; 64 65 rio_readinitb(&request, fd); 66 67 if((err = rio_readlineb(&request, temp, MAXSIZE)) < 0) 68 ERROR("READLINE"); 69 70 sscanf(temp, "%s %s %s", method, uri, protocol); 71 process_request_body(&request); 72 if(strcasecmp(method, "GET")) 73 { 74 client_error(request.rio_fd, 403, "not suppose"); 75 return; 76 } 77 78 if((err = process_uri(uri, filename, filetype)) < 0) 79 { 80 client_error(fd, 403, "Not Found"); 81 return; 82 } 83 ffd = open(filename, O_RDONLY, 0); 84 fstat(ffd, &sbuf); 85 handle = mmap(0, sbuf.st_size, PROT_READ, MAP_PRIVATE, ffd, 0); 86 close(ffd); 87 88 sprintf(content, "HTTP/1.1 200 OK\r\n"); 89 sprintf(content, "%sContent-type: %s\r\n", content, filetype); 90 sprintf(content, "%sContent-length: %lu\r\n\r\n", content, sbuf.st_size); 91 92 printf("%s", content); 93 94 rio_writen(fd, content, strlen(content)); 95 96 rio_writen(fd, handle, sbuf.st_size); 97 munmap(handle, sbuf.st_size); 98 close(fd); 99 return; 100 } 101 102 void process_request_body(rio_t *request) 103 { 104 char buf[MAXSIZE]; 105 rio_readlineb(request, buf, MAXSIZE); 106 while(strcmp(buf, "\r\n")) 107 { 108 rio_readlineb(request, buf, MAXSIZE); 109 } 110 return; 111 } 112 113 void client_error(int fd, int no,const char *msg) 114 { 115 char buf[MAXSIZE]; 116 sprintf(buf, "HTTP/1.1 %d %s\r\n", no, msg); 117 sprintf(buf, "%sContent-length: %d\r\n\r\n", buf, 0); 118 rio_writen(fd, buf, strlen(buf)); 119 close(fd); 120 } 121 122 int process_uri(const char *uri, char *filename, char *filetype) 123 { 124 char buf[MAXSIZE]; 125 struct stat sbuf; 126 int err; 127 128 strcpy(buf, "."); 129 strcat(buf, uri); 130 131 if(buf[strlen(buf) - 1] == '/') 132 strcat(buf, "index.html"); 133 134 printf("____%s____\n", buf); 135 136 if((err = stat(buf, &sbuf)) < 0) 137 return -1; 138 139 strcpy(filename, buf); 140 141 printf("%s\n", filename); 142 143 if((S_ISREG(sbuf.st_mode)) && (S_IRUSR & sbuf.st_mode)) 144 { 145 if(strstr(filename, "html")) 146 strcpy(filetype, "text/html"); 147 else if(strstr(filename, "jpg")) 148 strcpy(filetype, "image/jpeg"); 149 else if(strstr(filetype, "gif")) 150 strcpy(filetype, "image/gif"); 151 else if(strstr(filename, "png")) 152 strcpy(filetype, "image/png"); 153 else 154 strcpy(filetype, "text/plain"); 155 } 156 printf("%s\n", filetype); 157 return 0; 158 }