最简单的http服务器,可以发html、jpg、gif文件给客户端,有日志记录、monitor功能:
#include "unp.h"
#include <semaphore.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <syslog.h>
#include <sys/syscall.h>
#define gettid() syscall(__NR_gettid)
static int servfd;
static int nsec; /* #seconds between each alarm */
static int maxnalarms; /* #alarms w/no client probe before quit */
static int nprobes; /* #alarms since last client probe */
static void sig_urg(int), sig_alrm(int);
int dealHttpApply(const char* receiveline,int *fd,int *contentType);
int myreadline(int fd, char *buf, int n);
void recordLog(char * record,int flag); //flag =0 :tou flag=1:zhongjian flag=2:wei
static void *reply(void* sockfd);
void *monitorOrder();
sem_t mutex;
sem_t CRNum;
char recordline[MAXLINE];
char hostname[65];
int CR=2;
double ACR=0;
double cpuUse;
char memUse[20];
char ip[20];
char port[20];
int main(int argc, char **argv)
{
//daemon_init(argv[0],0);
sem_init(&mutex,0,1);
sem_init(&CRNum,0,1);
int listenfd, connfd;
pthread_t childThreadPid;
socklen_t clilen;
struct sockaddr_in cliaddr, servaddr;
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
char temp[20];
int httpd=open("httpd.conf",O_RDONLY);
myreadline(httpd,temp,MAXLINE);
sscanf(temp,"%*s%s",ip);
myreadline(httpd,temp,MAXLINE);
sscanf(temp,"%*s%s",port);
inet_pton(AF_INET,ip,&servaddr.sin_addr);
servaddr.sin_port=htons(atoi(port));
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
Signal(SIGALRM, sig_alarm);
alarm(5);
signal(SIGPIPE,SIG_IGN);
for ( ; ; )
{
clilen = sizeof(cliaddr);
if ( (connfd = accept(listenfd, (SA *) &cliaddr, &clilen)) < 0)
{
if (errno == EINTR) continue;/* back to for() */
else err_sys("accept error");
}
int *fd=malloc(sizeof(int));
*fd=connfd;
//---------------------------printf---------------------------------
printf("connected from %s:%u...http\n\n",inet_ntoa(cliaddr.sin_addr),cliaddr.sin_port);
//---------------------------record---------------------------------
sprintf(recordline,"connected from %s:%u...\n",inet_ntoa(cliaddr.sin_addr),cliaddr.sin_port);
recordLog(recordline,0);
pthread_create(&childThreadPid,NULL,reply,(void*)fd);
}
sem_destroy(&mutex);
sem_destroy(&CRNum);
}
static void *reply(void* sockfd)
{
int *once=sockfd;
sem_wait(&CRNum);
CR++;
sem_post(&CRNum);
pthread_detach(pthread_self());
ssize_t n;
char sendline[MAXLINE];
char receiveline[MAXLINE];
char buf[MAXLINE];
int judge=0;
int replyNum;
int fd;
char name[65];
int contentTypeIndex=0;
gethostname(name, sizeof(name));
char contentType[20][100]= {"text/html","image/jpg","text/css","application/x-javascript","image/gif"};
while((n=myreadline(*once,receiveline,MAXLINE))>2)
{
if(!judge)
{
replyNum=dealHttpApply(receiveline,&fd,&contentTypeIndex);
judge=1;
}
//--------------------record------------------
recordLog(receiveline,flag++);
}
switch(replyNum)
{
case 501:
{
sprintf(sendline,"HTTP/1.1 501 Not Implemented\r\nServer: fantasy & nani's web server/0.01 %s\r\n\r\n",name);
Writen(*once,sendline,strlen(sendline));
break;
}
case 404:
{
sprintf(sendline,"HTTP/1.1 404 Not Found\r\nServer: fantasy & nani's web server/0.01 %s\r\n\r\n",name);
Writen(*once,sendline,strlen(sendline));
break;
}
case 200:
{
sprintf(sendline,"HTTP/1.1 200 OK\r\nServer: hp\r\nContent-Length: %lu\r\nContent-Type: %s\r\n\r\n",(unsigned long int)lseek(fd,0,SEEK_END),contentType[contentTypeIndex]);
// printf("%s\n",sendline);
writen(*once,sendline,strlen(sendline));
lseek(fd,0,SEEK_SET);
while((n=read(fd,buf,MAXLINE))>0)
{
write(*once,buf,n);
}
close(fd);
break;
}
//monitor
case 250:
{
char memInfo[100];
gethostname(hostname, sizeof(hostname));
int fd=open("/proc/self/statm",O_RDONLY,0444);
myreadline(fd,memInfo,100);
sscanf(memInfo,"%s",memUse);
close(fd);
sprintf(sendline,"OSName:%s\r\nCR:%d\r\nACR:%lf\r\ncpuUse:%lf\r\nmemUse:%s\r\n\r\n",hostname,CR,ACR,cpuUse,memUse);
writen(*once,sendline,strlen(sendline));
break;
}
default:
{
sprintf(sendline,"HTTP/1.1 500 Internal Server Error\r\nServer: fantasy & nani's web server/0.01 %s\r\n\r\n",name);
Writen(*once,sendline,strlen(sendline));
break;
}
}
sem_wait(&CRNum);
CR--;
sem_post(&CRNum);
close(*once);
free(once);
return NULL;
}
int dealHttpApply(const char* receiveline,int *fd,int *contentTypeIndex)
{
//GET /fileName HTTP/1.1\r\n
char fileName[50];
char suffix[20];
char temp[50];
char fileNameAndSuffix[70];
sscanf(receiveline,"%s",temp);
if(strcmp(temp,"GET")!=0)
{
if(!strcmp(temp,"monitor"))return 250;
else return 501;
}
sscanf(receiveline,"%*[^/]%*[/]%s",fileNameAndSuffix);
sscanf(fileNameAndSuffix,"%[^.]",temp);
sscanf(fileNameAndSuffix,"%*[^.]%*[.]%s",suffix);
strcpy(fileName,"./webapps/");
strcat(fileName,fileNameAndSuffix);
if(((*fd)=open(fileName,O_RDONLY))<0)
{
return 404;
}
else
{
if(strcmp(suffix,"html")==0) *contentTypeIndex=0;
else if(strcmp(suffix,"jpg")==0) *contentTypeIndex=1;
else if(strcmp(suffix,"css")==0) *contentTypeIndex=2;
else if(strcmp(suffix,"javascript")==0) *contentTypeIndex=3;
else if(strcmp(suffix,"gif")==0) *contentTypeIndex=4;
return 200;
}
}
void recordLog(char *record,int flag)
{
time_t t=time(NULL);
struct tm *nowTime;
nowTime=localtime(&t);
char logName[50];
sprintf(logName,"./log/httpd-%d-%d-%d.log",1900+nowTime->tm_year,nowTime->tm_mon+1,nowTime->tm_mday);
char time[50];
sprintf(time,"%d:%d:%d\n",nowTime->tm_hour,nowTime->tm_min,nowTime->tm_sec);
sem_wait(&mutex);
int dayLog=open(logName,O_WRONLY|O_CREAT|O_APPEND,0444);
if(!flag)write(dayLog,time,strlen(time));
write(dayLog,record,strlen(record));
if(flag==3)write(dayLog,"\r\n",2);
close(dayLog);
sem_post(&mutex);
return;
}
void heartbeat_serv(int servfd_arg, int nsec_arg, int maxnalarms_arg)
{
servfd = servfd_arg; /* set globals for signal handlers */
if ( (nsec = nsec_arg) < 1)
nsec = 1;
if ( (maxnalarms = maxnalarms_arg) < nsec)
maxnalarms = nsec;
Signal(SIGURG, sig_urg);
Fcntl(servfd, F_SETOWN, getpid());
Signal(SIGALRM, sig_alrm);
alarm(nsec);
}
static void sig_urg(int signo)
{
int n;
char c;
if ( (n = recv(servfd, &c, 1, MSG_OOB)) < 0)
{
if (errno != EWOULDBLOCK)
err_sys("recv error");
}
printf("living...\n");
Send(servfd, &c, 1, MSG_OOB); /* echo back out-of-band byte */
nprobes = 0; /* reset counter */
return; /* may interrupt server code */
}
static void sig_alrm(int signo)
{
if (++nprobes > maxnalarms)
{
printf("no probes from client\n");
exit(0);
}
static clock_t last_clock=0;
clock_t current_clock=clock(), t=5-alarm(0);
// printf("%ld,%lf\n", t, (current_clock-last_clock)*100.0/(t*CLOCKS_PER_SEC*4));
cpuUse=(current_clock-last_clock)*100.0/(t*CLOCKS_PER_SEC*4);
ACR=(CR*100.0/(t*CLOCKS_PER_SEC*4));
last_clock=current_clock;
alarm(nsec);
return; /* may interrupt server code */
}
void sig_alarm(int signum)
{
static clock_t last_clock=0;
clock_t current_clock=clock(), t=5-alarm(0);
// printf("%ld,%lf\n", t, (current_clock-last_clock)*100.0/(t*CLOCKS_PER_SEC*4));
cpuUse=(current_clock-last_clock)*100.0/(t*CLOCKS_PER_SEC*4);
ACR=(CR*100.0/(t*CLOCKS_PER_SEC*4));
last_clock=current_clock;
alarm(5);
}
int myreadline(int fd, char *buf, int n)
{
char ch;
char *base=buf;
while(1)
{
if(read(fd, &ch, 1)!=1)
{
if(errno==EINTR) continue;
return -1;
}
if((*(buf++)=ch)=='\n') break;
}
*buf='\0';
return buf-base;
}