dhttpd.c
上传用户:ladybrid91
上传日期:2007-01-04
资源大小:287k
文件大小:6k
源码类别:

Web服务器

开发平台:

Unix_Linux

  1. /*
  2. ** dhttpd.c A dummy HTTP server for benchmarking purposes
  3. **
  4. ** Copyright (c) 1995 Peter Eriksson <pen@signum.se>
  5. **
  6. ** This program is free software; you can redistribute it and/or modify
  7. ** it under the terms of the GNU General Public License as published by
  8. ** the Free Software Foundation; either version 2 of the License, or
  9. ** (at your option) any later version.
  10. **
  11. ** This program is distributed in the hope that it will be useful,
  12. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ** GNU General Public License for more details.
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program; if not, write to the Free Software
  17. ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #include <stdio.h>
  20. #include <unistd.h>
  21. #include <fcntl.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <thread.h>
  25. #include <errno.h>
  26. #include <sys/types.h>
  27. #include <sys/socket.h>
  28. #include <sys/wait.h>
  29. #include <sys/mman.h>
  30. #include <netinet/in.h>
  31. #include <netinet/tcp.h>
  32. #include <arpa/inet.h>
  33. #include <sys/resource.h>
  34. char *mbuf;
  35. int mbufsize = 4096;
  36. int concurrency = 32;
  37. int port = 80;
  38. int bound = 0;
  39. int stack_size = 0;
  40. int use_exit = 0;
  41. int n_processes = 0;
  42. static void *request_thread(void *misc)
  43. {
  44.     int fd = * (int *) misc;
  45.     char buf[4096], *cp;
  46.     int len, val, tosend;
  47.     
  48.     val = 1;
  49.     setsockopt(fd, 6, TCP_NODELAY, (void *) &val, sizeof(val));
  50.     while ((len = read(fd, buf, sizeof(buf))) < 0 && errno == EINTR)
  51. ;
  52.     if (len < 0)
  53. perror("read");
  54.     
  55.     tosend = mbufsize;
  56.     cp = mbuf;
  57.     while (len > 0 && tosend > 0)
  58.     {
  59. while ((len = write(fd, cp, tosend)) < 0 && errno == EINTR)
  60.     ;
  61. if (len < 0)
  62.     perror("dhttpd: write");
  63. if (len > 0)
  64. {
  65.     tosend -= len;
  66.     cp += len;
  67. }
  68.     }
  69.     while ((len = close(fd)) < 0 && errno == EINTR)
  70. ;
  71.     if (len < 0)
  72. perror("close");
  73.     
  74.     free(misc);
  75.     if (use_exit)
  76. thr_exit(NULL);
  77.     return NULL;
  78. }
  79. int help(char *argv0)
  80. {
  81.     printf("Usage: %s [<options>]*nn", argv0);
  82.     puts("Option  tDefaultttDescription");
  83.     puts("------- t---------------t-----------------------------------");
  84.     puts("-H      tttDisplay this information");
  85.     printf("-p<port>t%-15d Server port to bind ton", port);
  86.     printf("-b      tttUse bound threadsn");
  87.     printf("-Q<num> t%-15d Parallell processes (if nonzero)n",
  88.    n_processes);
  89.     printf("-c<num> t%-15d Thread concurrency level if nonzeron",
  90.    concurrency);
  91.     printf("-s<size>t%-15d Thread stack size, if nonzeron",
  92.    stack_size);
  93.     printf("-l<size>t%-15d Reply buffer sizen",
  94.    mbufsize);
  95.     return 0;
  96. }
  97.     
  98. int main(int argc, char *argv[])
  99. {
  100.     mutex_t *accept_lock = NULL;
  101.     int *int_val = NULL;
  102.     int sock_fd, fd;
  103.     int one = 1;
  104.     struct sockaddr_in sin;
  105.     int *fdp;
  106.     int len, i;
  107.     struct rlimit rlb;
  108.     
  109.     
  110.     for (i = 1; i < argc && argv[i][0] == '-'; i++)
  111. switch (argv[i][1])
  112. {
  113.   case '?':
  114.   case 'H':
  115.     exit(help(argv[0]));
  116.     break;
  117.   case 'Q':
  118.     n_processes = atoi(argv[i]+2);
  119.     break;
  120.     
  121.   case 'p':
  122.     port = atoi(argv[i]+2);
  123.     break;
  124.   case 's':
  125.     stack_size = atoi(argv[i]+2);
  126.     break;
  127.   case 'b':
  128.     bound = 1;
  129.     break;
  130.   case 'E':
  131.     use_exit = 1;
  132.     break;
  133.     
  134.   case 'l':
  135.     mbufsize = atoi(argv[i]+2);
  136.     if (mbufsize < 128)
  137.     {
  138. fprintf(stderr, "%s: buffer length (%d) is too smalln",
  139. argv[0], mbufsize);
  140. exit(1);
  141.     }
  142.     break;
  143.   case 'c':
  144.     concurrency = atoi(argv[i]+2);
  145.     break;
  146.   default:
  147.     fprintf(stderr, "%s: unknown switch '%s', try -H for helpn",
  148.     argv[0], argv[1]);
  149.     exit(1);
  150. }
  151.     mbuf = malloc(mbufsize);
  152.     if (mbuf == NULL)
  153.     {
  154. perror("malloc");
  155. exit(1);
  156.     }
  157.     
  158.     if (getrlimit(RLIMIT_NOFILE, &rlb) < 0)
  159.     {
  160. perror("getrlimit()");
  161. rlb.rlim_max = 64;
  162.     }
  163.     
  164.     rlb.rlim_cur = rlb.rlim_max;
  165.     
  166.     if (setrlimit(RLIMIT_NOFILE, &rlb) < 0)
  167. perror("setrlimit()");
  168.     
  169.     sprintf(mbuf, "HTTP/1.0 200 OKrnContent-Type: text/plainrnrn");
  170.     len = strlen(mbuf);
  171.     memset(mbuf+len, 'A', mbufsize-len);
  172.    
  173.     sin.sin_family = AF_INET;
  174.     sin.sin_addr.s_addr = INADDR_ANY;
  175.     sin.sin_port = htons(port);
  176.     if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  177.     {
  178. perror("sock_fd");
  179. exit(1);
  180.     }
  181.     
  182.     setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (void *) &one, sizeof(one));
  183.     if (bind(sock_fd, (struct sockaddr *) &sin, sizeof(sin)) < 0)
  184.     {
  185. perror("bind");
  186. exit(1);
  187.     }
  188.     
  189.     if (listen(sock_fd, 1024) < 0)
  190.     {
  191. perror("listen");
  192. exit(1);
  193.     }
  194.     if (n_processes > 0)
  195.     {
  196. pid_t pid;
  197. int child_status, fd;
  198. while ((fd = open("/dev/zero", 2)) < 0 && errno == EINTR)
  199.     ;
  200. if (fd < 0)
  201. {
  202.     perror("open("/dev/zero")");
  203.     exit(1);
  204. }
  205. accept_lock = (mutex_t *) mmap((caddr_t) NULL,
  206.        sizeof(mutex_t),
  207.        PROT_READ+PROT_WRITE,
  208.        MAP_SHARED, fd, 0);
  209. int_val = (int *) mmap((caddr_t) NULL,
  210.        sizeof(int),
  211.        PROT_READ+PROT_WRITE,
  212.        MAP_SHARED, fd, 0);
  213. while (close(fd) < 0 && errno == EINTR)
  214.     ;
  215. mutex_init(accept_lock, USYNC_PROCESS, NULL);
  216. *int_val = 0;
  217. for (i = 0; i < n_processes; i++)
  218. {
  219.     if (fork() == 0)
  220. goto Request;
  221. }
  222. while (i > 0)
  223. {
  224.     while ((pid = waitpid(-1, &child_status, 0)) < 0 && errno == EINTR)
  225. ;
  226.     
  227.     printf("Process %d exitedn", (int) pid);
  228.     --i;
  229. }
  230. exit(0);
  231.     }
  232.   Request:
  233.     thr_setconcurrency(concurrency);
  234.     
  235.   Loop:
  236.     if (n_processes > 0)
  237. mutex_lock(accept_lock);
  238.     
  239.     while ((fd = accept(sock_fd, NULL, NULL)) < 0 &&
  240.    (errno == EINTR || errno == EPROTO))
  241.     {
  242. if (errno == EPROTO)
  243.     putc('.', stderr);
  244.     }
  245.     
  246.     if (n_processes > 0)
  247. mutex_unlock(accept_lock);
  248.     
  249.     if (fd < 0)
  250.     {
  251. perror("accept");
  252. _exit(1);
  253.     }
  254.     fdp = (int *) malloc(sizeof(int));
  255.     if (fdp == NULL)
  256.     {
  257. perror("malloc");
  258. _exit(1);
  259.     }
  260.     
  261.     *fdp = fd;
  262.     
  263.     if (thr_create(NULL,
  264.    stack_size,
  265.    request_thread,
  266.    fdp,
  267.    THR_DETACHED+THR_DAEMON+(bound?THR_BOUND:0),
  268.    NULL) < 0)
  269.     {
  270. perror("thr_create");
  271. _exit(1);
  272.     }
  273.     goto Loop;
  274. }