如何优化C非阻塞accept()套接字连接

时间:2018-01-28 10:32:38

标签: c sockets

我有一个app(服务器),它使用accept()从手机(客户端)接收TCP套接字连接。它似乎工作,但当我在Apple Instruments中运行我的应用程序时,我可以看到这个应用程序使用大约100%的CPU,主要原因95%的帐户调用非阻塞accept()。我想我已经添加了这个非阻塞的accept()方法调用,以便能够通过单击GUI按钮“停止服务器”随时停止服务器。通过这个解决方案我可以每次检查我是否有一个标志shouldShutDown等于true然后我关闭服务器()

enter image description here

这是服务器循环的代码:

/**
 * Function is looping infinitely and waiting
 * for new incoming connections.
 * It handles each connection on thread pool's worker thread
 */
result_t thread_pool_stream_server_loop(server_info_t *server_info, connection_handler_t conn_handler) {

    sock_fd_t cs_fd, ps_fd;
    thread_pool_t *thread_pool;

    // get passive server socket
    ps_fd = server_info_sock(server_info);

    // initialize thread pool and set its size
    thread_pool_init(&thread_pool, 5, 10, 3000 /* [ms] */);

    while(1) {

        if(server_info_should_shut_down(server_info)) {
            thread_pool_shutdown(thread_pool);
            return CLOSED;
        }
        if(server_info_force_shut_down(server_info)) {
            thread_pool_shutdown(thread_pool);
            return FORCE_CLOSED;
        }

        // check to accept new connections on the main thread...
        cs_fd = accept_new_connection(ps_fd);

        if(cs_fd == FAILURE) {
            fprintf(stderr, "accept_new_connection: failed!\n");
            server_info_connection_error_event(server_info, cs_fd, CONN_ERROR_ACCEPT, "accept_new_connection: failed!");
            break;
        } else if(cs_fd == CONTINUE) {
            continue;
        }

        // publish client connected event
        server_info_client_connected_event(server_info, cs_fd);

        // revert connection socket to non-blocking
        int opts = fcntl(cs_fd, F_GETFL);
        opts = opts & (~O_NONBLOCK);
        fcntl(cs_fd, F_SETFL, opts);

        // handle new connection by thread pool's worker thread
        conn_thread_runner_attr_t *connection_thread_runner_attr;
        conn_thread_runner_attr_init(&connection_thread_runner_attr);
        conn_thread_runner_attr_fill(connection_thread_runner_attr, conn_handler, server_info, cs_fd, NULL, NULL);

        thread_pool_run(thread_pool, (runner_t) connection_thread_runner, (runner_attr_t) connection_thread_runner_attr, NULL);

        // adjust thread pool actual size to number of added connection handling tasks
        thread_pool_adjust_size(thread_pool);
    }

    thread_pool_force_free(thread_pool);
    return FAILURE;
}

1 个答案:

答案 0 :(得分:0)

代码正在忙着等待,accept()返回的内容与EAGAIN / EWOULDBLOCK不同,那么还有什么能比你预期的CPU周期更快?

您可以在拨打select()之前拨打accept(),超时10毫秒来解决此问题。