简单HTTP服务器(select模型)
2015-05-19 15:41
267 查看
server.c
index.html
加入了一个POST请求,并将请求数据用alert显示出来。带了文件下载功能,附带了CGI的处理,就将输入的数传给服务器,服务器执行一段shell脚本,然后将数据打包回馈给浏览器,在代码中,我使用了中间文件存储处理生成的结果,后来我发现可以利用更好的方法利用 popen函数来处理,自己改动吧!
CGI执行的代码:
<pre name="code" class="cpp">#include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <assert.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/stat.h> #include <sys/select.h> #include <signal.h> #define SERVER_NAME "IAMCAP-SERVER" #define PROTOCOL "HTTP/1.1" #define REQUESTLEN 4096 #define RESPONSELEN 1024000 #define LISTENNUM 5 #define TIMELEN 55 #define TEMPLEN 100 #define BUFFERLEN 1024 #define HOMEPATH "/Users/iamcap/http/showhttp/" static char* add_header(int , char *, char *, off_t , char *, int ); void parsedata(char*,int); int main(int argc, char **argv){ if(argc <=2){ printf("usage: %s ip_address port_number\n", (argv[0])); return 1; } const char *ip = argv[1]; int port = atoi(argv[2]); //initialize the struct struct sockaddr_in address; bzero(&address, sizeof(address)); address.sin_family = AF_INET; inet_pton(AF_INET, ip, &address.sin_addr); address.sin_port = htons(port); //reuse the port int sock = socket(PF_INET, SOCK_STREAM, 0); assert( sock >= 0); int opt = 1; setsockopt(sock, SOL_SOCKET,SO_REUSEADDR, &opt, sizeof(opt)); int ret = bind(sock, (struct sockaddr*)&address, sizeof(address)); assert(ret != -1); printf("listening ...\n"); ret = listen(sock, LISTENNUM); assert(ret != -1); fd_set fp_socketselect; FD_ZERO(&fp_socketselect); FD_SET(sock,&fp_socketselect); int max_fp = sock; struct sockaddr_in client; socklen_t client_addrlength = sizeof(client); int temp; int fdarr[65535]; fdarr[0] = sock; printf("------>>%d\n",fdarr[0]); int boundcount = 1; signal(SIGCHLD,SIG_IGN); while(1){ printf("i am coming to accept\n"); temp = accept(sock,(struct sockaddr*)&client,&client_addrlength); printf("connect = %d",temp); max_fp = max_fp > temp ? max_fp : temp; fdarr[boundcount++]=temp; FD_SET(temp, &fp_socketselect); int num = select(max_fp+1,&fp_socketselect,NULL,NULL,NULL); //return the number which suit to the rules printf("num = %d\n",num); printf("boundcount = %d",boundcount); if(num > 0){ int i = 0; printf("polling..\n"); while(i++ < boundcount ) { FD_SET(fdarr[i],&fp_socketselect); if(FD_ISSET(fdarr[i],&fp_socketselect)){ if(fdarr[i] == sock){ temp = accept(sock,(struct sockaddr*)&client,&client_addrlength); max_fp = max_fp > temp ? max_fp : temp; fdarr[boundcount++]=temp; FD_SET(temp, &fp_socketselect); printf("\nconnected with ip: %s and port: %d\n", inet_ntoa(client.sin_addr),ntohs(client.sin_port)); }else if(fdarr[i]>3){ char recvdata[REQUESTLEN]; memset(recvdata,'\0',REQUESTLEN); int ret = recv(fdarr[i],recvdata,REQUESTLEN-1,0); printf("\n%s\n", recvdata); pid_t pid = fork(); if(-1 == pid){ printf("fork() is wrong!!!\n"); }else if(0 == pid){ parsedata(recvdata,fdarr[i]); break; }else{ close(fdarr[i]); } } } } }else if(0==num){ printf("time out \n"); }else{ printf("something wrong\n"); } } close(sock); return 0; } // send header to the browser static char* add_header(int status, char *title, char *mime_type, off_t length, char *buffer , int buffersize) { char temp[TEMPLEN]; memset(buffer, 0, sizeof(buffersize)); sprintf(temp, "%s %d %s\r\n", PROTOCOL, status, title); strcat(buffer, temp); sprintf(temp, "Server: %s\r\n", SERVER_NAME); strcat(buffer, temp); sprintf(temp, "Connection: Keep-Alive\r\n"); strcat(buffer, temp); sprintf(temp, "Content-Type: %s\r\n", mime_type); strcat(buffer, temp); sprintf(temp, "Content-Length: %d\r\n", (int)length); strcat(buffer, temp); sprintf(temp, "Content-Language: zh-CN\r\n"); strcat(buffer, temp); strcat(buffer, "\r\n"); return buffer; } static char* get_mime_type(char *filename) { char *postfix; postfix = strrchr(filename, '.'); if (!strcasecmp(postfix, ".html") || !strcasecmp(postfix, ".htm")){ return "text/html; charset=UTF-8"; }else if (!strcasecmp(postfix, ".jpg") || !strcasecmp(postfix, ".jpeg")){ return "image/jpeg"; }else{ return "text/plain; charset=UTF-8"; } } void parsedata(char *recvdata, int connectfd){ if(chdir(HOMEPATH)<0){ // printf("chdir error\n"); exit(0); } char method[BUFFERLEN]; char path[BUFFERLEN]; char protocol[BUFFERLEN]; memset(method,'\0',BUFFERLEN); memset(path,'\0',BUFFERLEN); memset(protocol,'\0',BUFFERLEN); sscanf(recvdata, "%[^ ] %[^ ] %[^ ]", method, path, protocol); //open file or dir struct stat property; stat(path,&property); if(S_ISDIR(property.st_mode)){ if(0 == strcmp(path,"/")){ if(0 == strcasecmp(method,"GET")) { FILE *fp; if(fp = fopen("index.html","r")){ char head[BUFFERLEN]; memset(head,'\0',BUFFERLEN); stat(path+1,&property); stat("index.html",&property); add_header(200, "OK", "text/html", property.st_size, head, BUFFERLEN); char temp[RESPONSELEN]; memset(temp,'\0',RESPONSELEN); strcpy(temp,head); fread(temp+strlen(head),1,property.st_size,fp); send(connectfd, temp, strlen(head)+property.st_size,0); close(connectfd); } }else if(0 == strcasecmp(method,"POST")){ char *postemp=strtok(recvdata, "\r\n\r\n"); char *pos = postemp; while (postemp) { postemp=strtok(NULL, "\r\n\r\n"); if(postemp){ pos = postemp; } } char mes[500]={"<html><script>alert(\""}; strcat(mes,pos); strcat(mes,"\");</script></html>"); char head[BUFFERLEN]; memset(head,'\0',BUFFERLEN); add_header(200, "OK", "text/html", strlen(mes), head, BUFFERLEN); char temp[RESPONSELEN]; memset(temp,'\0',RESPONSELEN); strcpy(temp,head); strcat(temp,mes); send(connectfd, temp, strlen(head)+strlen(mes),0); close(connectfd); } }else{ //other dir exit(0); } }else{ //if it is a file if(0 == strcasecmp(method,"GET")){ FILE *fp; if(fp = fopen(path+1,"rb")){ char head[BUFFERLEN]; memset(head,'\0',BUFFERLEN); stat(path+1,&property); add_header(200, "OK", get_mime_type((path + 1)), property.st_size, head, BUFFERLEN); char temp[RESPONSELEN]; memset(temp,'\0',RESPONSELEN); strcpy(temp,head); fread(temp+strlen(head),1,property.st_size,fp); send(connectfd, temp, strlen(head)+property.st_size,0); close(connectfd); } }else if(0 == strcasecmp(method,"POST")){ }else if(0 == strcasecmp(method,"HEAD")){ }else if(0 == strcasecmp(method,"PUT")){ }else{ exit(0); } } }
index.html
<html> <script type="text/javascript"> <span style="white-space:pre"> </span>function mdo(){ <span style="white-space:pre"> </span>var flag = confirm("Do you want to download ?"); <span style="white-space:pre"> </span>if(flag == true){ <span style="white-space:pre"> </span>var x = document.getElementById('mydo').href = "1.zip"; <span style="white-space:pre"> </span>alert("you confirmed"); <span style="white-space:pre"> </span>}else{ <span style="white-space:pre"> </span>alert("you canceled"); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} </script> <span style="white-space:pre"> </span><body> <span style="white-space:pre"> </span><H1>this is a page</H1> <span style="white-space:pre"> </span><img src="mypic.jpg" /> <span style="white-space:pre"> </span><form method="post"> <span style="white-space:pre"> </span><input id="firstid" type="text" name="first" /> <span style="white-space:pre"> </span><input id="secondid" type="text" name="second"/> <span style="white-space:pre"> </span><input id="sumid" type="text" name="sum" readonly="true"> <span style="white-space:pre"> </span><input type="submit" value="compute" onclick="location.reload(true)"> <span style="white-space:pre"> </span></form> <span style="white-space:pre"> </span><a id="mydo" href="" onclick="mdo()" >click to download zip</a> <span style="white-space:pre"> </span></body> </html>
加入了一个POST请求,并将请求数据用alert显示出来。带了文件下载功能,附带了CGI的处理,就将输入的数传给服务器,服务器执行一段shell脚本,然后将数据打包回馈给浏览器,在代码中,我使用了中间文件存储处理生成的结果,后来我发现可以利用更好的方法利用 popen函数来处理,自己改动吧!
CGI执行的代码:
#!/bin/sh echo "<HTML><HEAD>" echo "<TITLE>bigger or not</TITLE>" echo "</HEAD><BODY>" if [ $1 -gt 0 ] then echo "<script>alert(\"$1 > 0\");</script>" else echo "<script>alert(\"$1 <= 0\");</script>" fi echo "</BODY></HTML>"
相关文章推荐
- 基于的epoll模型的简单http服务器
- C++ Windows 上简单的非阻塞Select模型
- IO模型的简单记录select、poll、epoll
- Select 模型的使用 简单聊天室的实现
- 网络编程:select模型的简单实例
- 最简单的WSAEventSelect模型(注意注释的地方)
- Select模型的简单实现
- libevent for qt网络模块,直接替换qt的select模型,支持epoll,select,pool.使用非常简单,无需修改以前的代码结构
- 简单光照模型(Lambert 光照模型)
- 设计一条简单的等待工作队列之软件模型设计与实现(一)
- 使用正向最大匹配算法实现中文分词简单模型-用trie树实现
- vue--简单的select组件
- 《Windows网络与通信程序设计》读书笔记----WSAEventSelect模型
- select/poll使用简单分析
- 实用计算机视觉 -- 简单摄像机针孔模型
- hello_world-2.3之简单设备驱动模型(三)---添加设备属性文件
- Simple Model 和 Rich Model(简单模型和领域模型)
- C#插件开发简单模型
- 简单了解Backbone.js的Model模型以及View视图的源码
- Linux网络编程--TCP网络编程基础(简单的server/client模型)