天天看點

epoll-httpserver測試

1. epoll-httpserver

為了深入了解java的reactor模型,用c語言實作一下。

程式結構:

主線程用來接受新的連接配接

新線程用來處理請求

epoll_http_test.c 源檔案

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/epoll.h>
#include<pthread.h>
#include<string.h>
struct epoll_event events[10];
int epollRet;
void* thread_run_wait(void* arg){
    while (1){
        int ws = epoll_wait(epollRet, events, 10, -1);
        printf("wait 傳回 %d\n", ws);
        if (ws < 0){ 
            perror("epoll_wait"); 
            continue;
        }
        for (int i = 0; i < ws; ++i) {
            // 
            if(events[i].events == EPOLLIN){
                char buf[1024] = {0};
                int resSize = recv(events[i].data.fd, buf, 1024, 0);
                printf("%s\n", buf);
                bzero(&buf, 1024);
                char* sendBuf = "HTTP/1.1 200 OK\nContent-Type: text/html;charset=utf-8\nContent-Length: 6\n\nhello\n";
                strcpy(buf, sendBuf);
                int r = send(events[i].data.fd, &buf, 1024, 0);
                
            }else if (events[i].events == EPOLLERR){
                printf("%s\n", "error close clifd");
                epoll_ctl(epollRet, EPOLL_CTL_MOD, events[i].data.fd, &events[i]);
                close(events[i].data.fd);
            }else{
                printf("%s\n", "error close clifd");
                epoll_ctl(epollRet, EPOLL_CTL_MOD, events[i].data.fd, &events[i]);
                close(events[i].data.fd);
            }
        }
    }
}

int main(){
    int socketserverfd = socket(AF_INET, SOCK_STREAM, 0);
    if (socketserverfd < 0){ 
        perror("socket"); 
        exit(-1);
    }
    struct sockaddr_in addr;
    addr.sin_port = htons(8080);
    addr.sin_family = AF_INET;
    int bindre = bind(socketserverfd, (struct sockaddr*)&addr, sizeof(addr));
    if (bindre < 0){
        perror("bind");
        exit(-1);
    }
    int res = listen(socketserverfd, 5);
    if (res < 0){ 
        perror("listen");
        exit(-1);
    }
    struct sockaddr_in cli;
    int len = sizeof(cli);
    epollRet = epoll_create(1024);
    pthread_t pt;
    int pres = pthread_create(&pt, NULL, thread_run_wait, NULL);
    if (pres == -1){
        perror("pthread_create");
        exit(-1);
    }
    
    while (1){
        int clifd = accept(socketserverfd, NULL, &len);
        printf("新的連接配接對象 %d\n", clifd);
        if (clifd < 0){ 
            perror("accept"); 
            continue;
        }
        struct epoll_event fdEvent;
        fdEvent.events = EPOLLIN|EPOLLERR;
        fdEvent.data.fd = clifd;
        // 添加
        epoll_ctl(epollRet, EPOLL_CTL_ADD, clifd, &fdEvent);
    }
    return 0;
}
           

2. 編譯

gcc epoll_http_test.c -o epoll_server -l pthread
           

編譯後的檔案,這個可以在linux系統運作

epoll-httpserver測試

3. 啟動

./epoll_server 
           

4. 浏覽器請求

http://localhost:8080/

epoll-httpserver測試

背景列印的http請求資訊

epoll-httpserver測試
epoll-httpserver測試

繼續閱讀