网络编程实战框架 五、tcp_server_start(tcpServer) + event_loop_run()
发布日期:2021-05-06 23:39:08 浏览次数:26 分类:精选文章

本文共 4490 字,大约阅读时间需要 14 分钟。

网络服务器事件驱动模型优化与实现

事件驱动模型与线程设计

在网络服务器开发中,事件驱动模型是处理I/O请求和网络连接的核心机制。传统的线程模型通常采用单线程或多线程模型,但随着网络应用的复杂化,多线程模型逐渐成为主流。以下是本文将要探讨的主要结构体和实现细节。

结构体定义

事件循环线程结构体

struct event_loop_thread {    struct event_loop *eventLoop;    pthread_t thread_tid;    /* 线程ID */    pthread_mutex_t mutex;    pthread_cond_t cond;    char *thread_name;    long thread_count;    /* 处理连接的数量 */};

TCP连接结构体

struct tcp_connection {    struct event_loop *eventLoop;    struct channel *channel;    char *name;    struct buffer *input_buffer;    /* 接收缓冲区 */    struct buffer *output_buffer;   /* 发送缓冲区 */    void *data;    /* 回调使用 */    void *request;    /* 回调使用 */    void *response;    /* 回调使用 */};

功能流程

主线程流程

  • 初始化服务器配置参数
  • 启动线程池
  • 启动主事件循环
  • 处理客户端连接请求
  • 子线程流程

  • 初始化事件循环
  • 等待事件到来
  • 分发事件处理
  • 更新事件列表
  • 服务器启动流程

    void tcp_server_start(struct TCPserver *tcpServer) {    struct acceptor *acceptor = tcpServer->acceptor;    struct event_loop *eventLoop = tcpServer->eventLoop;        // 启动线程池    thread_pool_start(tcpServer->threadPool);        // 创建并添加监听channel    struct channel *channel = channel_new(acceptor->listen_fd,                                          EVENT_READ,                                          handle_connection_established,                                          NULL,                                         tcpServer);    event_loop_add_channel_event(eventLoop, channel->fd, channel);}

    事件处理回调

    int handle_connection_established(void *data) {    struct TCPserver *tcpServer = (struct TCPserver *) data;    struct acceptor *acceptor = tcpServer->acceptor;    int listenfd = acceptor->listen_fd;        // 接收新连接    struct sockaddr_in client_addr;    socklen_t client_len = sizeof(client_addr);    int connected_fd = accept(listenfd, (struct sockaddr *) &client_addr, &client_len);    make_nonblocking(connected_fd);        // 获取事件循环    struct event_loop *eventLoop = thread_pool_get_loop(tcpServer->threadPool);        // 创建新的TCP连接    struct tcp_connection *tcpConnection = tcp_connection_new(        connected_fd,         eventLoop,         tcpServer->connectionCompletedCallBack,        tcpServer->connectionClosedCallBack,        tcpServer->messageCallBack,        tcpServer->writeCompletedCallBack    );        // 设置回调数据    if (tcpServer->data != NULL) {        tcpConnection->data = tcpServer->data;    }        return 0;}

    线程池实现

    void thread_pool_start(struct thread_pool *threadPool) {    if (!threadPool->started) {        threadPool->started = true;        // 初始化事件循环线程        threadPool->eventLoopThreads = malloc(threadPool->thread_number * sizeof(struct event_loop_thread));        for (int i = 0; i < threadPool->thread_number; ++i) {            event_loop_thread_init(&threadPool->eventLoopThreads[i], i);            event_loop_thread_start(&threadPool->eventLoopThreads[i]);        }    }}

    线程初始化

    int event_loop_thread_init(struct event_loop_thread *eventLoopThread, int i) {    pthread_mutex_init(&eventLoopThread->mutex, NULL);    pthread_cond_init(&eventLoopThread->cond, NULL);    eventLoopThread->eventLoop = NULL;    eventLoopThread->thread_count = 0;    eventLoopThread->thread_tid = 0;    char *buf = malloc(16);    sprintf(buf, "Thread-%d\0", i + 1);    eventLoopThread->thread_name = buf;    return 0;}

    线程启动

    struct event_loop *event_loop_thread_start(struct event_loop_thread *eventLoopThread) {    pthread_create(&eventLoopThread->thread_tid, NULL, &event_loop_thread_run, eventLoopThread);        pthread_mutex_lock(&eventLoopThread->mutex);    while (eventLoopThread->eventLoop == NULL) {        pthread_cond_wait(&eventLoopThread->cond, &eventLoopThread->mutex);    }    pthread_mutex_unlock(&eventLoopThread->mutex);        yolanda_msgx("event loop thread started, %s", eventLoopThread->thread_name);    return eventLoopThread->eventLoop;}

    事件循环运行

    int event_loop_run(struct event_loop *eventLoop) {    assert(eventLoop != NULL);    struct event_dispatcher *dispatcher = eventLoop->eventDispatcher;        if (eventLoop->owner_thread_id != pthread_self()) {        exit(1);    }        yolanda_msgx("event loop run, %s", eventLoop->thread_name);        struct timeval timeval;    timeval.tv_sec = 1;    while (!eventLoop->quit) {        event_loop_handle_pending_channel(eventLoop);    }        yolanda_msgx("event loop end, %s", eventLoop->thread_name);    return 0;}

    代码优化

  • 线程安全管理:使用pthread_mutex和pthread_cond实现线程安全,确保多线程环境下的数据正确性。
  • 事件驱动设计:通过将I/O事件由主线程转移至子线程处理,提升服务器性能和响应速度。
  • 线程池机制:动态分配和管理事件循环线程,根据系统负载自动调整线程数量,提高资源利用率。
  • 总结

    上述实现展示了一个基于事件驱动的网络服务器框架,通过线程池和事件循环机制,实现了高效的网络连接处理。该设计能够在多线程环境下,动态管理服务器资源,确保网络应用的稳定性和性能。

    上一篇:/proc/sys/kernel/hung_task_timeout_secs问题
    下一篇:ntp同步的问题

    发表评论

    最新留言

    逛到本站,mark一下
    [***.202.152.39]2025年03月31日 04时44分18秒