天天看点

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测试

继续阅读