From CS61
Jump to: navigation, search

Building Network Servers

Let's see how our abstractions hold up when we go outside the boundary of a single computer.

Learning Objectives

  • Modify an existing server to efficiently handle multiple connections
  • Apply what we learned about synchronization to manage our server

Get the Code

We're working in the l25 directory of the cs61-exercises directory.

Putting our server under load

When we left our serviceserver (form the video), we used serviceserver-02, which looped handling a single request at a time. Real servers need to handle many simultaneous requests. Our work today will walk us through some different approaches to handling multiple connections simultaneously.

The serviceserver.c file in the l25 directory is the version that handles one connection at a time. Run it and put it in the background. Then fire up the serviceblaster program. Notice how slowly connections are handled. Kill the blaster and then kill the server you have running in the background.

A Process per Connection

One way we might handle multiple simultaneous connections would be to have the main server thread repeatedly listen on the accepting socket, but then fork off a child thread to handle each request.

Copy the serviceserver.c file into serviceserver-process.c. Make the following changes to that file (and add serviceserver-process to the Makefile on the SERVER_PROGRAMS line).

First, we want the server to automatically reap the child processes that it's going to spawn, so add the line:

   signal(SIGCHLD, SIG_IGN);

at the beginning of main.

Now, rather than calling handle_connection in your main server, modify the code to fork a new child that runs only as long as it takes to handle the connection (i.e, it should exit after it processes the connection message). When that's working, try running the serviceblaster client against that server.

1. How does its behavior compare to the original serviceserver?

A Thread per Connection

OK, so a process per connection is too resource intensive. What about threads! After all, we did just learn how to use pthreads. Let's give it a try! Rather than forking off a process per connection, let's just fork off a thread and handle the request. Implement this in a field called serviceserver-thread.c

2. What happens?

Thread Pools (1)

One way we limit resource usage is to limit the number of concurrent threads we have active at any time. Use what you've learned about synchronization to impose a limit on the total number of threads the server might have active simultaneously. Don't change your overall structure though -- create a new thread when you can and have a thread exit after it handles a request. Name this version of the server serviceserver-pool.c.

3. How well does that perform?

Wrapping Up

Please take a minute to fill out this survey.