【问题标题】:c - socket failing when passed through pthread_createc - 通过 pthread_create 时套接字失败
【发布时间】:2019-03-18 23:02:41
【问题描述】:

我有一个接受客户端的服务器。我正在做一些多线程,当我创建一个线程时,我将 socketfd 作为参数传递。接受失败,因为它需要的 sockFd 为零。但是我不知道为什么会这样。 sockfd 对 take_client 函数有效,并且已正确设置。我刚刚包含了我的代码的这一部分,因为我确定问题就在这里。

void* thread_func(void* pSockfd) {
    int sockFd;
    sockFd = *(int*)pSockfd;
    printf("sockFD = %d\n", sockFd); //returns zero
    struct sockaddr_in sockAddr;
    socklen_t sockAddrSize;

    sockAddrSize = sizeof(struct sockaddr_in);
    accept(sockFd, (struct sockaddr*) &sockAddr, &sockAddrSize);

return 0;
}

void take_client(int sock) { //when called, 'sock' is a valid number > 0
    pthread_t thread_id;
    pthread_create(&thread_id, NULL, thread_func, (void*)&sock);
}

如果有什么突出的可能是一个问题,我将非常感激听到。谢谢!

【问题讨论】:

  • 0 对于文件描述符来说是完全可以的(即使在这里,它可能不是你需要的 fd 值)
  • stackoverflow.com/q/52712559/694576 不完全相同,但实际上是同样的问题。

标签: c multithreading sockets networking pthreads


【解决方案1】:

您的代码中存在竞争条件,“有时”可能看起来不错:

void take_client(int sock) { //sock live on stack here
    pthread_t thread_id;
    pthread_create(&thread_id, NULL, thread_func, (void*)&sock);
    // you pass the stack address of sock to your thread
}

您传递的地址在线程运行时必须保持有效,因此您可以负担得起(它在某处有点“全局”),或者您需要分配一个新缓冲区并将其传递给线程。

有时您会看到代码将 sock 值转换为 void* ( (void*)sock) 并将指针转换回线程中的 int。

这可能行得通,但我认为分配一个新缓冲区对可读性更好,并且明确负责该缓冲区的所有权(在线程之间共享“sock”需要锁定才能完全安全)。

此外,通常,您最终需要将更多信息传递给线程,因此已经有了一个缓冲区来简化代码的演变。

【讨论】:

  • 谢谢,这绝对是我会研究的。
【解决方案2】:

查看手册页以获取套接字返回值:“成功时,返回新套接字的文件描述符。出错时,返回 -1,并正确设置 errno。”所以零返回值是有效的。除非我不明白你的问题。

【讨论】:

  • 虽然正确,但这可能无法回答问题。
猜你喜欢
  • 2012-08-25
  • 1970-01-01
  • 2012-06-07
  • 2017-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多