使用c語言實現了一個簡單的web服務器。程序支持html,css,js,jpg,gif格式的請求 [cpp] #include<stdio.h> #include<fcntl.h> #include<netinet/in.h> #include<arpa/inet.h> #include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<string.h> #include<stdlib.h> #define PORT 12345 #define WebRoot /home/meng/webpage /** * * 字符串s1是否以s2結束 */ int endsWith(char s1[],char s2[]){ int len1 = strlen(s1); int len2 = strlen(s2); int i=len1-1,j=len2-1; if(len1<len2)return 0; for(;i>=0&&j>=0;i--,j--){ if(s1[i]!=s2[j])return 0; } return 1; } int main(){ int sockfd,fd,client; struct sockaddr_in addr; int len=sizeof(addr); char recbuf[2048]; //socket連接 if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0){ perror("socket.\n"); exit(1); } //設置IP端口 bzero(&addr,sizeof(addr)); addr.sin_family=AF_INET; addr.sin_port=htons(PORT); addr.sin_addr.s_addr=inet_addr("127.0.0.1"); //bind if(bind(sockfd,(struct sockaddr*)&addr,sizeof(addr))<0){ perror("bind.\n"); exit(1); } //listen 最大連接數 if(listen(sockfd,10)<0){ perror("listen.\n"); exit(1); } printf("listening...\n"); while(1){ //取得客戶端的標識 if((client=accept(sockfd,(struct sockaddr*)&addr,&len))<0){ perror("accept.\n"); exit(1); } //讀取請求的頭部 int buf=0; if((buf=read(client,recbuf,2048))>=0){ recbuf[buf]='\0'; } //printf("%s\n",recbuf); char *token=strtok(recbuf," "); //獲得HTTP請求第一行中間部分,也就是URI if(token!=NULL){ token=strtok(NULL," "); } char type[256]; /** * 根據請求資源結尾的擴展名不同, * 響應不同mine類型 */ if(endsWith(token,".jpg")){ strcpy(type,"image/jpeg\r\nAccept-Ranges:bytes"); }else if(endsWith(token,".gif")){ strcpy(type,"image/gif"); }else if(endsWith(token,".js")){ strcpy(type,"text/javascript"); }else if(endsWith(token,".css")){ strcpy(type,"text/css"); }else{ strcpy(type,"text/html"); } //讀取文件內容 char filePath[1024]; char content[2048*512]; int fileSize; strcpy(filePath,"/home/meng/webpage"); strcat(filePath,token); fd=open(filePath,O_RDONLY,0766); if(fd==-1){ strcpy(content,"Not Found"); }else{ fileSize=read(fd,content,sizeof(content)); //printf("%d\n",strlen(content)); content[fileSize]='\0'; if(fileSize<=0)strcpy(content,"Not Found"); close(fd); } if(fileSize<=0){ fileSize=strlen("Not Found"); } char sendBuf[2048*1024]; char tmp[20]; sprintf(tmp,"%d",fileSize); memset(sendBuf,'\0',sizeof(sendBuf)); //返回HTTP響應的頭部信息 //所有的返回狀態都是200,暫不做404等其它響應狀態的判斷工作 strcat(sendBuf,"HTTP/1.1 200 OK\r\n"); strcat(sendBuf,"Server:MENGXIANLU\r\n"); strcat(sendBuf,"Content-Length:"); strcat(sendBuf,tmp); strcat(sendBuf,"\r\n"); strcat(sendBuf,"Content-Type: "); strcat(sendBuf,type); strcat(sendBuf,"\r\n"); //下面極其重要,表示響應頭部的結束。 //頭部結束後就是正文部分了 strcat(sendBuf,"\r\n"); /** 響應頭部 END */ int i,j; /** 響應內容(正文) */ /** 不能使用 strcat進行字符串的連接了。*/ /**如果請求的是圖片,其字節碼中有可能包含'\0'如果使用strcat有可能造成信息的截斷*/ for(i=0,j=strlen(sendBuf);i<fileSize;i++,j++){ sendBuf[j]=content[i]; } /** 一切准備就緒 */ sendBuf[j]='\0'; /**結果返回給客戶端*/ write(client,sendBuf,j); close(client); } close(sockfd); return 0; } 下面是運行程序後,從浏覽器作的一個簡單測試