#include
#include
#include
#pragma comment(lib,"ws2_32.lib")
#define HTTP_PORT 80
#define HTTP_BUF_SIZE 1024
#define NAME_SIZE 1024
#define PATH_SIZE 1024
struct doc_type
{
char *suffix;//文件后缀
char *type; //文件类型
};
struct doc_type file_type[]=
{
{"html","text/html"},
{"htm","text/html"},
{"txt","text/plain"},
{"jpg","image/jpeg"},
{"gif","image/gif"},
{"bmp","application/x-bmp"},
{"ico","application/x-ico"},
{"swf","application/x-shockwave-flash"},
{NULL,NULL},
};
//响应的首部内容
char *http_head_temp="HTTP/1.1 200 OK\r\nServer:Wayne's Server \r\n"
"Accept-Ranges:bytes\r\nContent-Length:%d\r\nConnection:close\r\n"
"Content-Type:%s\r\n\r\n";
//通过文件后缀查找对应的文件类型Content-Type
char *http_get_type_by_suffix(char *suffix)
{
struct doc_type *ty;
for(ty=file_type; (*ty).suffix; ty++)
if(strcmp((*ty).suffix,suffix)==0)
return (*ty).type;
return NULL;
}
//通过URL获取访问文件名和后缀
int http_analyse_url(char *buf,int buflen,char *file_path,char *file_name,char *suffix)
{
int length=0,i=0,j,k=0;
char *begin,*end,*bias,*p,*start;
for(j=0;j
if(buf[j]==' ') k++;
if(k<2) return -1;
begin=strchr(buf,' ');
begin++;
for(p=begin; *p=='/'; p++) begin=p;
start=begin; //start开始的位置不包括“/”
end=strchr(begin,' ');
for(p=begin; p!=end; p++)
if(*p=='/') begin=p;
begin++; //将指针定位到最后一个‘/’的后面一位
for(p=begin; p!=end; p++)
if(*p=='.') i=1; //判断最后后缀是否有“.”,有表示访问的是文件,无表示访问的是路径
if(i==0)
{
length=end-start; //获取访问路径长度
memcpy(file_path,start,length);
}
else
{
length=begin-start;
memcpy(file_path,start,length);
}
for(p=file_path; *p!=NULL; p++)
if(*p=='/') *p='\\'; //将路径中的'/'改为'\'
p--;
if(*p!='\\')
{
//在路径的最后添加'\'
p++;
*p='\\';
}
if(i==1)
{
length=end-begin; //获取文件名长度
memset(file_name,NULL,NAME_SIZE);
memcpy(file_name,begin,length);
for(p=begin; p!=end; p++)
if(*p=='.') begin=p; //定位到最后一个'.'
begin++;
length=end-begin; //获取扩展名长度
memset(suffix,NULL,NAME_SIZE);
memcpy(suffix,begin,length);
return 1; //定义了访问目标
}
return 0; //没有定义访问目标
}
void error(SOCKET soc)
{
int file_len=46,hdr_len;
char http_header[HTTP_BUF_SIZE],*Content_type="text/html";
char error[HTTP_BUF_SIZE]="
ERROR
"; //46memset(http_header,NULL,HTTP_BUF_SIZE);
hdr_len=sprintf(http_header,http_head_temp,file_len,Content_type); //格式化首部内容
send(soc,http_header,hdr_len,0);
send(soc,error,file_len,0);
printf("访问出错\n========================================================================\n");
}
int http_send_response(SOCKET soc,char *buf,int buf_len)
{
FILE *file=NULL;
char http_header[HTTP_BUF_SIZE],file_name[NAME_SIZE]="index.html",file_name2[NAME_SIZE]="index.htm",file_path[PATH_SIZE],file_path_temp[PATH_SIZE],suffix[NAME_SIZE]="html";
char HTTP_Send_Buff[HTTP_BUF_SIZE],*Content_type=NULL,read_buf[HTTP_BUF_SIZE],*p,*q,target_file[NAME_SIZE];
int file_len=0,hdr_len=0,send_len=0,read_len=0;
int results,i=0;
memset(file_path,NULL,PATH_SIZE);
if((results=http_analyse_url(buf,HTTP_BUF_SIZE,file_path,file_name,suffix))==-1)
{
error(soc);
return -1;
}
memset(target_file,NULL,NAME_SIZE);
for(p=file_path; *p!=NULL; p++)
{
if(*p=='\\')
{
p++;
memset(file_path_temp,NULL,PATH_SIZE);
for(q=p; *q=='\\'; q++);
memcpy(file_path_temp,q,strlen(q));
memcpy(p,file_path_temp,strlen(file_path_temp));
if(strlen(file_path_temp)==0)
{
*p=NULL;
break;
}
}
}
strcat(target_file,&file_path[1]);
strcat(target_file,file_name);
if(results==1)
{
if((file=fopen(target_file,"rb"))==NULL)
{
printf("访问\"%s\"失败,不存在此文件\n",target_file);
error(soc);
return -1;
}
}
//获取文件大小
else
{
if((file=fopen(target_file,"rb"))==NULL)
{
memset(target_file,NULL,NAME_SIZE);
strcat(target_file,&file_path[1]);
strcat(target_file,file_name2);
if((file=fopen(target_file,"rb"))==NULL)
{
printf("无首页文件\n");
error(soc);
return -1;
}
}
}
printf("访问文件:%s\n",target_file);
fseek(file,0,SEEK_END);
file_len=ftell(file);
fseek(file,0,SEEK_SET);
if((Content_type=http_get_type_by_suffix(suffix))==NULL)
{
puts("无此文件类型");
error(soc);
return -1;
}
hdr_len=sprintf(http_header,http_head_temp,file_len,Content_type); //格式化首部内容
if((send_len=send(soc,http_header,hdr_len,0))==SOCKET_ERROR)
{
return -1;
}
do
{
read_len=fread(read_buf,sizeof(char),HTTP_BUF_SIZE,file);
if(read_len>0)
{
send_len=send(soc,read_buf,read_len,0);
file_len-=read_len;
}
}
while((read_len>0)&&(file_len>0));
fclose(file);
printf("========================================================================\n");
return 1;
}
int main(int argc,char argv[]) { WSADATA wsa; SOCKET srv_soc,acpt_soc; struct sockaddr_in serv_addr; struct sockaddr_in from_addr; char recv_buf[HTTP_BUF_SIZE]; memset(recv_buf,NULL,sizeof(recv_buf)); int port=HTTP_PORT,from_len=sizeof(from_addr),recv_len; /*if(argc==2) { port=atoi(argv[1]); }*/ WSAStartup(MAKEWORD(2,0),&wsa); if((srv_soc=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET) exit(0); serv_addr.sin_family=AF_INET; serv_addr.sin_port=htons(port); serv_addr.sin_addr.s_addr=htonl(INADDR_ANY); if(bind(srv_soc,(struct sockaddr *)&serv_addr,sizeof(serv_addr))==SOCKET_ERROR) { puts("绑定地址失败"); system("pause"); exit(0); } if(listen(srv_soc,SOMAXCONN)!=0) { puts("套接口转被动模式失败"); system("pause"); exit(0); } printf("The Service Started...\n"); while(1) { if((acpt_soc=accept(srv_soc,(struct sockaddr *)&from_addr,&from_len))==INVALID_SOCKET) { puts("接受客户端连接服务启动失败"); closesocket(acpt_soc); continue; } printf("客户端%s接入\n",inet_ntoa(from_addr.sin_addr)); if(recv(acpt_soc,recv_buf,HTTP_BUF_SIZE,0)==SOCKET_ERROR) { puts("接收数据失败"); closesocket(acpt_soc); continue; } recv_buf[HTTP_BUF_SIZE-1]=NULL; http_send_response(acpt_soc,recv_buf,recv_len); closesocket(acpt_soc); } }