基于多线程的http服务器

#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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个简单的基于 Linux C 多线程的 HTTP 服务器示例,使用了 POSIX 线程库和 socket 编程接口: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <sys/socket.h> #include <netinet/in.h> #define PORT 8080 #define MAX_CONNECTIONS 10 #define BUFFER_SIZE 1024 void *handle_connection(void *arg) { int conn_fd = *(int*)arg; char buffer[BUFFER_SIZE]; ssize_t n; memset(buffer, 0, sizeof(buffer)); n = read(conn_fd, buffer, sizeof(buffer)-1); if (n <= 0) { close(conn_fd); pthread_exit(NULL); } char *response = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\nHello, world!"; write(conn_fd, response, strlen(response)); close(conn_fd); pthread_exit(NULL); } int main() { int sock_fd, conn_fd; struct sockaddr_in serv_addr, client_addr; socklen_t client_len; pthread_t threads[MAX_CONNECTIONS]; // create socket sock_fd = socket(AF_INET, SOCK_STREAM, 0); if (sock_fd < 0) { perror("Failed to create socket"); exit(EXIT_FAILURE); } // set server address memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(PORT); // bind socket to server address if (bind(sock_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) { perror("Failed to bind socket"); exit(EXIT_FAILURE); } // listen for connections if (listen(sock_fd, MAX_CONNECTIONS) < 0) { perror("Failed to listen for connections"); exit(EXIT_FAILURE); } printf("HTTP server is listening on port %d\n", PORT); // handle connections in separate threads while (1) { client_len = sizeof(client_addr); conn_fd = accept(sock_fd, (struct sockaddr*)&client_addr, &client_len); if (conn_fd < 0) { perror("Failed to accept connection"); continue; } pthread_t thread; if (pthread_create(&thread, NULL, handle_connection, &conn_fd) < 0) { perror("Failed to create thread"); close(conn_fd); continue; } pthread_detach(thread); } return 0; } ``` 上述代码创建了一个监听在 8080 端口的 HTTP 服务器,可以处理多个连接。在每个连接到来时,都会创建一个新的线程来处理请求。在处理请求的线程中,首先读取请求消息,然后发送一个简单的响应消息。 需要注意的是,在多线程环境下,需要使用线程安全的函数和数据结构,以避免竞争条件和死锁。例如,在本例中,每个线程都需要使用不同的连接套接字(conn_fd),因此需要将套接字的值作为线程参数传递,而不是直接使用全局变量。同时,需要注意在每个线程中关闭连接套接字,以避免资源泄漏。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值