void serve_forever(int* socket_number, void (*request_handler)(int)) {


  struct sockaddr_in server_address, client_address;

  size_t client_address_length = sizeof(client_address);

  int client_socket_number;


  // Creates a socket for IPv4 and TCP.

  *socket_number = socket(PF_INET, SOCK_STREAM, 0);

  if (*socket_number == -1) {

    perror("Failed to create a new socket");

    exit(errno);

  }


  int socket_option = 1;

  if (setsockopt(*socket_number, SOL_SOCKET, SO_REUSEADDR, &socket_option, sizeof(socket_option)) ==

      -1) {

    perror("Failed to set socket options");

    exit(errno);

  }


  // Setup arguments for bind()

  memset(&server_address, 0, sizeof(server_address));

  server_address.sin_family = AF_INET;

  server_address.sin_addr.s_addr = INADDR_ANY;

  server_address.sin_port = htons(server_port);


  /*

   * TODO: PART 1

   *

   * Given the socket created above, call bind() to give it

   * an address and a port. Then, call listen() with the socket.

   * An appropriate size of the backlog is 1024, though you may

   * play around with this value during performance testing.

   */


  /* PART 1 BEGIN */


  if(bind(*socket_number,(struct sockaddr*)&server_address,sizeof(server_address))==-1)

  {

  	perror("Failed to bind the socket");

	exit(errno);

  }

  if(listen(*socket_number,1024)==-1)

  {

  	perror("Failed to listen to the socket");

	exit(errno);

  }

  /* PART 1 END */

  printf("Listening on port %d...\n", server_port);


#ifdef POOLSERVER

  /*

   * The thread pool is initialized *before* the server

   * begins accepting client connections.

   */

  init_thread_pool(num_threads, request_handler);

#endif


  while (1) {

    client_socket_number = accept(*socket_number, (struct sockaddr*)&client_address,

                                  (socklen_t*)&client_address_length);

    if (client_socket_number < 0) {

      perror("Error accepting socket");

      continue;

    }


    printf("Accepted connection from %s on port %d\n", inet_ntoa(client_address.sin_addr),

           client_address.sin_port);


#ifdef BASICSERVER

    /*

     * This is a single-process, single-threaded HTTP server.

     * When a client connection has been accepted, the main

     * process sends a response to the client. During this

     * time, the server does not listen and accept connections.

     * Only after a response has been sent to the client can

     * the server accept a new connection.

     */

    request_handler(client_socket_number);


#elif FORKSERVER

    /*

     * TODO: PART 5

     *

     * When a client connection has been accepted, a new

     * process is spawned. This child process will send

     * a response to the client. Afterwards, the child

     * process should exit. During this time, the parent

     * process should continue listening and accepting

     * connections.

     */


    /* PART 5 BEGIN */


    /* PART 5 END */


#elif THREADSERVER

    /*

     * TODO: PART 6

     *

     * When a client connection has been accepted, a new

     * thread is created. This thread will send a response

     * to the client. The main thread should continue

     * listening and accepting connections. The main

     * thread will NOT be joining with the new thread.

     */


    /* PART 6 BEGIN */


    /* PART 6 END */

#elif POOLSERVER

    /*

     * TODO: PART 7

     *

     * When a client connection has been accepted, add the

     * client's socket number to the work queue. A thread

     * in the thread pool will send a response to the client.

     */


    /* PART 7 BEGIN */


    /* PART 7 END */

#endif

  }


  shutdown(*socket_number, SHUT_RDWR);

  close(*socket_number);

}
填写part5实现基于Fork的服务器子进程应使用客户端套接字 fd 调用 request_handler。提供响应后，子进程将终止。
父进程将继续监听并接受传入连接。它不会等待子进程。
请记住，父进程和子进程都要适当关闭套接字。