http服务器

最简单的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;
}


 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值