{"id":628,"date":"2024-06-05T23:47:05","date_gmt":"2024-06-05T15:47:05","guid":{"rendered":"http:\/\/www.madbull.site\/?p=628"},"modified":"2024-08-30T00:01:44","modified_gmt":"2024-08-29T16:01:44","slug":"epoll%e5%a4%9a%e8%b7%af%e5%a4%8d%e7%94%a8%e7%9b%91%e6%8e%a7%e5%a5%97%e6%8e%a5%e5%ad%97%e4%ba%8b%e4%bb%b6","status":"publish","type":"post","link":"https:\/\/www.madbull.site\/?p=628","title":{"rendered":"epoll\u591a\u8def\u590d\u7528\u76d1\u63a7\u5957\u63a5\u5b57\u4e8b\u4ef6"},"content":{"rendered":"\n<div class=\"wp-block-group has-global-padding is-layout-constrained wp-block-group-is-layout-constrained\">\n<p><strong>epoll\u6c34\u5e73\u89e6\u53d1\u6a21\u5f0f\uff0c\u76d1\u63a7\u76d1\u542c\u5957\u63a5\u5b57\u548c\u8fde\u63a5\u5957\u63a5\u5b57\u3002<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ \u7f16\u8bd1 gcc tepoll.c -lpthread -Wall\n\n\n#include &lt;stdio.h>\n#include &lt;stdlib.h>\n#include &lt;string.h>\n#include &lt;unistd.h>\n#include &lt;fcntl.h>\n#include &lt;pthread.h>\n#include &lt;sys\/errno.h>\n#include &lt;sys\/epoll.h>\n#include &lt;netinet\/in.h>\n#include &lt;netinet\/tcp.h>\n#include &lt;arpa\/inet.h>\n#include &lt;signal.h>\n\n#define MAX_EVENTS 10\n#define BUF_MALLOC_SIZE 1*1024*1024\n#define WRITE_DATA_CACHE_SIZE 1024\n\n\n\/*\n * \u7f13\u5b58\u7a7a\u95f4\u63a7\u5236\u7ed3\u6784\n *\/\ntypedef struct _buf_pend_t {                                                                                                                                                                           \n    char* buf;\n    int read_offset;\n    int write_offset;\n    int end_chk_offset;\n    int left_write;\n    int buf_size;\n} buf_pend_t ;\n\n\n\/*\n * \u6ce8\u518c\u7ed9\u4e8b\u4ef6\u76d1\u542c\u7684\u6570\u636e\uff0c\u7528\u6765\u76d1\u542c\u53ef\u8bfb\u4e8b\u4ef6\u3002\n * \u5373\uff0c\u5f53\u53ef\u8bfb\u4e8b\u4ef6\u89e6\u53d1\u540e\uff0c\u5c06\u6b64\u6570\u636e\u901a\u8fc7struct epoll_event\u7ed3\u6784\u7684data\u5b57\u6bb5\u8fd4\u56de\u5230\u5904\u7406\u51fd\u6570\n *\/\ntypedef struct _my_evnt_data_t {\n    int conn_fd ;                 \/\/ \u5ba2\u6237\u7aef\u6765\u8fde\u63a5\u65f6\uff0c\u670d\u52a1\u7aef\u7ef4\u6301\u8fde\u63a5\u6253\u5f00\u7684socket\n    int epoll_fd ;\n    buf_pend_t buf_pend ;    \/\/ \u6570\u636e\u7f13\u5b58\u7ba1\u7406\n    int send_data_len ;        \/\/ \u5f85\u53d1\u9001\u6570\u636e\u957f\u5ea6\n    char * send_data ;     \/\/ \u53d1\u9001\u7684\u6570\u636e\n    void * resource ;        \/\/ \u5176\u4ed6\u7528\u4e8e\u5904\u7406\u6570\u636e\u7684\u8d44\u6e90\uff0c\u6ce8\u610f\uff1a\u4e34\u754c\u8d44\u6e90\u5904\u7406\u4e92\u65a5\u5904\u7406\n} my_evnt_data_t ;\n\n\n\/\/ \u7ed1\u5b9a\u7684IP\u5730\u5740\nconst char * bind_host = \"0.0.0.0\" ;\n\/\/ \u7aef\u53e3\nconst int bind_port = 6666 ;\n\n\n\/*\n * \u521b\u5efa\u76d1\u542c\u7aef\u53e3\n *\/\nint create_listen() {\n    int listen_fd = 0;\n    struct sockaddr_in sin;\n    int flags = 0;\n    struct linger linger_tmp;\n\n    \/\/ 1\u3001\u8bbe\u7f6e\u7ed1\u5b9a\u7684 \u7f51\u7edc\u5730\u5740 \u548c \u7aef\u53e3\n    memset(&amp;sin, 0x00, sizeof(sin));\n    sin.sin_family = AF_INET;\n    inet_aton(bind_host, &amp;(sin.sin_addr));\n    sin.sin_port = htons(bind_port);\n\n    \/\/ 2\u3001\u521b\u5efa\u5957\u63a5\u5b57\n    if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {\n        printf(\"create listen failed !!\\n\");\n        return -1;\n    }\n\n    \/\/ 3\u3001\u8bbe\u7f6esocket\u76f8\u5173\u5c5e\u6027\n    \/\/ 3.1\u3001\u975e\u963b\u585e\n    flags = fcntl(listen_fd, F_GETFL, 0);\n    fcntl(listen_fd, F_SETFL, flags | O_NONBLOCK);\n\n    \/\/ 3.2\u3001\u6587\u4ef6\u63cf\u8ff0\u7b26\u590d\u7528\n    flags = 1;\n    setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &amp;flags, sizeof(flags));\n\n    \/\/ 3.3\u3001\u8bbe\u7f6e\u5728close\u540e\u7684\u8d85\u65f6\u53d1\u9001\u65f6\u95f4\n    linger_tmp.l_onoff = 1;\n    linger_tmp.l_linger = 0;\n    setsockopt(listen_fd, SOL_SOCKET, SO_LINGER, &amp;linger_tmp, sizeof(linger_tmp));\n\n    \/\/ 4\u3001\u7ed1\u5b9a\n    if (bind(listen_fd, (struct sockaddr*)(&amp;sin), sizeof(struct sockaddr)) == -1) {\n        printf(\"bind listen fd failed !!\\n\");\n        return -1;\n    }\n\n    \/\/ 5\u3001\u542f\u52a8\u76d1\u542c\n    if (listen(listen_fd, 4096) == 1) {\n        printf(\"listen failed !!\\n\");\n        return -1;\n    }\n\n    return listen_fd ;\n}\n\n\n\/*\n * \u8bbe\u7f6e\u5957\u63a5\u5b57\u5c5e\u6027\n *\/\nint set_client_fd_attr(int conn_fd){\n    int flags = 0;\n    \/\/ 1\u3001\u8bbe\u7f6e\u975e\u963b\u585e\n    flags = fcntl(conn_fd, F_GETFL, 0);\n    fcntl(conn_fd, F_SETFL, flags | O_NONBLOCK);\n\n    \/\/ 2\u3001\u8bbe\u7f6e\u6587\u4ef6\u63cf\u8ff0\u7b26\u590d\u7528\n    flags = 1;\n    setsockopt(conn_fd, SOL_SOCKET, SO_REUSEADDR, &amp;flags, sizeof(flags));\n\n    \/\/ 3\u3001\u8bbe\u7f6e\u5728close\u540e\u7684\u8d85\u65f6\u53d1\u9001\u65f6\u95f4\n    struct linger linger_tmp;\n    linger_tmp.l_onoff = 1;\n    linger_tmp.l_linger = 0;\n    setsockopt(conn_fd, SOL_SOCKET, SO_LINGER, &amp;linger_tmp, sizeof(linger_tmp));\n    \n    \/\/ 4\u3001\u8bbe\u7f6e\u53d1\u9001\u548c\u63a5\u6536\u8d85\u65f6\u65f6\u95f4\n    struct timeval tv = {30, 0};\n    setsockopt(conn_fd, SOL_SOCKET, SO_RCVTIMEO, &amp;tv, sizeof(tv));\n    setsockopt(conn_fd, SOL_SOCKET, SO_SNDTIMEO, &amp;tv, sizeof(tv));\n\n    \/\/ 5\u3001\u8bbe\u7f6e\u4fdd\u6d3b\u673a\u5236\uff0c\u7a7a\u95f2\u53d1\u8d77\u65f6\u95f4\u3001\u53d1\u9001\u95f4\u9694\u3001\u65e0\u54cd\u5e94\u5c1d\u8bd5\u6b21\u6570\n    int keepidle = 20, keepintval = 2, keepcnt = 5, keepalive = 1;\n    setsockopt(conn_fd, SOL_TCP, TCP_KEEPIDLE, &amp;keepidle, sizeof(keepidle));\n    setsockopt(conn_fd, SOL_TCP, TCP_KEEPINTVL, &amp;keepintval, sizeof(keepintval));\n    setsockopt(conn_fd, SOL_TCP, TCP_KEEPCNT, &amp;keepcnt, sizeof(keepcnt));\n    setsockopt(conn_fd, SOL_SOCKET, SO_KEEPALIVE, &amp;keepalive, sizeof(keepalive));\n\n    return 0 ;\n}\n\n\n\/*\n * \u5173\u95ed\u5ba2\u6237\u7aef\u5957\u63a5\u5b57\n * \u5220\u9664\u7a7a\u95f4\n *\/\nvoid free_ev_data(my_evnt_data_t * ev_data) {\n    printf(\"free_ev_data : conn_fd&#91;%d]\\n\", ev_data->conn_fd) ;\n    if ( ev_data != NULL ) {\n        \/\/ 1\u3001\u5173\u95ed\n        close(ev_data->conn_fd) ;\n        \/\/ 2\u3001\u5220\u9664\u63a5\u6536\u6570\u636e\u7f13\u5b58\n        if( ev_data->buf_pend.buf ){\n            free( ev_data->buf_pend.buf );\n        }\n        \/\/ 3\u3001\u5220\u9664\u53d1\u9001\u6570\u636e\u7f13\u5b58\n        if( ev_data->send_data ){\n            free( ev_data->send_data ) ;\n        }\n        free(ev_data) ;\n    }\n}\n\n\n\/*\n * \u8bbe\u7f6e\u4e8b\u4ef6\u53d1\u751f\u540e\u8fd4\u56de\u7684\u6570\u636e\u7ed3\u6784\n *\/\nmy_evnt_data_t * set_client_deal_data(int conn_fd, int epoll_fd, void * rsc) {\n    \/\/ 1\u3001\u7533\u8bf7\u6570\u636e\u5904\u7406\u7ed3\u6784\n    my_evnt_data_t * ev_data = (my_evnt_data_t *)calloc(1, sizeof(my_evnt_data_t)) ;\n    if ( ev_data == NULL) {\n        printf(\"ev_data calloc NULL\\n\");\n        return NULL;\n    }\n\n    \/\/ 2\u3001\u7533\u8bf7\u63a5\u6536\u6570\u636e\u7f13\u5b58\n    ev_data->buf_pend.buf = (char*)calloc(1,BUF_MALLOC_SIZE);\n    if (ev_data->buf_pend.buf == NULL) {\n        printf(\"ev_data->buf_pend.buf calloc NULL\\n\");\n        free_ev_data(ev_data);\n        return NULL ;\n    }\n\n    ev_data->buf_pend.buf_size = BUF_MALLOC_SIZE ;\n    ev_data->buf_pend.left_write = BUF_MALLOC_SIZE ;\n    ev_data->conn_fd = conn_fd ;                 \/\/ \u5ba2\u6237\u7aef\u6765\u8fde\u63a5\u65f6\uff0c\u670d\u52a1\u7aef\u7ef4\u6301\u8fde\u63a5\u6253\u5f00\u7684socket\n    ev_data->epoll_fd = epoll_fd ;\n    ev_data->resource = rsc ;\n\n    return ev_data ;\n}\n\n\n\/*\n * \u6dfb\u52a0conn_fd\u4e8b\u4ef6\u76d1\u542c\n *\/\nint add_event_to_epoll(my_evnt_data_t * ev_data, int events) {\n\n    int epoll_fd = ev_data->epoll_fd ;\n    int conn_fd = ev_data->conn_fd ; \n    \/\/ \u521d\u59cb\u5316\u76d1\u542c\u65f6\u95f4\u53d8\u91cf\n    struct epoll_event one_event;\n    memset(&amp;one_event, 0x00, sizeof(struct epoll_event));\n    one_event.events = events ;  \/\/ \u8bbe\u7f6e\u76d1\u63a7\u7684\u4e8b\u4ef6 \u51fa\u9519\u3001\u6302\u8d77\u3001\u53ef\u8bfb \u9ed8\u8ba4\u6c34\u5e73\u89e6\u53d1\n    one_event.data.ptr = ev_data  ;                     \/\/ \u628a\u521a\u7533\u8bf7\u7684\u7528\u4e8e\u8fd4\u56de\u7684\u6570\u636e\u7ed3\u4f20\u7ed9 data.ptr \u6307\u9488\n\n    \/\/ \u8bbe\u7f6econn_fd\u4e8b\u4ef6\u76d1\u542c\uff0c\u6ce8\u518c\u4e8b\u4ef6\u53d1\u751f\u65f6\u8fd4\u56de\u7684\u6570\u636e\u7ed3\u6784one_event\n    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, conn_fd, &amp;one_event) &lt; 0) {\n        fprintf(stderr, \"set conn_fd into epoll failed!!\\n\");\n        return -1 ;\n    }\n\n    return 0 ;\n}\n\n\n\/*\n * \u8fde\u63a5\u5904\u7406\n *\/\nint accept_connect(int listen_fd, int epoll_fd, void * rsc) {\n    struct sockaddr_in sin;\n    int conn_fd = 0;\n    int len = sizeof(struct sockaddr);\n\n    int ret = 0;\n\n    \/\/ 1\u3001\u5148\u63a5\u6536\u8fde\u63a5\n    if ((conn_fd = accept(listen_fd, (struct sockaddr*)(&amp;sin), (socklen_t*)&amp;len)) &lt; 0) {\n        fprintf(stderr,\"accept failed !! errno:%d errstr:%s\\n\", errno, strerror(errno));\n        return -1;\n    }\n\n    \/\/ 2\u3001\u8bbe\u7f6e\u5957\u63a5\u5b57\u5c5e\u6027\n    set_client_fd_attr(conn_fd);\n\n    \/\/ 3\u3001\u8bbe\u7f6e\u4e8b\u4ef6\u53d1\u751f\u540e\u8fd4\u56de\u7684\u6570\u636e\u7ed3\u6784\n    my_evnt_data_t * ev_data = set_client_deal_data(conn_fd, epoll_fd, rsc) ;\n    if(ev_data == NULL) {\n        ret = -1 ;\n        goto ERR_END ;\n    }\n\n    \/\/ 4\u3001\u52a0\u5165\u5957\u63a5\u5b57\u76d1\u542c\n    ret = add_event_to_epoll(ev_data, EPOLLERR | EPOLLHUP | EPOLLIN) ;\n    if(ret != 0 ) {\n        ret = -2 ;\n        goto ERR_END ;\n    }\n\n    \/\/ printf(\"set data.ptr addr &#91;%lu] socket&#91;%d]\\n\", (unsigned long)ev_data, conn_fd ) ;\n\n    return ret ;\n\nERR_END:\n    if(ev_data) free_ev_data(ev_data);\n    return ret;\n}\n\n\n\/*\n * \u8c03\u6574\u7f13\u51b2\u533a\u8bfb\u3001\u5199\u3001\u5269\u4f59\u7684\u504f\u79fb\u5730\u5740\n *\/\nint adjust_buf_pend_offset(buf_pend_t * buf_pend) {\n    int unprocess_bytes = 0 ;\n    int end_chk_bytes = 0 ;\n    if (buf_pend->read_offset == buf_pend->write_offset) {  \/\/ \u6570\u636e\u5168\u90e8\u5904\u7406\u5b8c\n        buf_pend->left_write = buf_pend->buf_size;\n\n        buf_pend->read_offset = 0;\n        buf_pend->write_offset = 0;\n        buf_pend->end_chk_offset = 0;\n    } else if (buf_pend->read_offset > 0) {  \/\/ \u6709\u4e00\u90e8\u5206\u6570\u636e\u5df2\u7ecf\u5904\u7406\u5b8c\uff0c\u9700\u8981\u8c03\u6574\n\n        \/\/ \u632a\u52a8\u4f4d\u7f6e\n        unprocess_bytes = buf_pend->write_offset - buf_pend->read_offset;\n        end_chk_bytes = buf_pend->end_chk_offset - buf_pend->read_offset;\n        memcpy(buf_pend->buf, buf_pend->buf + buf_pend->read_offset, unprocess_bytes);\n\n        \/\/ \u91cd\u65b0\u8c03\u6574\u504f\u79fb\n        buf_pend->write_offset = unprocess_bytes ;\n        buf_pend->read_offset = 0;\n        buf_pend->end_chk_offset = end_chk_bytes ;\n\n        \/\/ \u91cd\u65b0\u8ba1\u7b97\u5269\u4f59\u7a7a\u95f4\n        buf_pend->left_write = buf_pend->buf_size - unprocess_bytes;\n    }\n    return 0 ;\n}\n\n\n\/*\n * \u68c0\u6d4b\u7ed3\u675f\u7b26\n *\/\nconst char * END_FLAG = \"##&amp;&amp;\" ;\nint check_end_flag(char * buf_start) {\n\n    for(int i=0 ; i &lt; strlen(END_FLAG) ; ++i ) {\n        if(buf_start&#91;i] != END_FLAG&#91;i]) return 0 ; \n    }\n    return 1 ;\n}\n\n\n\/*\n * \u8bfb\u6570\u636e\u7684\u5217\u8868\n *\/\ntypedef struct _data_node_t {\n    char * data ;\n    struct _data_node_t * next ;\n} data_node_t ;\n\n\n\/*\n * \u6570\u636e\u5904\u7406\n * \u6b64\u5904\u4ec5\u6253\u5370\uff0c\u6839\u636e\u4e1a\u52a1\u9700\u6c42\u81ea\u884c\u5904\u7406\n *\/\nint deal_data_real(char * one_data) {\n    static int id = 0 ;\n    printf(\"one_data : &#91;%.5s]==len&#91;%lu] id &#91;%d]\\n\", one_data, strlen(one_data), ++id ) ;\n    return 0 ;\n}\n\n\n\/*\n * \u8bbe\u7f6e\u8fd4\u56de\u7684\u6570\u636e\n *\/\nint set_send_event(my_evnt_data_t * ev_data, int count) {\n\n    int ret = 0 ;\n    \/\/ 1\u3001\u521d\u59cb\u5316\u53ef\u5199\u76d1\u542c\u8fd4\u56de\u7684\u6570\u636e\n    ev_data->send_data = (char *)calloc(1, WRITE_DATA_CACHE_SIZE+strlen(END_FLAG)+1) ;\n    if( ev_data->send_data == NULL ) {\n        fprintf(stderr, \"no enough memory &#91;ev_data->data]\");\n        return -1 ;\n    }\n\n    snprintf(ev_data->send_data, WRITE_DATA_CACHE_SIZE, \"Just got &#91;%d] data\", count) ;\n    ev_data->send_data_len = strlen(ev_data->send_data) ;\n    snprintf(ev_data->send_data+ev_data->send_data_len, strlen(END_FLAG)+2, \"%s\\n\", END_FLAG) ;\n    ev_data->send_data_len = strlen(ev_data->send_data) ;\n\n    ret = add_event_to_epoll(ev_data, EPOLLOUT ) ;\n    if( ret != 0 ) {\n        return -1 ;    \n    }\n    return 0 ;\n}\n\n\n\/*\n * \u5904\u7406\u6570\u636e\n *\/\nint deal_data( my_evnt_data_t * ev_data, data_node_t * head, void* resp ) {\n    int ret = 0 ;\n    data_node_t * deal_node = head ;\n    int *count = (int*) resp;\n    \n    \/\/ \u9010\u4e2a\u5904\u7406\u6570\u636e\n    while( deal_node ) {\n        ret = deal_data_real(deal_node->data) ;\n        if ( ret != 0 ) break ;\n        (*count) ++ ;\n        deal_node = deal_node->next ;\n    }\n\n    return ret ;\n}\n\n\n\/*\n * \u8bc6\u522b\u7ed3\u675f\u7b26\uff0c\u628a\u6570\u636e\u6361\u51fa\u6765\n *\/\nvoid * check_out_data_and_deal(void* arg) {\n    my_evnt_data_t * ev_data = (my_evnt_data_t*) arg ;\n    int ret = 0 ;\n    char * one_data = NULL ;\n\n    buf_pend_t * buf_pend = &amp;(ev_data->buf_pend) ;\n    char * buf_start = &amp;buf_pend->buf&#91;buf_pend->end_chk_offset] ;\n    char * buf_begine =  &amp;buf_pend->buf&#91;buf_pend->read_offset] ;\n    char * buf_end = &amp;buf_pend->buf&#91;buf_pend->write_offset] - strlen(END_FLAG) ;\n\n    data_node_t * data_node = NULL, * head = NULL, * tail = NULL, * tmp_node = NULL ;\n    while(buf_start &lt;= buf_end ) {\n        \/\/ \u68c0\u6d4b\u7ed3\u675f\u7b26\n        if( check_end_flag(buf_start) == 1 ) {\n            \/\/ \u8bfb\u51fa\u6570\u636e\uff0c\u5728\u5904\u7406\u7ebf\u7a0b\u91cc\u91ca\u653e\n            data_node = (data_node_t*)calloc(1, sizeof(data_node_t) ) ;\n            if(data_node == NULL ) {\n                   fprintf(stderr, \"no enough space data_node\\n\") ;\n                goto ERR_END ;\n            }\n\n            \/\/ \u52a0\u5165\u5230\u5217\u8868\u4e2d\n            if( head == NULL ) {\n                head = data_node ;\n                tail = data_node ;\n            } else {\n                tail->next = data_node ;\n                tail = data_node ;\n            }\n            \/\/ \u7533\u8bf7\u5b58\u50a8\u6570\u636e\u7684\u7a7a\u95f4\n            one_data = (char *)calloc(1, buf_start + strlen(END_FLAG) - buf_begine + 1) ;\n            if(one_data == NULL ) {\n                fprintf(stderr, \"no enough space one_data\\n\") ;\n                goto ERR_END ;\n            }\n            data_node->data = one_data ;\n            memcpy(one_data, buf_begine, buf_start + strlen(END_FLAG) - buf_begine ) ;\n\n            \/\/ \u5411\u540e\u8df3\u8fc7\u7ed3\u675f\u7b26\n            buf_start += strlen(END_FLAG) ;\n            \/\/ \u91cd\u65b0\u8ba1\u7b97 \u8bfb\u504f\u79fb\n            buf_pend->read_offset = buf_start - buf_pend->buf ;\n            buf_begine =  &amp;buf_pend->buf&#91;buf_pend->read_offset] ;\n        } else {\n            buf_start ++ ;\n        }\n    }\n    \/\/ \u8c03\u6574\u68c0\u6d4b\u8fc7\u7684\u6570\u636e\u504f\u79fb\u91cf\n    buf_pend->end_chk_offset = buf_start - buf_pend->buf ;\n\n    int count = 0 ;\n    \/\/ \u5904\u7406\u6570\u636e\n    if( head != NULL ) {\n        ret = deal_data(ev_data, head, &amp;count) ;\n        if(ret != 0 ) {\n            free_ev_data(ev_data) ;\n            goto ERR_END ;\n        }\n    }\n\n    \/\/ \u7528\u5b8c\u4e86\uff0c\u9010\u4e2a\u5220\u9664\n    tmp_node = head ; \n    while(tmp_node) {\n         tmp_node = head->next ;\n         if(head->data) free(head->data) ;\n         free(head) ;\n        head = tmp_node ;\n    }\n\n     \/\/ \u8bbe\u7f6e\u8fd4\u56de\u7684\u6570\u636e\n    ret = set_send_event(ev_data, count) ;\n    if( ret != 0 ) {\n        \/\/ \u8bbe\u7f6e\u5931\u8d25\uff0c\u5219\u5173\u95edconn_fd\u5e76\u6e05\u7406\u6570\u636e\n        free_ev_data(ev_data) ;\n        return NULL ;\n    }\n\n    return NULL ;\n\nERR_END :\n    \/\/ \u6e05\u7406\u7533\u8bf7\u7684\u6570\u636e\n    tmp_node = head ; \n    while(tmp_node != NULL ) {\n         tmp_node = head->next ;\n         if(head->data) free(head->data) ;\n         free(head) ;\n        head = tmp_node ;\n    }\n    return NULL ; \n}\n\n\n\/*\n * \u8bfb\u6570\u636e\u5904\u7406\n *\/\nint read_data(my_evnt_data_t * ev_data) {\n    \/\/ printf(\"ev_data addr &#91;%lu] socket&#91;%d]\\n\", (unsigned long) ev_data, ev_data->conn_fd ) ;\n    buf_pend_t * buf_pend = &amp;ev_data->buf_pend ;\n    int bytes = 0 ;\n    volatile int flag = 0 ; \n    while ((bytes = recv(ev_data->conn_fd, (void*)(buf_pend->buf + buf_pend->write_offset), buf_pend->left_write, 0)) > 0) {\n        \/\/ printf(\"read : data bytes&#91;%d]\\n\", bytes) ;\n        flag = 1 ; \n        buf_pend->write_offset += bytes;\n        buf_pend->left_write -= bytes;\n    }\n    if ( bytes == 0 ) {\n        if( flag == 0 ) {        \/\/ \u8fde\u63a5\u5173\u95ed\u7684\u60c5\u51b5\n            return -1 ;\n        }\n    } else if ( bytes &lt; 0 ) {\n        if (EINTR != errno &amp;&amp; EWOULDBLOCK != errno &amp;&amp; EAGAIN != errno) {  \/\/ \u5982\u679c\u662f\u591a\u4e2a\u76d1\u542c\u7aef\u53e3\uff0cerrno\u4f1a\u76f8\u4e92\u8986\u76d6\uff0c\u53ef\u4ee5\u76f4\u63a5\u5173\u95ed\n            fprintf(stderr, \"connect fd &#91;%d] error, will close later! \\n\", ev_data->conn_fd);\n            return -1;\n        }\n    }\n    \/\/ \u8c03\u6574\u504f\u79fb\u91cf\n    adjust_buf_pend_offset(buf_pend) ;\n    return 0 ;\n}\n\n\n\/*\n * \u5b9e\u9645\u53d1\u9001\u6570\u636e\n *\/\nint send_data(my_evnt_data_t * ev_data) {\n    int ret = 0 ;\n    int total_num = 0 ;\n    int once_num = 0 ;\n    char * send_p = ev_data->send_data ;\n    while(1) {\n        once_num = send(ev_data->conn_fd, send_p, ev_data->send_data_len - total_num, 0) ; \n        if (once_num &lt; 0) {\n            if (EINTR != errno &amp;&amp; EWOULDBLOCK != errno &amp;&amp; EAGAIN != errno) {  \/\/ \u5982\u679c\u662f\u591a\u4e2a\u76d1\u542c\u7aef\u53e3\uff0cerrno\u4f1a\u76f8\u4e92\u8986\u76d6\uff0c\u53ef\u4ee5\u76f4\u63a5\u5173\u95ed\n                fprintf(stderr, \"connect fd &#91;%d] error, will close later! \\n\", ev_data->conn_fd);\n                return -1;\n            }\n            goto END ;\n        } else {\n            total_num += once_num ;\n            send_p += once_num ;\n        }\n\n        if( total_num >= ev_data->send_data_len ) {\n            goto END ;\n        }\n    }\n\nEND:\n    free(ev_data->send_data) ;\n    ev_data->send_data = NULL ;\n    ev_data->send_data_len = 0 ;\n    return ret ;\n}\n\n\n\/*\n * epoll\u4e8b\u4ef6\u76d1\u542c\u670d\u52a1--\u63a5\u6536\u6570\u636e\n *\/\nint epoll_recv_server(int listen_fd, void * rsc) {\n\n    int ret = 0 ;\n    int epoll_fd = 0;\n    struct epoll_event one_event;\n    struct epoll_event event_list&#91;MAX_EVENTS];\n\n    \/\/ 1\u3001\u521b\u5efaepoll\u53e5\u67c4\uff08\u6587\u4ef6\u63cf\u8ff0\u7b26\uff09\n    epoll_fd = epoll_create(MAX_EVENTS);\n\n    \/\/ 2\u3001\u628alisten_fd \u52a0\u5165\u5230 epoll \u7684\u76d1\u63a7\n    \/\/ 2.1\u3001\u521d\u59cb\u5316\u7b2c\u4e00\u4e2a\u4e8b\u4ef6\uff0c\u5373\u76d1\u542c\u4e8b\u4ef6\u88abepoll\u76d1\u63a7\u8d77\u6765\u3002\n    memset(&amp;one_event, 0x00, sizeof(struct epoll_event)) ;\n    one_event.events = EPOLLIN | EPOLLET ;        \/\/ \u8bbe\u7f6e\u88ab\u76d1\u542c\u7684\u4e8b\u4ef6\u662f\uff1a\u53ef\u8bfb\u4e8b\u4ef6\uff0c\u8bbe\u7f6e\u6c34\u5e73\u89e6\u53d1\n    one_event.data.fd = listen_fd;     \/\/ \u9884\u5148\u8bbe\u7f6e\u8981\u8fd4\u56de\u7684\u6570\u636e\uff0c\u5f53\u4e8b\u4ef6\u53d1\u751f\u65f6\uff0c\u8fd4\u56de\u7684 struct epoll_event \u7ed3\u6784\u7684.data.fd\u4e3a\u8fd9\u4e2a\u503c\u3002\n    \n    \/\/ 2.2\u3001\u628alisten_fd\u76d1\u542c\u52a0\u5165\u5230\u4e8b\u4ef6\u76d1\u63a7\uff0c\u76d1\u542c\u4e8b\u4ef6\u53d1\u751f\u65f6\u8fd4\u56de\u4e00\u4e2a\u6570\u636e\u7ed3\u6784 struct epoll_event\n    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd, &amp;one_event) &lt; 0) {\n        fprintf(stderr, \"set listen_fd into epoll failed!!\\n\");\n        return -1;\n    }\n\n    struct epoll_event * event_p ;\n    my_evnt_data_t * ev_data ;\n\n    \/\/ \u8bbe\u7f6e\u7ebf\u7a0b\u5c5e\u6027\uff0c\u53ef\u5206\u79bb\n    pthread_t pthid ;\n    pthread_attr_t pth_attr ;\n    pthread_attr_init(&amp;pth_attr) ;\n    pthread_attr_setdetachstate(&amp;pth_attr, PTHREAD_CREATE_DETACHED) ;\n    \/\/ 3\u3001\u5f00\u59cb\u5faa\u73af\u76d1\u63a7\u4e8b\u4ef6\n    \/\/ 3.1\u3001\u521d\u59cb\u5316\u4e8b\u4ef6\u5217\u8868\uff0c\u6e05\u7a7a\u6240\u6709\u7684\u6570\u636e\u3002\n    memset(event_list, 0x00, sizeof(struct epoll_event) * MAX_EVENTS);\n    while (1) {\n        \/\/ 3.2\u3001\u8d85\u65f6\u7b49\u5f85\u4e8b\u4ef6\u3002\n        \/\/ \u76d1\u63a7\u5230\u6709\u4e8b\u4ef6\u53d1\u751f\uff0c\u5219\u4f1a\u628a\u6ce8\u518c\u65f6\uff08epoll_ctl\u51fd\u6570\u7684EPOLL_CTL_ADD\u53c2\u6570\u6dfb\u52a0\u7684\uff09\u7684\u6570\u636e\u7ed3\u6784\u8fd4\u56de\u3002\n        ret = epoll_wait(epoll_fd, event_list, MAX_EVENTS, 50) ;\n        \/\/ 4\u3001\u5f00\u59cb\u5bf9\u8fd4\u56de\u503c\u8fdb\u884c\u5206\u6790\n        if (ret &lt; 0) {\n            \/\/ 4.1\u3001\u62a5\u9519\u5904\u7406\n            if (EINTR == errno) {\n                continue;\n            }\n            printf(\"epoll failed!!\\n\");\n            return -1;\n        } else if (0 == ret) {\n            \/\/ 4.2\u3001\u6ca1\u6709\u4e8b\u4ef6\uff0c\u8d85\u65f6\u4e86\u3002\u7ee7\u7eed\u4e0b\u4e2a\u5faa\u73af\u7b49\u5f85\u76d1\u542c\n            continue;\n        }\n        \/\/ 5\u3001\u8fdb\u5165\u4e0b\u8fb9\u7684\u4ee3\u7801\uff0c\u5219\u8bf4\u660e\u53d1\u751f\u4e86\u76d1\u542c\u7684\u4e8b\u4ef6\u3002\u904d\u5386\u6240\u6709\u7684\u4e8b\u4ef6\n        for (int i = 0; i &lt; ret; i++) {\n            printf(\"\\n==============================\\n\") ;\n            event_p = &amp;event_list&#91;i] ;\n            if (event_p->data.fd == listen_fd) {\n                \/\/ 5.1\u3001listen_fd\u7684\u4e8b\u4ef6\uff0c\u8bf4\u660e\u6709\u65b0\u7684\u8fde\u63a5\u8fc7\u6765\u4e86\u3002\u8fdb\u5165\u5bf9\u4e8b\u4ef6\u7684\u5904\u7406\u3002\n                accept_connect(listen_fd, epoll_fd, rsc);\n            } else {\n                ev_data = (my_evnt_data_t *)event_p->data.ptr ;\n                \/\/ \u975e listen_fd \u7684\u4e8b\u4ef6\u5904\u7406\n                \/\/ 5.2\u3001\u5305\u542b\u53ef\u8bfb\u4e8b\u4ef6\n                if ( event_p->events &amp; EPOLLIN) {\n                    printf(\"epoll get&#91;%lu] read conn_fd&#91;%d]\\n\", (unsigned long) event_p, ((my_evnt_data_t *)( event_p->data.ptr))->conn_fd) ;\n                    \/\/ 5.2.1\u3001\u5148\u5220\u9664\u4e8b\u4ef6\u76d1\u542c\n                    if (epoll_ctl(epoll_fd, EPOLL_CTL_DEL, ev_data->conn_fd, event_p ) &lt; 0) {\n                        if (EINTR == errno) {\n                            continue;\n                        }\n                        printf(\"delete conn_fd from epoll failed!!\\n\");\n                    }\n                    \/\/ 5.2.2\u3001\u83b7\u53d6\u6570\u636e\uff0c\u5e76\u505a\u57fa\u672c\u5904\u7406\uff0c\u4e0d\u505a\u4e1a\u52a1\u5904\u7406\uff0c(\u53ea\u8d1f\u8d23\u6570\u636e\u7684\u5b58\u50a8\u79fb\u52a8\u7b49)\n                    if (read_data( ev_data ) != 0) {\n                        \/\/ \u91ca\u653e\u7533\u8bf7\u7684\u5185\u5b58\uff0c\u5173\u95edconn_fd\n                        free_ev_data(ev_data);\n                        continue;\n                    }\n                    \/\/ 5.2.3\u3001\u68c0\u6d4b\u6570\u636e\u5b8c\u6574\u6027\u5e76\u5904\u7406\n                    if( pthread_create(&amp;pthid, &amp;pth_attr, check_out_data_and_deal, (void*) ev_data) != 0 ) {\n                        printf(\"pthread_create failed!!\") ;\n                        \/\/ \u7ebf\u7a0b\u521b\u5efa\u4e0d\u6210\u529f\uff0c\u91ca\u653e\u7533\u8bf7\u7684\u5185\u5b58\uff0c\u5173\u95edconn_fd\n                        free_ev_data( ev_data );\n                        continue ;\n                    }\n                }\n                \/\/ 5.3\u3001\u5305\u542b\u53ef\u5199\u4e8b\u4ef6\n                if ( event_p->events &amp; EPOLLOUT) {\n                    printf(\"epoll get&#91;%lu] write conn_fd&#91;%d]\\n\", (unsigned long) event_p, ev_data->conn_fd) ;\n                    \/\/ 5.3.1\u3001\u53bb\u6389\u5bf9conn_fd\u7684\u4e8b\u4ef6\u76d1\u542c\n                    if (epoll_ctl(epoll_fd, EPOLL_CTL_DEL, ev_data->conn_fd, event_p) &lt; 0) {\n                        if (EINTR == errno) {\n                            continue;\n                        }\n                        printf(\"delete conn_fd from epoll failed!!\\n\");\n                    }\n                    \/\/ 5.3.2\u3001\u6267\u884c\u6570\u636e\u53d1\u9001\n                    if ( send_data(ev_data) != 0) {\n                        \/\/ \u91ca\u653e\u7533\u8bf7\u7684\u5185\u5b58\uff0c\u5173\u95edconn_fd\n                        free_ev_data( ev_data );\n                        continue;\n                    }\n                    \/\/ 5.3.3\u3001\u7ee7\u7eed\u76d1\u542c\u53ef\u5199\u4e8b\u4ef6\n                    if( add_event_to_epoll( ev_data, EPOLLERR | EPOLLHUP | EPOLLIN ) != 0 ) {\n                        \/\/ \u91ca\u653e\u7533\u8bf7\u7684\u5185\u5b58\uff0c\u5173\u95edconn_fd\n                        free_ev_data( ev_data );\n                        continue;\n                    }\n                }\n                \/\/ 5.4\u3001\u5305\u542b\u6302\u65ad \u548c \u9519\u8bef\u4e8b\u4ef6\n                if ( event_p->events &amp; (EPOLLHUP | EPOLLERR)) {\n                    printf(\"epoll get&#91;%lu] error conn_fd&#91;%d]\\n\", (unsigned long) event_p, ((my_evnt_data_t *)( event_p->data.ptr))->conn_fd) ;\n                    \/\/ 5.4.1\u3001\u4eceepoll\u76d1\u542c\u4e8b\u4ef6\u96c6\u4e2d\u5220\u9664\u5bf9\u5e94\u6587\u4ef6\u63cf\u8ff0\u7b26\u7684\u76d1\u542c\n                    if (epoll_ctl(epoll_fd, EPOLL_CTL_DEL, ev_data->conn_fd, event_p) &lt; 0) {\n                        if (EINTR == errno) {\n                            continue;\n                        }\n                        printf(\"delete conn_fd from epoll failed!!\\n\");\n                    }\n                    \/\/ 5.4.2\u3001\u91ca\u653e\u7533\u8bf7\u7684\u5185\u5b58\uff0c\u5173\u95edconn_fd\n                    free_ev_data( ev_data );\n                    continue;\n                }\n            }\n        }\n    }\n    pthread_attr_destroy(&amp;pth_attr) ;\n    close(listen_fd);\n    close(epoll_fd);\n}\n\n\n\nvoid hand(int signo) {\n    printf(\"signo &#91;%d]\\n\", signo) ;\n}\n\nint main(){\n\n    int ret = 0 ;\n    void * rsc = NULL ; \n    int listen_fd = create_listen() ;\n    \n    signal(SIGPIPE, hand) ;\n    ret = epoll_recv_server(listen_fd, rsc) ;\n    exit(ret) ;\n\n    return 0 ;\n}<\/code><\/pre>\n\n\n\n<div style=\"margin-top:var(--wp--preset--spacing--20);margin-bottom:var(--wp--preset--spacing--20);height:5px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n<\/div>\n\n\n\n<p>\u53d1\u8d77\u6d4b\u8bd5\uff0c\u7ea2\u8272\u5185\u5bb9\u4e3a\u8f93\u5165\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"586\" height=\"279\" src=\"https:\/\/www.madbull.site\/wp-content\/uploads\/2024\/06\/1.png\" alt=\"\" class=\"wp-image-634\" srcset=\"https:\/\/www.madbull.site\/wp-content\/uploads\/2024\/06\/1.png 586w, https:\/\/www.madbull.site\/wp-content\/uploads\/2024\/06\/1-300x143.png 300w\" sizes=\"auto, (max-width: 586px) 100vw, 586px\" \/><\/figure>\n\n\n\n<p>\u670d\u52a1\u7aef\u8f93\u51fa\u60c5\u51b5<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"389\" height=\"836\" src=\"https:\/\/www.madbull.site\/wp-content\/uploads\/2024\/06\/22.png\" alt=\"\" class=\"wp-image-635\" srcset=\"https:\/\/www.madbull.site\/wp-content\/uploads\/2024\/06\/22.png 389w, https:\/\/www.madbull.site\/wp-content\/uploads\/2024\/06\/22-140x300.png 140w\" sizes=\"auto, (max-width: 389px) 100vw, 389px\" \/><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>epoll\u6c34\u5e73\u89e6\u53d1\u6a21\u5f0f\uff0c\u76d1\u63a7\u76d1\u542c\u5957\u63a5\u5b57\u548c\u8fde\u63a5\u5957\u63a5\u5b57\u3002<\/p>\n","protected":false},"author":1,"featured_media":559,"comment_status":"open","ping_status":"open","sticky":false,"template":"single-with-sidebar","format":"standard","meta":{"footnotes":"[]"},"categories":[156,154],"tags":[234,227,231,232,235,236,230,233,228,229],"class_list":["post-628","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-c","category-154","tag-connect","tag-epoll","tag-epollin","tag-epollout","tag-recv","tag-send","tag-signal","tag-struct-epoll_event","tag-tcp","tag-229"],"_links":{"self":[{"href":"https:\/\/www.madbull.site\/index.php?rest_route=\/wp\/v2\/posts\/628","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.madbull.site\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.madbull.site\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.madbull.site\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.madbull.site\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=628"}],"version-history":[{"count":3,"href":"https:\/\/www.madbull.site\/index.php?rest_route=\/wp\/v2\/posts\/628\/revisions"}],"predecessor-version":[{"id":636,"href":"https:\/\/www.madbull.site\/index.php?rest_route=\/wp\/v2\/posts\/628\/revisions\/636"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.madbull.site\/index.php?rest_route=\/wp\/v2\/media\/559"}],"wp:attachment":[{"href":"https:\/\/www.madbull.site\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=628"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.madbull.site\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=628"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.madbull.site\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=628"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}