代码之家  ›  专栏  ›  技术社区  ›  user142019

使用C的套筒和螺纹

  •  3
  • user142019  · 技术社区  · 16 年前

    我对插座和线都是新手。我有这个代码:

    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 回复  |  直到 16 年前
        1
  •  7
  •   Puppy    16 年前

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

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

        2
  •  6
  •   Maister    16 年前

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

    您将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()同步线程。

        3
  •  0
  •   Darron    16 年前

    VLAD有很好的建议。

    另外请注意,newsocket_fd变量正被重新用于接受循环中的每个新连接,然后一个指向它的指针被传递给每个工作线程。当您同时连接多个客户机时,这将导致问题。

    编辑:忽略这个评论,我误解了你犯的错误。其他人已经对你处理newsocket-fd进行了适当的修正。