天天看点

web server服务程式编写

  1. 本程序是一个提供特殊服务的Web Server。该程序是一个Daemon程序,用单进程+I/O多路转换(select)的方式接收Http的Get请求,请求中是一个字符串(可以是数字或者字母),返回一个PNG格式的图片,整个过程符合Http 1.0协议。
  2.         本程序类似于网站上常用的生成“验证码”的程序。
  3.         本程序在FreeBSD环境下开发完成,并可同时在FreeBSD和Windows (Cygwin)下编译运行。FreeBSD环境安装有gd-1.8.4库,Cygwin环境安装有libpng-1.2.8和gd-2.0.33库,用于生成PNG图片。
  4.         整个程序用C语言完成,源代码如下:
  5. #include <sys/types.h>
  6. #include <sys/stat.h>
  7. #include <sys/socket.h>
  8. #include <netinet/in.h>
  9. #include <sys/time.h>
  10. #include <signal.h>
  11. #include <fcntl.h>
  12. #include <stdio.h>
  13. #include <time.h>
  14. #include <syslog.h>
  15. #include <errno.h>
  16. #include <string.h>
  17. #include <stdarg.h>
  18. #include <unistd.h>
  19. #include <gd.h>
  20. #include <gdfontg.h>  
  21. #define MAXCLIENT 1024  
  22. #define BUFFSIZE 4096
  23. int daemon_init(const char *); 
  24. int getpng(char *,char *,int); 
  25. void sendFile(int, char *); 
  26. void log_sys(const char *, ...);
  27. static void log_doit(int, int, const char *, va_list ap);
  28. int
  29. main(int argc, char **argv)
  30. {
  31.  int   i,maxi,maxfd,listenfd,connfd,hfd,nready,client[MAXCLIENT];
  32.  char   *p,*pp, recvbuf[BUFFSIZE];
  33.  ssize_t   recvlen;
  34.  fd_set   rset, allset;
  35.  struct sockaddr_in servaddr;
  36.  daemon_init(argv[0]);    
  37.  listenfd=socket(AF_INET, SOCK_STREAM, 0);
  38.  bzero(&servaddr, sizeof(servaddr));  
  39.  servaddr.sin_family      =AF_INET;
  40.  servaddr.sin_addr.s_addr =htonl(INADDR_ANY);
  41.  servaddr.sin_port        =htons(80);
  42.  bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
  43.  listen(listenfd,5);
  44.  maxfd=listenfd;
  45.  maxi=-1;
  46.  for(i=0;i<MAXCLIENT;i++)
  47.   client[i]=-1;  
  48.  FD_ZERO(&allset);
  49.  FD_SET(listenfd, &allset); 
  50.  for(;;){
  51.   rset=allset;
  52.   nready=select(maxfd+1, &rset, NULL, NULL, NULL);
  53.   if(FD_ISSET(listenfd, &rset)){  
  54.    connfd=accept(listenfd,(struct sockaddr *)NULL,NULL);
  55.    for(i=0;i<FD_SETSIZE;i++)
  56.     if(client[i]<0){
  57.      client[i]=connfd; 
  58.      break;
  59.     }
  60.    if(i==MAXCLIENT)  
  61.     log_sys("connection overflow");
  62.    FD_SET(connfd, &allset); 
  63.    if(connfd>maxfd)
  64.     maxfd=connfd;  
  65.    if(i>maxi)
  66.     maxi=i;   
  67.    if(--nready<=0)
  68.     continue;  
  69.   }
  70.   for(i=0;i<=maxi;i++){ 
  71.    if((hfd=client[i])<0)
  72.     continue;
  73.    if(FD_ISSET(hfd, &rset)){
  74.     if((recvlen=recv(hfd,recvbuf,sizeof(recvbuf),0))==0){
  75.      close(hfd);
  76.      FD_CLR(hfd, &allset);
  77.      client[i]=-1;
  78.     }else
  79.      if(strncmp(recvbuf,"GET",3)==0){ 
  80.       p=strchr(recvbuf+3,'/'); 
  81.       if(p!=0){
  82.        pp=strstr(recvbuf+3,"HTTP/1."); 
  83.        if(pp!=0){
  84.         p++;
  85.         pp--;
  86.         *pp='/0'; 
  87.         getpng
  88. ("/tmp/pass.png",p,strlen(p)); 
  89.         sendFile
  90. (hfd,"/tmp/pass.png"); 
  91.         close(hfd);
  92.         FD_CLR(hfd, &allset);
  93.         client[i]=-1;
  94.        }
  95.       }
  96.      }
  97.     if(--nready<=0)
  98.      break;  
  99.    }
  100.   }
  101.  }
  102. }
  103. int
  104. getpng(char *filename,char *string,int strlen)
  105. {
  106.  int back,word,front,len,sx,sy,i;
  107.  char *str;
  108.  gdImagePtr newimg;
  109.  FILE *pngfp;
  110.  str=string;
  111.  len=strlen;
  112.  sx=10+len*9;
  113.  sy=20;
  114.  newimg=gdImageCreate(sx,sy); 
  115.  pngfp=fopen(filename,"wb");
  116.  back=gdImageColorAllocate(newimg,0,255,128); 
  117.  word=gdImageColorAllocate(newimg,255,0,128); 
  118.  front=gdImageColorAllocate(newimg,255,64,128); 
  119.  gdImageFill(newimg,0,0,back);   
  120.  gdImageString(newimg,gdFontGiant,5,1,str,word); 
  121.  for(i=0;i<len;(i=i+2))    
  122.   gdImageLine(newimg,(5+i*9),0,(23+i*9),20,front);
  123.  gdImagePng(newimg,pngfp);   
  124.  gdImageDestroy(newimg);    
  125.  fclose(pngfp);
  126.  return;
  127. }
  128. void
  129. sendFile(int sock, char *filename)
  130. {
  131.  char pngbuf[65535],clenth[32],*sendDate;
  132.  char sendbuf[8192]="HTTP/1.0 200 OK/nServer: mypngserver (FreeBSD)/nMime-Version:
  133. 1.0/nDate: ";
  134.  int n;
  135.  time_t tp;
  136.  FILE *fp;
  137.  fp=fopen(filename,"r");
  138.  n=fread(&pngbuf,sizeof(char),65535,fp); 
  139.  tp=time(NULL);
  140.  sendDate=ctime(&tp);  
  141.  strcat(sendbuf,sendDate);
  142.  strcat(sendbuf,"Content-Type: image/png/nContent-Length: ");
  143.  sprintf(clenth,"%d/n",n); 
  144.  strcat(sendbuf,clenth);
  145.  strcat(sendbuf,"Connection: close/n/n");
  146.  send(sock,sendbuf,strlen(sendbuf),0); 
  147.  write(sock,pngbuf,n);   
  148.  fclose(fp);
  149. }
  150. int
  151. daemon_init(const char *pname)
  152. {
  153.  int i;
  154.  pid_t pid;
  155.  if((pid=fork())!=0)
  156.   exit(0);
  157.  setsid();  
  158.  signal(SIGHUP,SIG_IGN); 
  159.  if((pid=fork())!=0)
  160.   exit(0);
  161.  chdir("/");  
  162.  umask(0);  
  163.  for(i=0;i<64;i++) 
  164.   close(i);
  165.  openlog(pname,LOG_PID,0);
  166. }
  167. void
  168. log_sys(const char *fmt, ...)
  169. {
  170.  va_list ap;
  171.  va_start(ap,fmt);
  172.  log_doit(1,LOG_ERR,fmt,ap);
  173.  va_end(ap);
  174.  exit(2);
  175. }
  176. static void
  177. log_doit(int errnoflag, int priority, const char *fmt, va_list ap)
  178. {
  179.  int errno_save;
  180.  char buf[BUFFSIZE];
  181.  errno_save=errno;
  182.  vsprintf(buf,fmt,ap);
  183.  if(errnoflag)
  184.   sprintf(buf+strlen(buf),":%s",strerror(errno_save));
  185.  strcat(buf,"/n");
  186.  syslog(priority,buf);
  187.  return;
  188. }

转自http://blog.csdn.net/hustxxb/archive/2005/01/08/244618.aspx