【问题标题】:read() not working when called from a pthread C从 pthread C 调用时 read() 不起作用
【发布时间】:2015-06-11 19:33:34
【问题描述】:

我目前正在编写一个 C 服务器,其目标是使用 pthreads 来处理客户端连接,在我引入 pthreads 之前,一切都可以正常工作。我在 pthread 上启动了一个客户端,它被创建并运行良好;但是,它将不再从客户端的文件描述符中“读取()”。

我已经尝试解决这个问题大约 2 周了。我已经包含了服务器代码(包括和不包括 pthread)和客户端处理程序代码的代码 sn-ps。

这是我的主服务器循环(pthread):

/*Sets up and runs the server. (MAX 10 CLIENTS)*/
void publicServer(void)
{
    //Server locals
    int serverSocket_fd;
    int clientSocket_fd;
    socklen_t serverLength;
    socklen_t clientLength;
    struct sockaddr_in serverAddress;
    struct sockaddr_in clientAddress;

    //Threading locals
    pthread_t threadPool[20];   //Pool of threads, used in a FIFO fashion.
    int threadPointer = 0;      //Points to the location of the next available thread.

    //Clear old sockets
    puts("Unlinking server socket");
    unlink("server_socket");

    //Setup server socket
    printf("Setting server socket properties..\n");
    serverSocket_fd                 = socket(AF_INET, SOCK_STREAM, 0);
    serverAddress.sin_family        = AF_INET;
    serverAddress.sin_addr.s_addr   = htonl(INADDR_ANY);
    serverAddress.sin_port          = htons(5000);
    serverLength = sizeof(serverAddress);

    //Bind the socket
    printf("Binding socket\n");
    bind(serverSocket_fd, (struct sockaddr*)&serverAddress, serverLength);

    //Create listener
    listen(serverSocket_fd, 20);

    //Main server loop
    printf("Entering main loop\n");
    while (1)
    {
        clientLength = sizeof(clientAddress);

        //Accept connection
        printf("Blocking for connection\n");
        clientSocket_fd = accept(serverSocket_fd, (struct sockaddr*)&clientAddress, &clientLength);

        //Handle Client
        pthread_create(&threadPool[0], NULL, clientHandler, clientSocket_fd);

        //Increment thread pointer
        threadPointer++;
        if (threadPointer == 20)
        {
            threadPointer = 0;
        }

        //End client
        close(clientSocket_fd);
    }
}

这是没有 pthreads 的服务器代码(工作正常。):

/*Sets up and runs the server. (MAX 10 CLIENTS)*/
void publicServer(void)
{
    //Server locals
    int serverSocket_fd;
    int clientSocket_fd;
    socklen_t serverLength;
    socklen_t clientLength;
    struct sockaddr_in serverAddress;
    struct sockaddr_in clientAddress;

    //Clear old sockets
    puts("Unlinking server socket");
    unlink("server_socket");

    //Setup server socket
    printf("Setting server socket properties..\n");
    serverSocket_fd                 = socket(AF_INET, SOCK_STREAM, 0);
    serverAddress.sin_family        = AF_INET;
    serverAddress.sin_addr.s_addr   = htonl(INADDR_ANY);
    serverAddress.sin_port          = htons(5000);
    serverLength = sizeof(serverAddress);

    //Bind the socket
    printf("Binding socket\n");
    bind(serverSocket_fd, (struct sockaddr*)&serverAddress, serverLength);

    //Create listener
    listen(serverSocket_fd, 20);

    //Main server loop
    printf("Entering main loop\n");
    while (1)
    {
        clientLength = sizeof(clientAddress);

        //Accept connection
        printf("Blocking for connection\n");
        clientSocket_fd = accept(serverSocket_fd, (struct sockaddr*)&clientAddress, &clientLength);

        //Handle Client
        clientHandler(clientSocket_fd);

        //End client
        close(clientSocket_fd);
    }
}

这是客户端处理程序代码:

/*
 * Handles the client's request.
 * <int : client_fd> Client's file descriptor.
 */
void *clientHandler(int client_fd)
{
    char request = ' ';

    puts("Waiting for request");
    read(client_fd, &request, 1);

    //Determine what to do for user
    if (request == '1')                 //Output current temp and pressure
    {
        outputCurrentTemperaturePressure(client_fd);
    }
    else if (request == '2')            //Begin regular sampling of temp and pressure
    {
        startSampling();
    }
    else if (request == '3')            //Stop regular sampling of temp and pressure
    {
        stopSampling();
    }
    else if (request == '4')            //Clear the EEPROM
    {
        eraseEEPROM();
    }
    else if (request == '5')            //Retrieve all stored temperature and pressure values
    {
        outputSavedTempPressValues(client_fd);
    }
    else if (request == '6')            //Retrieve a certain number of temperature and pressure values
    {
        outputLastNTempPressValues(client_fd);
    }
    else if (request == '7')            //Output current noise level
    {
        outputCurrentNoiseLevel(client_fd);
    }

    close(client_fd);
    pthread_exit(1);
}

当我尝试从客户端读取数据时,问题出在 clientHandler 方法中的第 6 行。当在 pthread 上运行时,它一直读取 0。但是,当没有 pthreads 运行时,它会读取正确的值。我希望有人能帮忙解决这个问题,因为这真的让我很困惑。

提前致谢, 安迪

【问题讨论】:

    标签: c embedded pthreads client server


    【解决方案1】:

    据我所知,pthread 入口点必须有一个 void * 参数。您定义 clientHandler 的方式似乎是错误的。读这个: http://timmurphy.org/2010/05/04/pthreads-in-c-a-minimal-working-example/ .

    【讨论】:

      【解决方案2】:
      int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                            void *(*start_routine) (void *), void *arg);
      
      
      pthread_create(&threadPool[0], NULL, clientHandler, (void*)&clientSocket_fd);
      
      void *clientHandler(void *args) {
      int client_fd = *((int*) args);
      

      【讨论】:

        【解决方案3】:

        只关闭线程中的客户端socket_fd,而不是主函数

        while (1)
        {
            clientLength = sizeof(clientAddress);
        
            //Accept connection
            printf("Blocking for connection\n");
            clientSocket_fd = accept(serverSocket_fd, (struct sockaddr*)&clientAddress, &clientLength);
        
            //Handle Client
            pthread_create(&threadPool[0], NULL, clientHandler, clientSocket_fd);
        
            //Increment thread pointer
            threadPointer++;
            if (threadPointer == 20)
            {
                threadPointer = 0;
            }
        
            //End client
            /* remove close(clientSocket_fd) from here */
        }
        

        当你在 while 中运行新线程时,循环仍然关闭客户端文件描述符,这就是 read() 不起作用的原因

        【讨论】:

        • 这解决了 read() 的问题,所以谢谢你!但是现在我遇到了很多等待的 pthreads。我必须想办法阻止服务器循环。
        猜你喜欢
        • 1970-01-01
        • 2016-09-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多