【问题标题】:C - server client multithreaded pthread_create failingC - 服务器客户端多线程 pthread_create 失败
【发布时间】:2013-10-24 10:09:50
【问题描述】:

我正在编写一个多线程服务器,但我如何尝试调试它,但由于某种原因,它实际上并没有进入由 pthread_create() 调用的客户端线程,主线程的底部。知道为什么 pthread_create() 失败了吗?

我还想知道将结构发送到客户端然后客户端将结构发送回服务器作为服务器和客户端之间的主要通信是否是个好主意?或者 send() 和 recv() 应该是更好的实现方式吗?

int main(int argc, char* argv[])
{
    int fdServer;
    int accept_fd;
    int optVal = 1;
    struct sockaddr_in fromAddr;
    struct sockaddr_in serverAddr;
    struct pollfd* pServerPollFd;
    pthread_t threadId;
    socklen_t fromAddrSize;

    /*
     * Check user input and assign values
     */
    if(argc != 4)
        errorServer(WRONG_CLI);
    char* greeting = calloc(100,sizeof(char*));
    char* file_name = calloc(100,sizeof(char*));
    greeting = argv[2];
    file_name = argv[3];

    /*
     * Check pthread_key_create != 0 -> ERROR
     */
    if(pthread_key_create(&threadSpecificKey, dataDestructor))
        errorServer(SYSTEM_ERROR);
    int port_num = atoi(argv[1]);
    if(!((port_num <= 65535)&&(1<=port_num)))
        errorServer(INVALID_PORT);

    /*
     * Set up the server socket
     */
    fdServer = socket(AF_INET, SOCK_STREAM, 0);
    if(fdServer < 0)
        errorServer(SYSTEM_ERROR);
    if(setsockopt(fdServer, SOL_SOCKET, SO_REUSEADDR, &optVal, sizeof(int)) < 0)
        errorServer(SYSTEM_ERROR);
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(port_num);
    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    if(bind(fdServer, (struct sockaddr*)&serverAddr, sizeof(struct sockaddr_in)) < 0)
        errorServer(PORT_ERROR);

    /*
     * Setup poll pool
     */
    pMessageBuffer = fifo_buffer_create(-1);
    poll_pool* pPool = poll_pool_create(MAX_CONNECTIONS + 1);
    pServerPollFd = poll_pool_allocate(pPool, fdServer);
    pServerPollFd->events |= POLLIN;
    int flags = fcntl(fdServer, F_GETFL);// Get the file access mode and the file status flags;
    if(fcntl(fdServer, F_SETFL, flags | O_NONBLOCK) == -1)// Set the file descriptor flags to the value specified by 3rd arg.
            errorServer(SYSTEM_ERROR);
    if(listen(fdServer, 4) != 0)//Allow only 4 connections to the server
            errorServer(SYSTEM_ERROR);




    while(1) {

            fromAddrSize = sizeof(struct sockaddr_in);
        /* Block, waiting for a connection request to come in and accept it.
         * fromAddr structure will get populated with the address of the client
         */
            while((accept_fd = accept(fdServer, (struct sockaddr*)&fromAddr,  &fromAddrSize)) != -1){
                printf("Someone connected \n");

            client_connection *pClientConnection = client_connection_create(accept_fd);
            client_details *pClientDetails = client_details_create();
            client_session *pClientSession = client_session_create(pClientConnection,pClientDetails);

            pthread_mutex_lock(&game_state_mutex);
            //SEARCH THE LINKEDLIST FOR THE GAME NAME - IF FALSE CREATE NEW LINKED ELEMENT
            C_lst requestedGame;
            clst_init(&requestedGame,NULL);
            clst_insert_next(&requestedGame,NULL,pClientSession);

            pthread_mutex_unlock(&game_state_mutex);
            write(accept_fd, greeting, strlen(greeting));



        /* Start a thread to deal with client communication - pass the
         * connected file descriptor as the last argument.
         */
            pthread_create(&threadId, NULL, client_thread, (void*)pClientSession);
            pthread_detach(threadId);
            }

    }
    free(greeting);
    free(file_name);
    return 0;
}

这是client_thread的开始

void * client_thread(void* arg)
    {
    ssize_t numBytesRead;
    char buffer[MAXBUFFER];
    client_session* pClientSession = (client_session*)arg;

    if(pthread_setspecific(threadSpecificKey, pClientSession))
        errorServer(SYSTEM_ERROR);
/* below read fails because of the nonblocking fdServer from fnctl*/
 while((numBytesRead = read(fd,buffer,MAXBUFFER))>0){ 
    //loop code here
   }

【问题讨论】:

  • 如果没有任何内容要读取,非阻塞读取将因 EAGAIN 失败。你必须妥善处理这种情况。

标签: c multithreading client-server


【解决方案1】:

为什么你没有检查 pthread_create 返回值并且没有打印相应的错误信息?

s = pthread_create(...);
if (s != 0) {
    errno = s;
    perror("pthread_create");
    exit(EXIT_FAILURE);
}

来源:pthread_create(3)

UPD。此外,对于套接字设置,您可以尝试 getaddrinfo(3) 而不是手动操作:http://www.beej.us/guide/bgnet/output/html/multipage/syscalls.html#getaddrinfo

UPD 2.“发送结构”是什么意思?

【讨论】:

  • 我已经打印出来了,它是一个零,这意味着它执行得很好。这真的很奇怪!
  • @MarkNicolle,所以,现在您知道问题不在于 pthread_create。检查其他系统功能怎么样?
  • 是的,我只是看到我认为问题出在 fdServer 上,它设置为非阻塞,但是在我的 clent_thread(并且它一直在执行)中使用读取,因此 client_thread 中的 while 循环失败为它不是从 read 中读取任何内容。并完成线程。我会更新 client_thread 但我认为我可能需要使用 poll 或 select,对吗??
  • @MarkNicolle - 为什么在每个客户端一个线程的服务器中将套接字设置为非阻塞?
  • @MartinJames 我最初的想法是将来自多个客户端的消息排队。我想错了吗?
猜你喜欢
  • 2019-05-17
  • 2015-01-09
  • 2019-04-18
  • 2014-12-21
  • 2011-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-10
相关资源
最近更新 更多