简单http_server的C语言实现

主要实现以下几点:

1.静态文件访问,包括jpg、html、css等

2.文件不存在404

3.目录列表

4.501 Not Implemented

=============================================================================

启动脚本
Shell代码 复制代码 收藏代码
  1. #!/bin/sh
  2. ps -ef | grep fasthttp | grep -v grep | awk '{print $2}' | xargs -t -i kill -9 {} >/dev/null
  3. gcc fasthttp.c -o fasthttp
  4. $(pwd)/fasthttp


以下是源码

=====================================================================================
C代码 复制代码 收藏代码
  1. #include <string.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <netinet/in.h>
  5. #include <error.h>
  6. #include <errno.h>
  7. #include <sys/types.h>
  8. #include <dirent.h>
  9. #include <sys/socket.h>
  10. #include <sys/stat.h>
  11. #include <unistd.h>
  12. #include <fcntl.h>
  13. // 建立socket 开始侦听 接收连接 接收客户端数据 解析http协议 发送文件数据给客户端
  14. #define HTTP_PORT "2010"
  15. #define MAX_CONNECTION 10
  16. #define DOCUMENT_ROOT "www"
  17. #define LOG_PATH "log/access.log"
  18. void parser(char *s,char res[][255],char host[][255]);
  19. static char *strtoupper( char *s );
  20. static long filesize(const char *filename);
  21. static int file_exists(const char *filename);
  22. static void mime_content_type( const char *name, char *ret );
  23. static int WriteLog( const char *message );
  24. static int is_dir(const char *filename);
  25. static unsigned short g_is_log = 1;
  26. static int g_log_fd = 0;
  27. int main(void)
  28. {
  29. int server_sock;
  30. int client_sock;
  31. struct sockaddr_in server_addr;
  32. struct sockaddr_in client_addr;
  33. struct sockaddr_in sin;
  34. struct stat file_stat;
  35. pid_t pid;
  36. char client_ip[100];
  37. char buf[20000];
  38. char buf_all[2000];
  39. char buf1[2000];
  40. char p[3][255];
  41. char h[3][255];
  42. char tmp[2000];
  43. char cwd[1024];
  44. char filename[2000];
  45. char filepath[2000];
  46. int fd,size;
  47. int currentConn = 0;
  48. DIR * dir;
  49. struct dirent * ptr;
  50. chdir("../");
  51. if ( (pid = fork()) < 0 )
  52. {
  53. perror("fork");
  54. exit(1);
  55. }
  56. else if ( pid != 0)
  57. {
  58. exit(1);
  59. }
  60. if((server_sock = socket(AF_INET,SOCK_STREAM,0)) < 0)
  61. {
  62. perror("socket");
  63. exit(1);
  64. }
  65. memset(&server_addr,0,sizeof(server_addr));
  66. server_addr.sin_family = AF_INET;
  67. server_addr.sin_port = htons(atoi(HTTP_PORT));
  68. server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  69. if(bind(server_sock,(struct sockaddr*)&server_addr,sizeof(server_addr)) < 0)
  70. {
  71. perror("bind");
  72. exit(1);
  73. }
  74. if(listen(server_sock,MAX_CONNECTION) < 0)
  75. {
  76. perror("listen");
  77. exit(1);
  78. }
  79. printf("fasthttp successful created ...\n");
  80. while(1)
  81. {
  82. unsigned int clientlen = sizeof(client_addr);
  83. if((client_sock = accept(server_sock,(struct sockaddr*)&client_addr,&clientlen)) < 0)
  84. {
  85. perror("accept");
  86. exit(1);
  87. }
  88. if((pid = fork()) == 0)
  89. {
  90. if(read(client_sock,buf,20000) < 0)
  91. {
  92. perror("read data from client");
  93. exit(1);
  94. }
  95. parser(buf,p,h);
  96. if(strcmp(strtoupper(p[0]),"GET") != 0
  97. && strcmp(strtoupper(p[0]),"POST") != 0
  98. && strcmp(strtoupper(p[0]),"HEAD") != 0)
  99. {
  100. memset(&buf,0,sizeof(buf));
  101. sprintf(buf, "HTTP/1.1 501 Not Implemented\r\nServer: %s\r\nContent-Type: text/html\r\nContent-Length: 1489\r\nAccept-Ranges: bytes\r\nConnection: close\r\n\r\n", "Apache");
  102. write(client_sock,buf,strlen(buf));
  103. memset(&buf,0,sizeof(buf));
  104. sprintf(buf,"<h2>%s Method Not Implemented</h2>","501");
  105. write(client_sock,buf,strlen(buf));
  106. close(client_sock);
  107. exit(0);
  108. }
  109. if(strcmp(p[1],"/") == 0)
  110. {
  111. memset(&tmp,0,sizeof(tmp));
  112. sprintf(tmp,"%s","index.html");
  113. strcat(p[1],tmp);
  114. }
  115. WriteLog(p[1]);
  116. getcwd(filepath, sizeof(filepath));
  117. strcat(filepath,"/");
  118. strcat(filepath,DOCUMENT_ROOT);
  119. strcat(filepath,p[1]);
  120. if(!file_exists(filepath))
  121. {
  122. memset(&buf,0,sizeof(buf));
  123. sprintf(buf, "HTTP/1.1 404 Not Found\r\nServer: %s\r\nContent-Type: text/html\r\nContent-Length: 257271\r\nConnection: close\r\n\r\n", "Apache");
  124. write(client_sock,buf,strlen(buf));
  125. memset(&buf,0,sizeof(buf));
  126. sprintf(buf,"<html><head><title>404 Not Found</title></head><body bgcolor=\"white\"><center><h1>404 Not Found</h1></center><hr><center>Powered by %s</center></body></html>","fasthttp");
  127. write(client_sock,buf,strlen(buf));
  128. close(client_sock);
  129. memset(&buf,0,sizeof(buf));
  130. sprintf(buf,"404 Not Found\t%s\n",filepath);
  131. WriteLog(buf);
  132. exit(0);
  133. }
  134. if(access(filepath,R_OK) < 0)
  135. {
  136. memset(&buf,0,sizeof(buf));
  137. sprintf(buf, "HTTP/1.1 403 Forbidden\r\nServer: %s\r\nContent-Type: text/html\r\nContent-Length: 25727\r\nConnection: close\r\n\r\n", "Apache");
  138. write(client_sock,buf,strlen(buf));
  139. close(client_sock);
  140. exit(0);
  141. }
  142. /** 目录列表 **/
  143. if(is_dir(filepath))
  144. {
  145. memset(&tmp,0,sizeof(tmp));
  146. sprintf(tmp,"<html><head><title>Index of %s</title></head><body><h1>Index of %s</h1><ul><li><a href=\"/\"> Parent Directory</a></li>",filepath,filepath);
  147. strcat(buf,tmp);
  148. if((dir = opendir(filepath)) != NULL)
  149. {
  150. while((ptr = readdir(dir)) != NULL)
  151. {
  152. if(strcmp(ptr->d_name,".") == 0 || strcmp(ptr->d_name,"..") == 0)
  153. {
  154. continue;
  155. }
  156. memset(&buf,0,sizeof(buf));
  157. sprintf(buf,"%s/%s",filepath,ptr->d_name);
  158. if(is_dir(buf))
  159. {
  160. memset(&buf,0,sizeof(buf));
  161. sprintf(buf,"<li><a href=\"%s/\"> %s/</a></li>",ptr->d_name,ptr->d_name);
  162. }
  163. else
  164. {
  165. memset(&buf,0,sizeof(buf));
  166. sprintf(buf,"<li><a href=\"%s\"> %s</a></li>",ptr->d_name,ptr->d_name);
  167. }
  168. strcat(tmp,buf);
  169. }
  170. }
  171. closedir(dir);
  172. memset(&buf,0,sizeof(buf));
  173. sprintf(buf,"%s","</ul>");
  174. strcat(tmp,buf);
  175. memset(&buf,0,sizeof(buf));
  176. sprintf(buf, "HTTP/1.1 200 OK\r\nServer: fasthttp\r\nContent-Type: text/html;charset=utf-8\r\nContent-Length: %d\r\nConnection: close\r\n\r\n", strlen(tmp));
  177. write(client_sock,buf,strlen(buf));
  178. write(client_sock,tmp,strlen(tmp));
  179. close(client_sock);
  180. }
  181. memset(&tmp,0,sizeof(tmp));
  182. mime_content_type(filepath,tmp);
  183. memset(&buf,0,sizeof(buf));
  184. sprintf(buf, "HTTP/1.1 200 OK\r\nServer: %s\r\nContent-Type: %s\r\nContent-Length: 25727\r\nConnection: close\r\n\r\n", "Apache",tmp);
  185. write(client_sock,buf,strlen(buf));
  186. memset(&buf,0,sizeof(buf));
  187. fd = open(filepath,O_RDONLY);
  188. read(fd,buf,filesize(filepath));
  189. close(fd);
  190. write(client_sock,buf,filesize(filepath));
  191. close(client_sock);
  192. memset(&buf,0,sizeof(buf));
  193. sprintf(buf,"200 OK\t%s\t%d\n",filepath,filesize(filepath));
  194. WriteLog(buf);
  195. exit(0);
  196. }
  197. else
  198. {
  199. wait(NULL);
  200. }
  201. close(client_sock);
  202. }
  203. }
  204. void parser(char *s,char res[][255],char host[][255])
  205. {
  206. int i,j = 0;
  207. int n;
  208. char hosts[255];
  209. for (i = 0;s[i] != '\r';i++) /* obtain the first line in http protocol head */
  210. ;
  211. s[i] = '\0';
  212. n=i++;
  213. for (i = 0,j = 0;i < 3;i++,j++) /* divide the protocol head in blank */
  214. {
  215. strcpy(res[j],strsep(&s," "));
  216. }
  217. for(i=n;s[i] != '\r';i++)
  218. {
  219. strcat(hosts,s[i]);
  220. }
  221. for (i = 0,j = 0;i < 3;i++,j++) /* divide the protocol head in blank */
  222. {
  223. strcpy(host[j],strsep(&hosts,":"));
  224. }
  225. }
  226. /**
  227. * strtoupper - string to upper
  228. *
  229. */
  230. static char *strtoupper( char *s )
  231. {
  232. int i, len = sizeof(s);
  233. for( i = 0; i < len; i++ )
  234. {
  235. s[i] = ( s[i] >= 'a' && s[i] <= 'z' ? s[i] + 'A' - 'a' : s[i] );
  236. }
  237. return(s);
  238. }
  239. /**
  240. * filesize - get file size
  241. */
  242. static long filesize(const char *filename)
  243. {
  244. struct stat buf;
  245. if (!stat(filename, &buf))
  246. {
  247. return buf.st_size;
  248. }
  249. return 0;
  250. }
  251. /**
  252. * file_exists - check file is exist
  253. */
  254. static int file_exists(const char *filename)
  255. {
  256. struct stat buf;
  257. if (stat(filename, &buf) < 0)
  258. {
  259. if (errno == ENOENT)
  260. {
  261. return 0;
  262. }
  263. }
  264. return 1;
  265. }
  266. /**
  267. * Get MIME type header
  268. *
  269. */
  270. static void mime_content_type( const char *name, char *ret ){
  271. char *dot, *buf;
  272. dot = strrchr(name, '.');
  273. /* Text */
  274. if ( strcmp(dot, ".txt") == 0 ){
  275. buf = "text/plain";
  276. } else if ( strcmp( dot, ".css" ) == 0 ){
  277. buf = "text/css";
  278. } else if ( strcmp( dot, ".js" ) == 0 ){
  279. buf = "text/javascript";
  280. } else if ( strcmp(dot, ".xml") == 0 || strcmp(dot, ".xsl") == 0 ){
  281. buf = "text/xml";
  282. } else if ( strcmp(dot, ".xhtm") == 0 || strcmp(dot, ".xhtml") == 0 || strcmp(dot, ".xht") == 0 ){
  283. buf = "application/xhtml+xml";
  284. } else if ( strcmp(dot, ".html") == 0 || strcmp(dot, ".htm") == 0 || strcmp(dot, ".shtml") == 0 || strcmp(dot, ".hts") == 0 ){
  285. buf = "text/html";
  286. /* Images */
  287. } else if ( strcmp( dot, ".gif" ) == 0 ){
  288. buf = "image/gif";
  289. } else if ( strcmp( dot, ".png" ) == 0 ){
  290. buf = "image/png";
  291. } else if ( strcmp( dot, ".bmp" ) == 0 ){
  292. buf = "application/x-MS-bmp";
  293. } else if ( strcmp( dot, ".jpg" ) == 0 || strcmp( dot, ".jpeg" ) == 0 || strcmp( dot, ".jpe" ) == 0 || strcmp( dot, ".jpz" ) == 0 ){
  294. buf = "image/jpeg";
  295. /* Audio & Video */
  296. } else if ( strcmp( dot, ".wav" ) == 0 ){
  297. buf = "audio/wav";
  298. } else if ( strcmp( dot, ".wma" ) == 0 ){
  299. buf = "audio/x-ms-wma";
  300. } else if ( strcmp( dot, ".wmv" ) == 0 ){
  301. buf = "audio/x-ms-wmv";
  302. } else if ( strcmp( dot, ".au" ) == 0 || strcmp( dot, ".snd" ) == 0 ){
  303. buf = "audio/basic";
  304. } else if ( strcmp( dot, ".midi" ) == 0 || strcmp( dot, ".mid" ) == 0 ){
  305. buf = "audio/midi";
  306. } else if ( strcmp( dot, ".mp3" ) == 0 || strcmp( dot, ".mp2" ) == 0 ){
  307. buf = "audio/x-mpeg";
  308. } else if ( strcmp( dot, ".rm" ) == 0 || strcmp( dot, ".rmvb" ) == 0 || strcmp( dot, ".rmm" ) == 0 ){
  309. buf = "audio/x-pn-realaudio";
  310. } else if ( strcmp( dot, ".avi" ) == 0 ){
  311. buf = "video/x-msvideo";
  312. } else if ( strcmp( dot, ".3gp" ) == 0 ){
  313. buf = "video/3gpp";
  314. } else if ( strcmp( dot, ".mov" ) == 0 ){
  315. buf = "video/quicktime";
  316. } else if ( strcmp( dot, ".wmx" ) == 0 ){
  317. buf = "video/x-ms-wmx";
  318. } else if ( strcmp( dot, ".asf" ) == 0 || strcmp( dot, ".asx" ) == 0 ){
  319. buf = "video/x-ms-asf";
  320. } else if ( strcmp( dot, ".mp4" ) == 0 || strcmp( dot, ".mpg4" ) == 0 ){
  321. buf = "video/mp4";
  322. } else if ( strcmp( dot, ".mpe" ) == 0 || strcmp( dot, ".mpeg" ) == 0 || strcmp( dot, ".mpg" ) == 0 || strcmp( dot, ".mpga" ) == 0 ){
  323. buf = "video/mpeg";
  324. /* Documents */
  325. } else if ( strcmp( dot, ".pdf" ) == 0 ){
  326. buf = "application/pdf";
  327. } else if ( strcmp( dot, ".rtf" ) == 0 ){
  328. buf = "application/rtf";
  329. } else if ( strcmp( dot, ".doc" ) == 0 || strcmp( dot, ".dot" ) == 0 ){
  330. buf = "application/msword";
  331. } else if ( strcmp( dot, ".xls" ) == 0 || strcmp( dot, ".xla" ) == 0 ){
  332. buf = "application/msexcel";
  333. } else if ( strcmp( dot, ".hlp" ) == 0 || strcmp( dot, ".chm" ) == 0 ){
  334. buf = "application/mshelp";
  335. } else if ( strcmp( dot, ".swf" ) == 0 || strcmp( dot, ".swfl" ) == 0 || strcmp( dot, ".cab" ) == 0 ){
  336. buf = "application/x-shockwave-flash";
  337. } else if ( strcmp( dot, ".ppt" ) == 0 || strcmp( dot, ".ppz" ) == 0 || strcmp( dot, ".pps" ) == 0 || strcmp( dot, ".pot" ) == 0 ){
  338. buf = "application/mspowerpoint";
  339. /* Binary & Packages */
  340. } else if ( strcmp( dot, ".zip" ) == 0 ){
  341. buf = "application/zip";
  342. } else if ( strcmp( dot, ".rar" ) == 0 ){
  343. buf = "application/x-rar-compressed";
  344. } else if ( strcmp( dot, ".gz" ) == 0 ){
  345. buf = "application/x-gzip";
  346. } else if ( strcmp( dot, ".jar" ) == 0 ){
  347. buf = "application/java-archive";
  348. } else if ( strcmp( dot, ".tgz" ) == 0 || strcmp( dot, ".tar" ) == 0 ){
  349. buf = "application/x-tar";
  350. } else {
  351. buf = "application/octet-stream";
  352. }
  353. strcpy(ret, buf);
  354. }
  355. /**
  356. * Log message
  357. *
  358. */
  359. static int WriteLog( const char *message )
  360. {
  361. if ( !g_is_log )
  362. {
  363. fprintf(stderr, "%s", message);
  364. return 0;
  365. }
  366. if ( g_log_fd == 0 )
  367. {
  368. char g_log_path[2000];
  369. getcwd(g_log_path, sizeof(g_log_path));
  370. strcat(g_log_path,"/");
  371. strcat(g_log_path,LOG_PATH);
  372. if ( (g_log_fd = open(g_log_path, O_RDWR|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1 )
  373. {
  374. perror("open log file error");
  375. return -1;
  376. }
  377. }
  378. if (write(g_log_fd, message, strlen(message)) == -1)
  379. {
  380. perror("write log error");
  381. return -1;
  382. }
  383. return 0;
  384. }
  385. /**
  386. * is_dir - check file is directory
  387. *
  388. */
  389. static int is_dir(const char *filename){
  390. struct stat buf;
  391. if ( stat(filename, &buf) < 0 ){
  392. return -1;
  393. }
  394. if (S_ISDIR(buf.st_mode)){
  395. return 1;
  396. }
  397. return 0;
  398. }

你可能感兴趣的:(简单http_server的C语言实现)