Web server
1. Task details
Based on Huawei Kunpeng ECS CentOS (or Ubuntu), the following is implemented using Linux Socket:
- Client server of Web server, submit screenshot of program running
- The request and response shall comply with the HTTP protocol specification
- The server is deployed to the Huawei cloud server, and the browser uses the native
- Deploy the server to the test box. (extra points)
2. Experimental process
The code part directly uses the code provided by the teacher, changes some address locations and parameters, and runs successfully
copy.c
#include <stdio.h> static char copybuf[16384]; extern int TIMEOUT; int copy(FILE *read_f, FILE *write_f) { int n; int wrote; alarm(TIMEOUT); while (n = fread(copybuf,1,sizeof(copybuf),read_f)) { alarm(TIMEOUT); wrote = fwrite(copybuf,n,1,write_f); alarm(TIMEOUT); if (wrote < 1) return -1; } alarm(0); return 0; }
httpd.c
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <errno.h> #include <sys/stat.h> #include <dirent.h> #include <signal.h> #include <unistd.h> #include <ctype.h> #include "pthread.h" #define DEBUG int KEY_QUIT=0; int TIMEOUT=30; #ifndef O_BINARY #define O_BINARY 0 #endif char referrer[128]; int content_length; #define SERVER_PORT 80 int PrintHeader(FILE *f, int content_type) { alarm(TIMEOUT); fprintf(f,"HTTP/1.0 200 OK\n"); switch (content_type) { case 't': fprintf(f,"Content-type: text/plain\n"); break; case 'g': fprintf(f,"Content-type: image/gif\n"); break; case 'j': fprintf(f,"Content-type: image/jpeg\n"); break; case 'h': fprintf(f,"Content-type: text/html\n"); break; } fprintf(f,"Server: uClinux-httpd 0.2.2\n"); fprintf(f,"Expires: 0\n"); fprintf(f,"\n"); alarm(0); return(0); } int DoJpeg(FILE *f, char *name) { char *buf; FILE * infile; int count; if (!(infile = fopen(name, "r"))) { alarm(TIMEOUT); fprintf(stderr, "Unable to open JPEG file %s, %d\n", name, errno); fflush(f); alarm(0); return -1; } PrintHeader(f,'j'); copy(infile,f); /* prints the page */ alarm(TIMEOUT); fclose(infile); alarm(0); return 0; } int DoGif(FILE *f, char *name) { char *buf; FILE * infile; int count; if (!(infile = fopen(name, "r"))) { alarm(TIMEOUT); fprintf(stderr, "Unable to open GIF file %s, %d\n", name, errno); fflush(f); alarm(0); return -1; } PrintHeader(f,'g'); copy(infile,f); /* prints the page */ alarm(TIMEOUT); fclose(infile); alarm(0); return 0; } int DoDir(FILE *f, char *name) { char *buf; DIR * dir; struct dirent * dirent; if ((dir = opendir(name))== 0) { fprintf(stderr, "Unable to open directory %s, %d\n", name, errno); fflush(f); return -1; } PrintHeader(f,'h'); alarm(TIMEOUT); fprintf(f, "<H1>Index of %s</H1>\n\n",name); alarm(0); if (name[strlen(name)-1] != '/') { strcat(name, "/"); } while(dirent = readdir(dir)) { alarm(TIMEOUT); fprintf(f, "<p><a href=\"/%s%s\">%s</a></p>\n", name, dirent->d_name, dirent->d_name); alarm(0); } closedir(dir); return 0; } int DoHTML(FILE *f, char *name) { char *buf; FILE *infile; int count; char * dir = 0; if (!(infile = fopen(name,"r"))) { alarm(TIMEOUT); fprintf(stderr, "Unable to open HTML file %s, %d\n", name, errno); fflush(f); alarm(0); return -1; } PrintHeader(f,'h'); copy(infile,f); /* prints the page */ alarm(TIMEOUT); fclose(infile); alarm(0); return 0; } int DoText(FILE *f, char *name) { char *buf; FILE *infile; int count; if (!(infile = fopen(name,"r"))) { alarm(TIMEOUT); fprintf(stderr, "Unable to open text file %s, %d\n", name, errno); fflush(f); alarm(0); return -1; } PrintHeader(f,'t'); copy(infile,f); /* prints the page */ alarm(TIMEOUT); fclose(infile); alarm(0); return 0; } int ParseReq(FILE *f, char *r) { char *bp; struct stat stbuf; char * arg; char * c; int e; int raw; #ifdef DEBUG printf("req is '%s'\n", r); #endif while(*(++r) != ' '); /*skip non-white space*/ while(isspace(*r)) r++; while (*r == '/') r++; bp = r; while(*r && (*(r) != ' ') && (*(r) != '?')) r++; #ifdef DEBUG printf("bp='%s' %x, r='%s' \n", bp, *bp,r); #endif if (*r == '?') { char * e; *r = 0; arg = r+1; if (e = strchr(arg,' ')) { *e = '\0'; } } else { arg = 0; *r = 0; } c = bp; /*zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz*/ if (c[0] == 0x20){ c[0]='.'; c[1]='\0'; } /*zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz*/ if(c[0] == '\0') strcat(c,"."); if (c && !stat(c, &stbuf)) { if (S_ISDIR(stbuf.st_mode)) { char * end = c + strlen(c); strcat(c, "/index.html"); if (!stat(c, &stbuf)) { DoHTML(f, c); } else { *end = '\0'; DoDir(f,c); } } else if (!strcmp(r - 4, ".gif")) DoGif(f,c); else if (!strcmp(r - 4, ".jpg") || !strcmp(r - 5, ".jpeg")) DoJpeg(f,c); else if (!strcmp(r - 4, ".htm") || !strcmp(r - 5, ".html")) DoHTML(f,c); else DoText(f,c); } else{ PrintHeader(f,'h'); alarm(TIMEOUT); fprintf(f, "<html><head><title>404 File Not Found</title></head>\n"); fprintf(f, "<body>The requested URL was not found on this server</body></html>\n"); alarm(0); } return 0; } void sigalrm(int signo) { /* got an alarm, exit & recycle */ exit(0); } int HandleConnect(int fd) { FILE *f; char buf[160]; char buf1[160]; f = fdopen(fd,"a+"); if (!f) { fprintf(stderr, "httpd: Unable to open httpd input fd, error %d\n", errno); alarm(TIMEOUT); close(fd); alarm(0); return 0; } setbuf(f, 0); alarm(TIMEOUT); if (!fgets(buf, 150, f)) { fprintf(stderr, "httpd: Error reading connection, error %d\n", errno); fclose(f); alarm(0); return 0; } #ifdef DEBUG printf("buf = '%s'\n", buf); #endif alarm(0); referrer[0] = '\0'; content_length = -1; alarm(TIMEOUT); //read other line to parse Rrferrer and content_length infomation while (fgets(buf1, 150, f) && (strlen(buf1) > 2)) { alarm(TIMEOUT); #ifdef DEBUG printf("Got buf1 '%s'\n", buf1); #endif if (!strncasecmp(buf1, "Referer:", 8)) { char * c = buf1+8; while (isspace(*c)) c++; strcpy(referrer, c); } else if (!strncasecmp(buf1, "Referrer:", 9)) { char * c = buf1+9; while (isspace(*c)) c++; strcpy(referrer, c); } else if (!strncasecmp(buf1, "Content-length:", 15)) { content_length = atoi(buf1+15); } } alarm(0); if (ferror(f)) { fprintf(stderr, "http: Error continuing reading connection, error %d\n", errno); fclose(f); return 0; } ParseReq(f, buf); alarm(TIMEOUT); fflush(f); fclose(f); alarm(0); return 1; } void* key(void* data) { int c; for(;;){ c=getchar(); if(c == 'q' || c == 'Q'){ KEY_QUIT=1; exit(10); break; } } } int main(int argc, char *argv[]) { int fd, s; int len; volatile int true = 1; struct sockaddr_in ec; struct sockaddr_in server_sockaddr; pthread_t th_key; void * retval; signal(SIGCHLD, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGALRM, sigalrm); chroot("."); printf("starting httpd...\n"); printf("press q to quit.\n"); // chdir("/"); if (argc > 1 && !strcmp(argv[1], "-i")) { /* I'm running from inetd, handle the request on stdin */ fclose(stderr); HandleConnect(0); exit(0); } if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { perror("Unable to obtain network"); exit(1); } if((setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&true, sizeof(true))) == -1) { perror("setsockopt failed"); exit(1); } server_sockaddr.sin_family = AF_INET; server_sockaddr.sin_port = htons(SERVER_PORT); server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(s, (struct sockaddr *)&server_sockaddr, sizeof(server_sockaddr)) == -1) { perror("Unable to bind socket"); exit(1); } if(listen(s, 8*3) == -1) { /* Arbitrary, 8 files/page, 3 clients */ perror("Unable to listen"); exit(4); } pthread_create(&th_key, NULL, key, 0); /* Wait until producer and consumer finish. */ printf("wait for connection.\n"); while (1) { len = sizeof(ec); if((fd = accept(s, (void *)&ec, &len)) == -1) { exit(5); close(s); } HandleConnect(fd); } pthread_join(th_key, &retval); }
Makefile
TOPDIR = /home/tzy/web/ws/07_httpd/ include $(TOPDIR)Rules.mak EXTRA_LIBS += -lpthread EXEC = $(INSTALL_DIR) ./httpd OBJS = httpd.o copy.o HTTPD_DOCUMENT_ROOT = /home/tzy/web/ws/07_httpd/ CFLAGS += -DHTTPD_DOCUMENT_ROOT=\"$(HTTPD_DOCUMENT_ROOT)\" all: $(EXEC) $(EXEC): $(OBJS) $(CC) $(LDFLAGS) -o $@ $(OBJS) $(EXTRA_LIBS) install: $(EXP_INSTALL) $(EXEC) $(INSTALL_DIR) clean: -rm -f $(EXEC) *.elf *.gdb *.o
Rules.mak
TOPDIR= .. CROSS = arm-linux- CC= ${CROSS}gcc #CC=gcc #CFLAGS += -g #LDFLAGS += -static EXTRA_LIBS += EXP_INSTALL = install -m 755 INSTALL_DIR = /home/tzy/web/ws/07_httpd/
-
Use the make command to export the executable httpd, and the problems encountered will be summarized at the end
-
However, it was found that the software could not be executed. After query, it was found that it was compiled using 32bit Ubuntu
-
Readjusted and changed the executable name
-
Finally, the tools tool is updated. sudo dhclient is used for networking. ipconfig queries the address and finds that the address is http://192.168.23.128/ , the results are as follows
Code link: https://gitee.com/tang_zi_yue1927/code/tree/master/web/web/ws/07_httpd -
Huawei cloud is in arrears and cannot be realized for the time being
3. Problem summary
- Firstly, it is found that the CROSS part of Rules.mak cannot be recognized by armv4l unknown Linux -, and another CROSS compiler arm linux GCC is downloaded through online query
- Use sudo tar -xjvf / home / tzy / arm linux-gcc-4.6.4-arm-x86_ 64.tar.bz2 - C / decompress the compressed package downloaded on the Internet
- After decompression, create a new directory arm in (/ usr/local), that is, enter the following command in Terminal: sudo mkdir /usr/local/arm (the file exists because it has been implemented)
- After creating the arm directory successfully, you also need to liberate all permissions for it, that is, enter the following command in Terminal: sudo chmod 777 /usr/local/arm
- Find the extracted directory and copy the entire gcc-4.6.4 directory to the newly built arm directory. First switch cd to the directory where gcc-4.6.4 is located (after switching, first ls check whether there is gcc-4.6.4 directory):
cd /opt/TuxamitoSoftToolchains/arm-arm1176jzfssf-linux-gnueabi/ - Then execute the cp copy command, - r indicates the entire directory and everything in it. sudo cp -r gcc-4.6.4 /usr/local/arm
- Open (/ etc/profile) to configure environment variables and library variables. The purpose is to use the cross compiler anywhere in the future. The command is as follows: sudo vim /etc/profile
- After opening with vim, add two lines at the end of the file and enter the following code: the first line is to add the environment variable of the executing program, and the second line is the path of the library file:
- Use sudo tar -xjvf / home / tzy / arm linux-gcc-4.6.4-arm-x86_ 64.tar.bz2 - C / decompress the compressed package downloaded on the Internet
1 export PATH=$PATH:/usr/local/arm/gcc-4.6.4/bin 2 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/arm/gcc-4.6.4/lib
-Use the source command to reload the configuration file source /etc/profile
-Verify whether the installation is successful, enter the following command in Terminal and output version information: arm linux GCC - V
The result is shown in the figure: version 4.6.4 just installed is obtained
-Add the same two sentences as "/ etc/profile" under the ". bashrc" hidden file in the "/ home / user name" directory
export PATH=$PATH:/usr/local/arm/gcc-4.6.4/bin export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/arm/gcc-4.6.4/lib
Use ls -a to view hidden files
Reference website: https://www.cnblogs.com/tansuoxinweilai/p/11602830.html