This program is a Web Server that provides special services. The program is a daemon program that receives the HTTP GET request with a single process I / O multiplex (select). The request is a string (which can be a number or letter), returns a picture of a PNG format, the whole process Comply with the HTTP 1.0 protocol. This program is similar to a program that generates "verification code" on the website. This program is developed in the FreeBSD environment and can be compiled under FreeBSD and Windows (Cygwin). The FreeBSD environment is installed with GD-1.8.4 libraries, and the Cygwin environment is equipped with libPng-1.2.8 and GD-2.0.33 libraries for generating a PNG image. The entire program is completed in C language, the source code is as follows: / ******************************************** ************************************ * CopyRight (C) 2004-2005 Xiongbin Xiong All Rights Reserved * References:.. Stevens, WR 1992. Advanced Programming in the UNIX Environment Addison-Wesley * Stevens, WR 1998. UNIX Network Programming Volum1.Prentice Hall PTR * / # include
#DEfine MaxClient 1024 / * Array Client's maximum, the maximum number of customers that can be processed by this server * / # Define buffsize 4096
INT daemon_init (const char *); / * daemon process initialization function * / int getpng (char *, char *, int); / * PNG image generating function * / void sendfile (int, char *); / * Send files Client * / void log_sys (const char *, ...); static void log_doit (int, int, const char *, va_list ap);
INTMAIN (int Argc, char ** argv) {INT I, MAXI, MAXFD, Listenfd, Connfd, HFD, NREADY, Client [MaxClient]; char * p, * pp, recvbuf [buffsize]; size_t recvlen; fd_set rset, allset Struct SockAddr_in servaddr; daemon_init (Argv [0]); / * Become a daemon process * / listenfd = socket (AF_INET, SOCK_STREAM, 0); Bzero (& ServadDr, Sizeof (ServadDR)); / * Initializer Exciprive address structure * / Servaddr.sin_Family = AF_INET; servaddr.sin_addr.s_addr = htonl (inaddr_any); servaddr.sin_port = HTONS (80);
Bind (Listenfd, Struct Sockaddr *) & Servaddr, SIZEOF (SERVADDR); Listen (Listenfd, 5);
Maxfd = listenfd; maxi = -1; for (i = 0; i For (;;) {Rset = allset; NREADY = SELECT (MAXFD 1, & RSET, NULL, NULL, NULL); IF (FD_Isset (Listenfd, & RSET)) {/ * New User Connection * / Connfd = Accept (Listenfd, (Struct SockAddr *) NULL, NULL); For (i = 0; i FD_SET (Connfd, & Allset); / * Add a new descriptor in allSet * / if (connfd> maxfd) maxfd = connfd; / * Value of the largest descriptor * / if (i> maxi) MAXI = i; / * client [] The maximum element mark * / if (- NREADY <= 0) Continue; / * has no readable descriptor * /} For (i = 0; i <= maxi; i ) {/ * check all clients for data * / if ((HFD = Client [i]) <0) Continue; if (fd_isset (hfd, & rset)) {IF ( (Recvlen = RECV (HFD, Recvbuf, SizeOf (Recvbuf), 0)) == 0) {/ * User Disconnect * / Close (HFD); FD_CLR (HFD, & Allset); Client [i] = - 1; } else IF (strncmp (recvbuf, "get", 3) == 0) {/ * judgment request Whether the type is get * / p = strchr (Recvbuf 3, '/'); / * Looking for a request The match of '/' 'match * / if (p! = 0) {pp = strstr (Recvbuf 3, "http / 1."); / * Looking for the "http / 1." Match * / if (pp! = 0) {p ; pp-; * pp = '/ 0'; / * Get users Input character or digital string * / getpng ("/TMP/pass.png" ,p ,strlen (P)); / * Build a png picture * / sendfile (HFD, "/ TMP / Pass.png"); / * Send PNG Pictures to User * / Close (HFD); FD_CLR (HFD, & Allset); Client [i] = - 1;}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} <= 0) BREAK; / * Unreadable descriptor * /}}}} / * --------------------------- -------------- * // * PNG Image Generate Function * / IntgetPng (Char * FileName, Char * String, Int Strlen) {Int Back, Word, Front, Len, SX, SY , i; char * str; gdimageptr newimg; file * pngfp; Str = string; len = Strlen; SX = 10 len * 9; SY = 20; newimg = gdimagecreate (sx, sy); / * Create a variable storage blank image, pixel SX * SY * / PNGFP = FOPEN (FileName, "wb"); back = gdImageColorAllocate (newimg, 0,255,128); / * background color matching * / word = gdImageColorAllocate (newimg, 255,0,128); / * matches the color of the character * / front = gdImageColorAllocate (newimg, 255,64,128 ); / * Match the color of the interference line * / gdimagefill (newimg, 0, 0, back); / * Fill the image to image color * / gdImageString (Newimg, GDFONTGIANT, 5, 1, STR, WORD); / * Generate characters Image * / for (i = 0; i Fclose (PNGFP); Return;} / * --------------------------------------- ----- * // * Send files to client * / voidsendfile (int sock, char * filename) {char pngbuf [65535], clenth [32], * senddate; char sendbuf [8192] = "http / 1.0 200 OK / NServer: MyPng Server (FreeBSD) / Nmime-Version: 1.0 / ndate: "; int N; time_t tp; file * fp; fp = fopen (filename," r "); n = fread (& PNGBUF, SIZEOF (CHAR), 65535, FP); / * Reads with binary structure PNG picture file * / tp = time (null); sendDate = ctime (& TP); / * Generate current time * / strcat (sendbuf, senddate); strcat (sendbuf, "content-type: image / png / ncontent-length: iMage "); Sprintf (CLENTH,"% D / N ", N); / * The current PNG picture size * / strcat (sendbuf, clenth); strcat (sendbuf," connection: close / n / n "); Send (Sock, Sendbuf, Strlen (Sendbuf), 0); / * Send Server Respond * / Write (Sock, PNGBUF, N); / * Send PNG Image * / Fclose (FP);} / * ---- ------------------------------------------------------------------- * // * daemon process initialization function * / intDaemon_init (const char * pname) {INT i; pid_t pid; IF ((pid = fork ())! = 0) exit (0); setsid (); / * process becomes the first process of sessions, no longer control terminal * / signal (SIGHUP, SIG_IGN); / * Ignore SIGHUP signals Again for Fork * / IF ((pid = fork ())! = 0) exit (0); Chdir ("/"); / * Change the work directory * / umask (0); / * Create a shield word * / For (i = 0; i <64; i ) / * Close all open file descriptors * / close (i); OpenLog (PNAME, LOG_PID, 0);} / * ---------- ----------------------------------------------- * / / * DAEMON process error handling two functions * / voidlog_sys (const char * fmt, ...) {va_list ap; VA_START (AP, FMT); log_doit (1, log_err, fmt, AP); VA_END (AP); EXIT (2);} Static voidlog_doit (int errnoflag, int priority, const char * fmt, va_list ap) {int errno_save; char buf [buffsize]; Errno_save = errno; vsprintf (buf, fmt, AP); if (errnoflag) Sprintf (BUF Strlen (BUF), ":% S", strcat (buf, "/ n"); syslog Priority, BUF); Return;} / * end all * /