8 https服务器的实现

这个代码核心就是我们首先监听一个8000接口,然后再服务器上访问这个接口,会得到一些https头文件

rbuffer: GET / HTTP/1.1
Host: 10.150.132.253:8000
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9

注意看这里:
在这里插入图片描述

然后我们回复一个html,再网页上显示。
在这里插入图片描述
其底层就是这样的:
在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include <fcntl.h>
#include <pthread.h>

#include <sys/poll.h>
#include <sys/epoll.h>

#define BUFFER_LENGTH		1024
#define EVENT_LENGTH		1024

typedef int (*ZVCALLBACK)(int fd, int events, void *arg);


typedef struct zv_connect_s {

    int fd;

    ZVCALLBACK cb;	// 回调函数

    int count;

    char rbuffer[BUFFER_LENGTH];
    int rc; // 当前rbuffer占用了多少

    char wbuffer[BUFFER_LENGTH];
    int wc; // 当前wbuffer占用了多少

} zv_connect_t;

typedef struct zv_connblock_s {

    zv_connect_t *block;
    struct zv_connblock_s *next;

} zv_connblock_t;

typedef struct zv_reactor_s {

    int epfd;
    int blkcnt;

    zv_connblock_t *blockheader;

} zv_reactor_t;


//初始化的三种写发
//zv_reactor_t* zv_init_reactor(void);
//zv_reactor_t* zv_init_reactor(zv_reactor_t * reactor);
int zv_init_reactor(zv_reactor_t *reactor) {

    if (!reactor) return -1;
#if 0
    reactor->blockheader = malloc(sizeof(zv_reactor_t));
    if (reactor->blockheader == NULL)	return -1;

    reactor->epfd = epoll_create(1);

    reactor->blockheader->block = calloc(1024, sizeof(zv_connect_t));
    if (reactor->blockheader->block == NULL)	return -1;

#else

    reactor->blockheader = (zv_connblock_t *)malloc(sizeof(zv_reactor_t) + EVENT_LENGTH * sizeof(zv_connect_t));
    if (reactor->blockheader == NULL)	return -1;

    reactor->blockheader->block = (zv_connect_t*)(reactor->blockheader + 1);
    reactor->blkcnt = 1;
    reactor->blockheader->next = NULL;

    reactor->epfd = epoll_create(1);

#endif
    return 0;
}

void zv_destory_reactor(zv_reactor_t *reactor) {
    if (!reactor) return ;

    if (reactor->blockheader)	free(reactor->blockheader);

    close(reactor->epfd);

}

int zv_connect_block(zv_reactor_t *reactor) {

    if (!reactor) return -1;

    zv_connblock_t *blk = reactor->blockheader;

    while (blk->next != NULL) blk = blk->next;

    zv_connblock_t *connblock = (zv_connblock_t *) malloc(sizeof(zv_reactor_t) + EVENT_LENGTH * sizeof(zv_connect_t));
    if (connblock == NULL)	return -1;


    //blk->next = connblock;
    connblock->block = (zv_connect_t*)(connblock + 1);
    connblock->next = NULL;

    blk->next = connblock;
    reactor->blkcnt++;

    return 0;
}

zv_connect_t *zv_connect_idx(zv_reactor_t *reactor, int fd) {

    if (!reactor) return NULL;

    int blkidx = fd / EVENT_LENGTH;

    while (blkidx >= reactor->blkcnt) {
        zv_connect_block(reactor);
    }

    int i = 0;
    zv_connblock_t *blk = reactor->blockheader;
    while (i++ < blkidx) {
        blk = blk->next;
    }

    return &blk->block[fd % EVENT_LENGTH];

}
//recv_cb(reactor)
//send_cb()
//zv_connect_t

// rbuffer: GET / HTTP/1.1
// Host: 127.0.0.1:8000
// Connection: keep-alive
// Cache-Control: max-age=0
// sec-ch-ua: "Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"
// sec-ch-ua-mobile: ?0
// sec-ch-ua-platform: "Linux"
// Upgrade-Insecure-Requests: 1
// User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
// Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
// Sec-Fetch-Site: cross-site
// Sec-Fetch-Mode: navigate
// Sec-Fetch-Dest: document
// Accept-Encoding: gzip, deflate, br, zstd
// Accept-Language: zh-CN,zh;q=0.9

int readline(char *allbuf,int idx,char *linebuf){
    int len=strlen(allbuf);
    for(;idx<len;idx++){
        if(allbuf[idx]=='\r'&&allbuf[idx+1]=='\n'){
            return idx+2;
        }else{
            *(linebuf++)=allbuf[idx];
        }
    }
}

int zv_http_response(zv_connect_t *conn){
    //将响应协议写入wbuffer中
    int len = sprintf(conn->wbuffer,
                      "HTTP/1.1 200 OK\r\n"
                      "Accept-Ranges: bytes\r\n"
                      "Content-Length: 78r\n"
                      "Content-Type: text/html\r\n"
                      "Date: Sat, 06 Aug 2022 13:16:46 GMT\r\n\r\n"
                      "<html><head><title>0vi=oice.king</title></head><boby><h1>lipu123</h1></boby></html>");

    conn->wc=len;

    //conn->wbuffer
    //conn->wc=len


}
//要让请求和关联做在一起
int zv_http_request(zv_connect_t *conn){
    //conn->rbuffer
    //conn->rc

    printf("http ---> request:\n %s\n",conn->rbuffer);
    char linebuffer[1024]={0};

    int idx = readline(conn->rbuffer,0,linebuffer);
    printf("line: %s\n",linebuffer);

#if 1
    if(strstr(linebuffer,"GET")){//resource
        //printf("resource: %s\n",linebuffer+4);
        int i=0;
        while(linebuffer[sizeof("GET ") + i]!=' ') i++;
        linebuffer[sizeof("GET ")+i]='\0';

        printf("resource: %s\n",linebuffer+4);
    }

#endif

}


int init_server(short port) {

    int sockfd = socket(AF_INET, SOCK_STREAM, 0); //io

    struct sockaddr_in servaddr;
    memset(&servaddr, 0, sizeof(struct sockaddr_in)); // 192.168.1.123
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 0.0.0.0
    servaddr.sin_port = htons(port);

    if(-1 == bind(sockfd, (struct sockaddr*)&servaddr, sizeof(struct sockaddr))) {
        printf(" bind failed: %s", strerror(errno));
        return -1;
    }

    listen(sockfd, 10);

    printf("sockfd port: %d\n", port);

    return sockfd;
}

int recv_cb(int fd, int events, void * arg);

int send_cb(int fd, int events, void *arg) {

    //printf("send_cb\n");

    zv_reactor_t *reactor = (zv_reactor_t*)arg;
    zv_connect_t *conn = zv_connect_idx(reactor, fd);

    //send之前返回response
    zv_http_response(conn);

    send(fd, conn->wbuffer, conn->wc, 0);

    conn->cb = recv_cb;

    struct epoll_event ev;
    ev.events = EPOLLIN;
    ev.data.fd = fd;
    epoll_ctl(reactor->epfd, EPOLL_CTL_MOD, fd, &ev);


    return 0;

}


int recv_cb(int fd, int events, void *arg) {

    zv_reactor_t *reactor = (zv_reactor_t*)arg;
    zv_connect_t *conn = zv_connect_idx(reactor, fd);

    int ret = recv(fd, conn->rbuffer + conn->rc, conn->count, 0);
    if (ret < 0) {
        printf("recv errno: %d\n", errno);
        return -1;
    }
    else if (ret == 0) {	// 当io断开 置为不可用

        conn->fd = -1;
        conn->rc = 0;
        conn->wc = 0;

        epoll_ctl(reactor->epfd, EPOLL_CTL_DEL, fd, NULL);

        close(fd);
        return -1;
    }else{

        conn->rc += ret;

        printf("rbuffer: %s, rc: %d\n", conn->rbuffer, conn->rc);

        //-->echo
        //memcpy(conn->wbuffer, conn->rbuffer, conn->rc);
        //printf("rc: %d\n", conn->rc);
        //conn->wc = conn->rc;

        //接收之后处理请求
        zv_http_request(conn);

        conn->cb = send_cb;

        struct epoll_event ev;
        ev.events = EPOLLOUT;
        ev.data.fd = fd;
        epoll_ctl(reactor->epfd, EPOLL_CTL_MOD, fd, &ev);
    }
    return 0;
}


int accept_cb(int fd, int events, void *arg) {

    //printf("accept_cb\n");

    struct sockaddr_in clientaddr;
    socklen_t len = sizeof(clientaddr);

    int clientfd = accept(fd, (struct sockaddr*)&clientaddr, &len);
    if (clientfd < 0) {

        printf("accept errno: %d\n", errno);
        return -1;
    }

    printf("clientfd: %d\n", clientfd);

    zv_reactor_t *reactor = (zv_reactor_t*)arg;
    zv_connect_t *conn = zv_connect_idx(reactor, clientfd);;

    conn->fd = clientfd;
    conn->cb = recv_cb;
    conn->count = BUFFER_LENGTH;

    struct epoll_event ev;
    ev.events = EPOLLIN;
    ev.data.fd = clientfd;
    epoll_ctl(reactor->epfd, EPOLL_CTL_ADD, clientfd, &ev);

    return 0;
}



int set_listener(zv_reactor_t *reactor, int fd, ZVCALLBACK cb) {

    if (!reactor || !reactor->blockheader)	return -1;

    reactor->blockheader->block[fd].fd = fd;
    reactor->blockheader->block[fd].cb = cb;

    struct epoll_event ev;
    ev.events = EPOLLIN;
    ev.data.fd = fd;

    epoll_ctl(reactor->epfd, EPOLL_CTL_ADD, fd, &ev);

    return 0;
}

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

    if (argc < 2)	return -1;

    zv_reactor_t reactor;
    zv_init_reactor(&reactor);

    int port = atoi(argv[1]);

    int i = 0;
    for (i = 0; i < 1; ++ i) {
        int sockfd = init_server(port + i);
        set_listener(&reactor, sockfd, accept_cb);
    }

    struct epoll_event events[EVENT_LENGTH] = {0};

    while (1) {

        int nready = epoll_wait(reactor.epfd, events, EVENT_LENGTH, -1);

        int i = 0;
        for (i = 0; i < nready; ++ i) {

            int connfd = events[i].data.fd;
            zv_connect_t *conn = zv_connect_idx(&reactor, connfd);	// 等同于 &reactor.blockheader->block[connfd]

            if (events[i].events & EPOLLIN) {

                conn->cb(connfd, events[i].events, &reactor);
            }
            if (events[i].events & EPOLLOUT) {

                conn->cb(connfd, events[i].events, &reactor);
            }

        }

    }

    return 0;

}

之后我们定义该目录为http的根目录,然后就可以访问该目录下的html文件了。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

如果我们想访问图片的画,要改一个地方:
在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include <fcntl.h>
#include <pthread.h>

#include <sys/poll.h>
#include <sys/epoll.h>
#include <sys/stat.h>
#include <sys/sendfile.h>



#define BUFFER_LENGTH		1024
#define EVENT_LENGTH		1024

#define HTTP_WEB_ROOT		"/home/user/03_high_server/06_reactor"	// hb.jpg所在的文件夹(绝对路径)



typedef int (*ZVCALLBACK)(int fd, int events, void *arg);


typedef struct zv_connect_s {

    int fd;

    ZVCALLBACK cb;	// 回调函数

    int count;

    char rbuffer[BUFFER_LENGTH];
    int rc; // 当前rbuffer占用了多少

    char wbuffer[BUFFER_LENGTH];
    int wc; // 当前wbuffer占用了多少

    char resource[BUFFER_LENGTH];	//

    int enable_sendfile;

} zv_connect_t;

typedef struct zv_connblock_s {

    zv_connect_t *block;
    struct zv_connblock_s *next;

} zv_connblock_t;

typedef struct zv_reactor_s {

    int epfd;
    int blkcnt;

    zv_connblock_t *blockheader;

} zv_reactor_t;


//初始化的三种写发
//zv_reactor_t* zv_init_reactor(void);
//zv_reactor_t* zv_init_reactor(zv_reactor_t * reactor);
int zv_init_reactor(zv_reactor_t *reactor) {

    if (!reactor) return -1;
#if 0
    reactor->blockheader = malloc(sizeof(zv_reactor_t));
    if (reactor->blockheader == NULL)	return -1;

    reactor->epfd = epoll_create(1);

    reactor->blockheader->block = calloc(1024, sizeof(zv_connect_t));
    if (reactor->blockheader->block == NULL)	return -1;

#else

    reactor->blockheader = malloc(sizeof(zv_reactor_t) + EVENT_LENGTH * sizeof(zv_connect_t));
    if (reactor->blockheader == NULL)	return -1;

    reactor->blockheader->block = (zv_connect_t*)(reactor->blockheader + 1);
    reactor->blkcnt = 1;
    reactor->blockheader->next = NULL;

    reactor->epfd = epoll_create(1);

#endif
    return 0;
}

void zv_destory_reactor(zv_reactor_t *reactor) {
    if (!reactor) return ;

    if (reactor->blockheader)	free(reactor->blockheader);

    close(reactor->epfd);

}

int zv_connect_block(zv_reactor_t *reactor) {

    if (!reactor) return -1;

    zv_connblock_t *blk = reactor->blockheader;

    while (blk->next != NULL) blk = blk->next;

    zv_connblock_t *connblock = malloc(sizeof(zv_reactor_t) + EVENT_LENGTH * sizeof(zv_connect_t));
    if (connblock == NULL)	return -1;


    //blk->next = connblock;
    connblock->block = (zv_connect_t*)(connblock + 1);
    connblock->next = NULL;

    blk->next = connblock;
    reactor->blkcnt++;

    return 0;
}

zv_connect_t *zv_connect_idx(zv_reactor_t *reactor, int fd) {

    if (!reactor) return NULL;

    int blkidx = fd / EVENT_LENGTH;

    while (blkidx >= reactor->blkcnt) {
        zv_connect_block(reactor);
    }

    int i = 0;
    zv_connblock_t *blk = reactor->blockheader;
    while (i++ < blkidx) {
        blk = blk->next;
    }

    return &blk->block[fd % EVENT_LENGTH];

}

//http的请求协议

//GET / HTTP/1.1
//Host: 192.168.126.132:8000
//Connection: keep-alive
//Cache-Control: max-age=0
//Upgrade-Insecure-Requests: 1
//User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36
//Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
//Accept-Encoding: gzip, deflate
//Accept-Language: zh-CN,zh;q=0.9

//读取协议的一行
int readline(char *allbuf, int idx, char *linebuf) {
    int len = strlen(allbuf);

    for (; idx < len; ++idx) {
        if (allbuf[idx] == '\r' && allbuf[idx+1] == '\n') {
            return idx + 2;
        } else {
            *(linebuf++) = allbuf[idx];
        }
    }
    return -1;
}


//URL:
//http://192.168.126.132:8000/hb.jpg

//响应协议
//HTTP/1.1 200 OK
//Accept-Ranges: bytes
//Content-Length: 92678
//Content-Type: image/jpg
//Date: Sat, 06 Aug 2022 13:16:46 GMT

int zv_http_response(zv_connect_t *conn) {
#if 0
    int len = sprintf(conn->wbuffer,
        "");
    conn->wc = len;

#elif 0

    printf("resource: %s\n", conn->resource);

    int filefd = open(conn->resource, O_RDONLY);
    if (filefd == -1) return -1;

    //fseek(, SEEK_END)
    struct stat stat_buf;
    fstat(filefd, &stat_buf);

    //将响应协议写入wbuffer中
    int len = sprintf(conn->wbuffer,
                      "HTTP/1.1 200 OK\r\n"
                      "Accept-Ranges: bytes\r\n"
                      "Content-Length: %ld\r\n"
                      "Content-Type: text/html\r\n"
                      "Date: Sat, 06 Aug 2022 13:16:46 GMT\r\n\r\n", stat_buf.st_size);

    len += read(filefd, conn->wbuffer + len, BUFFER_LENGTH-len);	//将文件信息也写在wbuffer后

    conn->wc = len;

    close(filefd);

#elif 0
    int filefd = open(conn->resource, O_RDONLY);
    if (filefd == -1) return -1;

    struct stat stat_buf;
    fstat(filefd, &stat_buf);
    close(filefd);

    int len = sprintf(conn->wbuffer,
                      "HTTP/1.1 200 OK\r\n"
                      "Accept-Ranges: bytes\r\n"
                      "Content-Length: %ld\r\n"
                      "Content-Type: text/html\r\n"
                      "Date: Sat, 06 Aug 2022 13:16:46 GMT\r\n\r\n", stat_buf.st_size);

    conn->wc = len;

    conn->enable_sendfile = 1;
#else
    int filefd = open(conn->resource, O_RDONLY);	// 打开文件,以只读的方式
    if (filefd == -1) return -1;

    struct stat stat_buf;
    fstat(filefd, &stat_buf);	// 将打开的文件信息,存入stat_buf
    close(filefd);


    // 将第三个参数stat_buf.st_size写在第二个参数的%ld的位置,再把第二个参数存入第一个参数conn->wbuffer中
    //返回参数len表示此次写入conn->wbuffer中的长度
    int len = sprintf(conn->wbuffer,
                      "HTTP/1.1 200 OK\r\n"
                      "Accept-Ranges: bytes\r\n"
                      "Content-Length: %ld\r\n"
                      "Content-Type: image/jpg\r\n"
                      "Date: Sat, 06 Aug 2022 13:16:46 GMT\r\n\r\n", stat_buf.st_size);
    conn->wc = len;

    conn->enable_sendfile = 1;

#endif
}

//URL:
//http://192.168.126.132:8000/hb.jpg

//请求协议:
//GET /hb.jpg HTTP/1.1
//Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
//Accept-Encoding: gzip, deflate
//Accept-Language: zh-CN,zh;q=0.9
//Cache-Control: max-age=0
//Connection: keep-alive
//Host: 192.168.126.132:8000
//Upgrade-Insecure-Requests: 1
//User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36

int zv_http_request(zv_connect_t *conn) {

    printf("http --> request:\n %s\n", conn->rbuffer);

    char linebuffer[1024] = {0};

    int idx = readline(conn->rbuffer, 0, linebuffer);
    printf("line: %s\n", linebuffer);
#if 1
    if (strstr(linebuffer, "GET")) {

        //printf("resource: %s\n", linebuffer+4);
        int i = 0;
        while (linebuffer[sizeof("GET ") + i] != ' ') ++i;
        linebuffer[sizeof("GET ") + i] = '\0';

        //memcpy(conn->resource, linebuffer + sizeof("GET "), sizeof(linebuffer));
        //printf("resource: %s\n", linebuffer+4); n

        sprintf(conn->resource, "%s/%s", HTTP_WEB_ROOT, linebuffer + sizeof("GET "));	// conn->resource = "/home/hebo/server-1/2-1-1-multi-io/hb.jpg"
    }
#endif

}

int init_server(short port) {

    int sockfd = socket(AF_INET, SOCK_STREAM, 0); //io

    struct sockaddr_in servaddr;
    memset(&servaddr, 0, sizeof(struct sockaddr_in)); // 192.168.1.123
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 0.0.0.0
    servaddr.sin_port = htons(port);

    if(-1 == bind(sockfd, (struct sockaddr*)&servaddr, sizeof(struct sockaddr))) {
        printf("bind failed: %s", strerror(errno));
        return -1;
    }

    listen(sockfd, 10);

    printf("sockfd port: %d\n", port);

    return sockfd;
}

int recv_cb(int fd, int events, void * arg);

int send_cb(int fd, int events, void *arg) {

    //printf("send_cb\n");

    zv_reactor_t *reactor = (zv_reactor_t*)arg;
    zv_connect_t *conn = zv_connect_idx(reactor, fd);

    zv_http_response(conn);	// 在服务端发送响应协议之前 在send之前进行响应协议处理

    // 1. 如果是conn->enable_sendfile == 0,此次send就将响应协议和文件信息一起发送给客户端,只发送一次
    // 2_1. 如果是conn->enable_sendfile == 1,此次send就只发送响应协议,共需发送两次(第一次)
    send(fd, conn->wbuffer, conn->wc, 0);	// send head
#if 1
    if (conn->enable_sendfile) {	// send body
        int filefd = open(conn->resource, O_RDONLY);
        if (filefd == -1) return -1;

        struct stat stat_buf;
        fstat(filefd, &stat_buf);

        //ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count); 零拷贝机制(指磁盘到内存不需要cpu参与) DMA
        // 2_2. 如果是conn->enable_sendfile == 1,此次send就只发送文件信息,共需发送两次(第二次)
        int ret = sendfile(fd, filefd, NULL, stat_buf.st_size);	// sendbody  发送文件信息
        if (ret == -1) {
            printf("sendfile errno: %d\n", errno);
        }

        close(filefd);
    }
#endif

    conn->cb = recv_cb;

    struct epoll_event ev;
    ev.events = EPOLLIN;
    ev.data.fd = fd;
    epoll_ctl(reactor->epfd, EPOLL_CTL_MOD, fd, &ev);

    //return 0;
}

int recv_cb(int fd, int events, void *arg) {

    zv_reactor_t *reactor = (zv_reactor_t*)arg;
    zv_connect_t *conn = zv_connect_idx(reactor, fd);

    int ret = recv(fd, conn->rbuffer + conn->rc, conn->count, 0);
    if (ret < 0) {
        //printf("recv errno: %d\n", errno);
        //return -1;
    }
    else if (ret == 0) {	// 当io断开 置为不可用

        conn->fd = -1;
        conn->rc = 0;
        conn->wc = 0;

        epoll_ctl(reactor->epfd, EPOLL_CTL_DEL, fd, NULL);

        close(fd);
        return -1;
    }
    else {

        printf("rc: %d rbuffer:\n%s\n", conn->rc, conn->rbuffer);

        conn->rc += ret;

        //memcpy(conn->wbuffer, conn->rbuffer, conn->rc);
        //printf("rc: %d\n", conn->rc);
        //conn->wc = conn->rc;

        zv_http_request(conn);	// 客户端发送请求协议后 在send之前进行协议处理

        conn->cb = send_cb;

        struct epoll_event ev;
        ev.events = EPOLLOUT;
        ev.data.fd = fd;
        epoll_ctl(reactor->epfd, EPOLL_CTL_MOD, fd, &ev);

    }
    //return 0;
}

int accept_cb(int fd, int events, void *arg) {

    //printf("accept_cb\n");

    struct sockaddr_in clientaddr;
    socklen_t len = sizeof(clientaddr);

    int clientfd = accept(fd, (struct sockaddr*)&clientaddr, &len);
    if (clientfd < 0) {

        printf("accept errno: %d\n", errno);
        return -1;
    }

    printf("clientfd: %d\n", clientfd);

    zv_reactor_t *reactor = (zv_reactor_t*)arg;
    zv_connect_t *conn = zv_connect_idx(reactor, clientfd);;

    conn->fd = clientfd;
    conn->cb = recv_cb;
    conn->count = BUFFER_LENGTH;

    struct epoll_event ev;
    ev.events = EPOLLIN;
    ev.data.fd = clientfd;
    epoll_ctl(reactor->epfd, EPOLL_CTL_ADD, clientfd, &ev);

    //return 0;
}

int set_listener(zv_reactor_t *reactor, int fd, ZVCALLBACK cb) {

    if (!reactor || !reactor->blockheader)	return -1;

    reactor->blockheader->block[fd].fd = fd;
    reactor->blockheader->block[fd].cb = cb;

    struct epoll_event ev;
    ev.events = EPOLLIN;
    ev.data.fd = fd;

    epoll_ctl(reactor->epfd, EPOLL_CTL_ADD, fd, &ev);

    //return 0;
}

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

    if (argc < 2)	return -1;

    //printf("sockfd: %d\n", sockfd);

    zv_reactor_t reactor;
    zv_init_reactor(&reactor);

    int port = atoi(argv[1]);

    int i = 0;
    for (i = 0; i < 1; ++ i) {
        int sockfd = init_server(port + i);
        set_listener(&reactor, sockfd, accept_cb);
    }

    struct epoll_event events[EVENT_LENGTH] = {0};

    while (1) {

        int nready = epoll_wait(reactor.epfd, events, EVENT_LENGTH, -1);

        int i = 0;
        for (i = 0; i < nready; ++ i) {

            int connfd = events[i].data.fd;
            zv_connect_t *conn = zv_connect_idx(&reactor, connfd);	// 等同于 &reactor.blockheader->block[connfd]

            if (events[i].events & EPOLLIN) {

                conn->cb(connfd, events[i].events, &reactor);
            }
            if (events[i].events & EPOLLOUT) {

                conn->cb(connfd, events[i].events, &reactor);
            }

        }

    }
    return 0;

}

在这里插入图片描述
如果我们要做一个http服务器的话,我们要注意几点

  1. reactor
  2. request/response
  3. 并发量测出来
  4. index.html/png
  5. header用什么存储,这里通常用key-Value存储
    在这里插入图片描述

对于Key-value有哪些可以存储:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值