基于多线程的http服务器

该代码实现了一个简单的基于C++的HTTP服务器,使用socket进行网络通信,监听80端口。当接收到客户端请求时,通过多线程处理请求,根据文件扩展名返回相应的内容类型。支持GET方法,若请求无效或文件不存在,会发送错误响应。
摘要由CSDN通过智能技术生成

#include<iostream>

#include<stdio.h>

#include<unistd.h>

#include<string.h>

#include<stdlib.h>

#include<arpa/inet.h>

#include<sys/socket.h>

#include<pthread.h>

using namespace std;

#define BUF_SIZE 1024

#define SMALL_BUF 100

void* request_handler(void *arg);

void send_data(FILE*fp,char*ct,char* file_name);

char* content_type(char*file);

void send_error(FILE*fp);

void error_handling(char *message);

int main(int argc,char *argv[]){

    int serv_sock,clnt_sock;

    struct sockaddr_in serv_adr,clnt_adr;

    int clnt_adr_size;

    char buf[BUF_SIZE];

    pthread_t t_id;

   if(argc!=2){

    cout<<"Usage : "<<argv[0]<<"<port>"<<endl;

    exit(1);

   }

   serv_sock=socket(PF_INET,SOCK_STREAM,0);

   memset(&serv_adr,0,sizeof(serv_adr));

   serv_adr.sin_family=AF_INET;

   serv_adr.sin_addr.s_addr=inet_addr("192.168.157.129");

   serv_adr.sin_port=htons(atoi("80"));

   cout<<serv_sock<<endl;

   if(bind(serv_sock,(struct sockaddr*)&serv_adr,sizeof(serv_adr))==-1){

    //error_handling("bind() error");

    perror("setsockopet error\n");

   }

   if(listen(serv_sock,20)==-1){

    error_handling("listen() error");

   }

   while(true){

    clnt_adr_size=sizeof(clnt_adr);

    clnt_sock=accept(serv_sock,(struct sockaddr*)&clnt_adr,(socklen_t*)&clnt_adr_size);

    cout<<"Connection Request :"<<inet_ntoa(clnt_adr.sin_addr)<<ntohs(clnt_adr.sin_port);

    pthread_create(&t_id,NULL,request_handler,&clnt_sock);

    pthread_detach(t_id);

    }

    close(serv_sock);

    return 0;

}

void *request_handler(void*arg){

    int clnt_sock=*((int *)arg);

    char req_line[SMALL_BUF];

    FILE*clnt_read;

    FILE*clnt_write;

    char method[10];

    char ct[15];

    char file_name[30];

    clnt_read=fdopen(clnt_sock,"r");

    clnt_write=fdopen(clnt_sock,"w");

    if(strstr(req_line,"HTTP/")==NULL){

        send_error(clnt_write);

        fclose(clnt_read);

        fclose(clnt_write);

        goto end;

    }

    strcpy(method,strtok(req_line," /"));

    strcpy(file_name,strtok(NULL," /"));

    strcpy(ct,content_type(file_name));

    if(strcmp(method,"GET")!=0){

        send_error(clnt_write);

        fclose(clnt_read);

        fclose(clnt_write);

        goto end;

    }

    fclose(clnt_read);

    send_data(clnt_write,ct,file_name);

    end:

    int a;

}

void send_data(FILE* fp,char* ct,char* file_name){

    char protocol[]="HTTP/1.0 200 OK\r\n";

    char server[]="Server:Linux Web Server \r\n";

    char cnt_len[]="Content-length:2048\r\n";

    char cnt_type[SMALL_BUF];

    char buf[BUF_SIZE];

    FILE*  send_file;

    sprintf(cnt_type,"Content-type:%s\r\n\r\n",ct);

    send_file=fopen(file_name,"r");

    if(send_file==NULL){

        send_error(fp);

        return;

    }

    fputs(protocol,fp);

    fputs(server,fp);

    fputs(cnt_len,fp);

    fputs(cnt_type,fp);

    while(fgets(buf,BUF_SIZE,send_file)!=NULL){

        fputs(buf,fp);

        fflush(fp);

    }

   

    fflush(fp);

    fclose(fp);

}

char* content_type(char* file){

    char extension[SMALL_BUF];

    char file_name[SMALL_BUF];

    strcpy(file_name,file);

    strtok(file_name,".");

    strcpy(extension,strtok(NULL,"."));

    if(!strcmp(extension,"html")||!strcmp(extension,"htm")){

        return "text/html";

    }

    else{

        return "text/plain";

    }

}

void send_error(FILE *fp){

    char protocol[]="HTTP/1.0 400 Bad Request\r\n";

    char server[]="Server:Linux Web Server \r\n";

    char cnt_len[]="Content-length:2048\r\n";

    char cnt_type[]="Content-type:text/html\r\n\r\n";

    char content[]="<html><head><title>NETWORK</title></head>""<body><font size=+5><br>""</font></body></html>";

    fputs(protocol,fp);

    fputs(server,fp);

    fputs(cnt_len,fp);

    fputs(cnt_type,fp);

    fflush(fp);

}

void error_handling(char*message){

    fputs(message,stderr);;

    fputc('\n',stderr);

    exit(1);

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值