从pthread C调用时read()不起作用

时间:2015-04-07 08:56:37

标签: c embedded pthreads client server

我目前正在编写一个C服务器,其目标是使用pthread来处理客户端连接,所有工作完全正常,直到我引入pthreads。我在pthread上解雇了一个客户端,它被创建并运行良好;但是,它将不再从客户端的文件描述符中读取()。

我一直试图解决这个问题大约2个星期了。我已经包含了服务器代码(包括和排除pthreads。)和客户端处理程序代码的代码片段。

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

/*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运行时,它会读取正确的值。我希望有人可以帮忙解决这个问题,因为它让我很困惑。

提前致谢, 安迪

3 个答案:

答案 0 :(得分:0)

只是在线程中关闭客户端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中运行新线程时,循环仍会关闭cliend文件描述符,这就是read()无效的原因

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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);