使用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;
}
下面是運行程序後,從浏覽器作的一個簡單測試