标签:web
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/sendfile.h>
#include<fcntl.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<assert.h>
#include<pthread.h>
#include<errno.h>
#define _DET_PAGE_ index.html
#define _SIZE_ 1024
static void printLog(const char* const str,const char* const fun,int line);
void usage(const char* const proc);
int startup(char* ip,int port);
int get_line(int sock,char* buf,int size);
void clear_head(int sock);
void echo_html(int sock,char* path,ssize_t size);
void accept_request(int sock);
void* handle_client(void* arg);
#include"http.h"
static void printLog(const char* const str,const char* const fun,int line)
{
printf("%s:%s:%d\n",str,fun,line);
}
void usage(const char* const proc)
{
assert(proc);
printLog(proc,__FUNCTION__,__LINE__);
}
int startup(char* ip,int port)
{
int sock=socket(AF_INET,SOCK_STREAM,0);
if(sock<0)
{
printLog(strerror(errno),__FUNCTION__,__LINE__);
exit(1);
}
int opt=1;
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
struct sockaddr_in local;
local.sin_family=AF_INET;
local.sin_port=htons(port);
local.sin_addr.s_addr=inet_addr(ip);
if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)
{
printLog(strerror(errno),__FUNCTION__,__LINE__);
exit(1);
}
if(listen(sock,5)<0)
{
printLog(strerror(errno),__FUNCTION__,__LINE__);
exit(1);
}
return sock;
}
int get_line(int sock,char* buf,int size)
{
assert(buf);
int i=0;
ssize_t _s=-1;
char ch=‘\0‘;
while(i<size-1)
{
_s=recv(sock,&ch,1,0);
if(_s>0)
{
if(ch==‘\r‘)
{
if(_s=recv(sock,&ch,1,MSG_PEEK))
{
if(_s>0&&ch==‘\n‘)
recv(sock,&ch,1,0);
}
}
buf[i++]=ch;
}
else
{
break;
}
}
buf[i]=‘\0‘;
return i;
}
void clear_head(int sock)
{
char buf[_SIZE_];
buf[0]=‘\0‘;
ssize_t _s=-1;
while(_s>0&&strcmp(buf,"\n")!=0)
{
get_line(sock,buf,sizeof(buf));
}
}
void echo_html(int sock,char* path,ssize_t size)
{
int fd=open(path,O_RDONLY);
if(fd<0)
{
printLog(strerror(errno),__FUNCTION__,__LINE__);
exit(1);
}
char* status_line="HTTP/1.1 200 ok/r/n/r/n";
send(sock,status_line,strlen(status_line));
if(sendfile(sock,fd,NULL,size)<0)
{
close(fd);
return;
}
close(fd);
}
void accept_request(int sock)
{
char buf[_SIZE_];
#ifdef _DEBUG1_
int ret=-1;
int i=0,j=0;
char method[_SIZE_/2];
char url[_SIZE_];
char path[_SIZE_];
memset(method,‘\0‘,sizeof(method));
memset(buf,‘\0‘,sizeof(buf));
memset(path,‘\0‘,sizeof(path));
memset(url,‘\0‘,sizeof(url));
//while(ret=get_line(sock,buf,sizeof(buf)>0))
//{
// if(ret==0)
// {
// printLog(strerror(errno),__FUNCTION__,__LINE__);
// break;
// }
// printf("%s",buf);
//}
if(get_line(sock,buf,sizeof(buf))==0)
{
printLog("errno",__FUNCTION__,__LINE__);
return;
}
i=j=0;
while(!isspace(buf[i])&&i<sizeof(buf)&&j<sizeof(method)-1)
{
method[j++]=buf[i++];//get method
}
method[j]=‘\0‘;
j=0;
while(isspace(buf[i]))
{
++i;
}
while(!isspace(buf[i])&&i<sizeof(buf)&&j<sizeof(url)-1)
{
url[j++]=buf[i++];
}
int cgi=0;
if(strncasecmp(method,"POST")!=0&&strncasecmp(method,"GET")!=0)
{
printLog("errno",__FUNCTION__,__LINE__);
return;
}
if(strncasecmp(method,"POST"))
{
cgi=1;
}
if(strncasecmp(method,"GET"))
{
char* query_string=url;
while(*query_string!=‘\0‘&&*query_string!=‘?‘)
{
if(*query_string==‘?‘)
{
*query_string=‘\0‘;
cgi=1;
}
++query_string;
}
sprintf(path,"ntdos%s",url);//sprintf
if(path[strlen(path)-1]==‘/‘)
{
strcat(path,_DET_PAGE_);
}
struct stat st;
if(stat(path,&st)<0)//not exist
{
printLog("errno",__FUNCTION__,__LINE__);
return;
}
else if(S_ISDIR(st.st_mode))//dir
{
strcpy(path,"htdocs/");
strcat(path,_DEF_PAGE_);
}
else if((st.st_mode&S_IXUSR)||(st.st_mode&S_IXGPR)||(st.st_mode&S_IXOTH))
{
cgi=1;
}
if(cgi)
{
execute_cgi(sock,path,method,query_string);
}
else
{
clear_head(sock);
echo_html(sock,path,st.st_size);
}
}
#endif
close(sock);
}
void* handle_client(void* arg)
{
int sock=(int)arg;
accept_request(sock);
return NULL;
}
//main.c
#include"http.h"
int main(int argc,char* argv[])
{
if(argc!=3)
{
usage(argv[0]);
return 1;
}
char* ip=argv[1];
int port=atoi(argv[2]);
int listen_sock=startup(ip,port);
struct sockaddr_in client;
socklen_t len=sizeof(client);
fflush(stdout);
while(1)
{
int new_sock=accept(listen_sock,(struct sockaddr*)&client,&len);
if(new_sock<0)
{
printf("no client");
fflush(stdout);
continue;
}
pthread_t id;
pthread_create(&id,NULL,handle_client,(void*)new_sock);
pthread_detach(id);//set detach return val:0/errno
}
return 0;
} 本文出自 “小止” 博客,请务必保留此出处http://10541556.blog.51cto.com/10531556/1785983
标签:web
原文地址:http://10541556.blog.51cto.com/10531556/1785983