使用C的套接字和线程

时间:2010-09-15 15:53:29

标签: c multithreading sockets asynchronous posix

我是套接字和线程的新手。我有这段代码:

listen(socket_fd, 20);

/* Looooop */
  while (1) {
    newsocket_fd = accept(socket_fd, 
                          (struct sockaddr *) &client_addr, 
                          &client_len);
    if (newsocket_fd < 0) {
      error("ERROR on accept");
    }
    pthread_t thread;
    pthread_create(&thread, NULL, run_thread, (void *) newsocket_fd);
    pthread_join(thread, NULL);
  }

如何为每个新连接启动新线程,而不是为每个请求启动?当新连接进入时,应该启动这些线程,然后这些线程应该等待请求,处理这些请求,最后在关闭连接时返回。 每个连接都应该有一个帖子。以下是run_thread的代码:

void
*run_thread(void *ptr) {
  char buffer[256];
  bzero(buffer, 256);
  int n;
  n = read((int) ptr, buffer, 255);
  if (n < 0) error("ERROR Reading from socket");
  printf("%s\n\n**********\n\n", buffer);

  /* Parse buffer and return result */
  char *result;
  {
    /* First, determine command, 4 characters */
    /* (much code) */
  }

  n = write((int) ptr, result, strlen(result));
  if (n < 0) error("ERROR Writing to socket");
}

任何人都可以帮助我吗?感谢。

3 个答案:

答案 0 :(得分:7)

你几乎做对了。但问题是,您在创建后立即加入了线程,pthread_join实际上是一个阻塞调用,它等待线程完成。这意味着当一个线程正在运行时,您将无法再接受任何连接。要解决此问题,您可能希望使用分离的线程。您不必加入分离的线程。为此,您必须使用pthread_attr_init函数创建线程属性,并将这些属性传递给pthread_create

请注意,如果您的客户端连接太多,您的应用程序可能会耗尽资源。因此,在现实世界中,您必须管理一个线程池。但TCP / IP服务器应用程序的最佳情况是使用asynchronous I/O。我不知道C,但C ++中有一个非常好的用于异步I / O应用程序的库boost::asio

答案 1 :(得分:6)

还有一个不同的严重错误。

将int转换为(void *)。这根本不符合逻辑。此外,您无法直接传递地址,因为在线程可以将变量复制到其本地堆栈之前,可以在下一个accept()调用中更改变量。写它的一种方法是这样的:

while (1) {
    newsocket_fd = accept(socket_fd, 
                          (struct sockaddr *) &client_addr, 
                          &client_len);
    if (newsocket_fd < 0) {
      error("ERROR on accept");
    }
    pthread_t thread;
    int *newsock = malloc(sizeof(int));
    *newsock = newsocket_fd;
    pthread_create(&thread, NULL, run_thread, newsock);
    pthread_detach(thread);
  }

通过这种方法,线程将确保释放()newsock。例如,一个简单的

void *handler(void *thread_data) {
   int fd = *(int *) thread_data;
   free(thread_data);
   ....
}

另外,我假设pthread_detach()没问题,如果主程序不关心稍后使用pthread_join()与线程同步。

答案 2 :(得分:0)

弗拉德有很好的建议。

另请注意,您的newsocket_fd变量正在为accept循环中的每个新连接重用,然后将指向它的指针传递给每个工作线程。当您开始同时连接多个客户端时,这将导致问题。

编辑:忽略这个评论,我误解了你所犯的错误。其他人对你处理newsocket_fd进行了适当的更正。