HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Minimal webserver in C++

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
minimalwebserverstackoverflow

Problem

Here's my test question for C++ programmer job:

  • Servers only static content, no cgi



  • Single process, multithreaded



  • 1000 concurrent request at least



  • Valid http status codes and headers



  • No external libraries, just STL, POSIX and glibc



Here's my code:

#include 
#include 
#include 
#include 

#include 
#include 

#include 
#include 
#include 
#include 

using namespace std;

    const char *response_200 = "HTTP/1.1 200 OK\nContent-Type: text/html; charset=utf-8\n\nHello!";
    const char *response_400 = "HTTP/1.1 400 Bad Request\nContent-Type: text/html; charset=utf-8\n\nBad Request!";
    const char *response_404 = "HTTP/1.1 404 Not Found\nContent-Type: text/html; charset=utf-8\n\nNot Found!";

void *handle_request(void *pcliefd) 
{
    int cliefd = *(int*)pcliefd;
    delete (int *)pcliefd;

    ssize_t n;
    char buffer[255];
    const char *response;

    n = recv(cliefd, buffer, sizeof(buffer), 0);
    if(n  token_list;
    for(int i = 0; i > token;
        //printf("token %d %s\n", i, token.c_str());
        token_list.push_back(token);
    } 

    if(token_list.size() == 3 
            && token_list[0] == "GET" 
            && token_list[2].substr(0, 4) == "HTTP") {
        if(token_list[1] == "/index.html") {
            response = response_200;
        } else {
            response = response_404;
        }
    }

    n = write(cliefd, response, strlen(response));
    if(n sin_addr, s, sizeof(s));
        printf("accept() %s\n", s);

        int *pcliefd = new int;
        *pcliefd = cliefd;
        if(true) {
            if(pthread_create(&thread, 0, handle_request, pcliefd) < 0) {
                perror("pthread_create()");
            } 
        } else {
            handle_request(pcliefd);
        }
    }

    return 0;
}

Solution

-
The server announces HTTP 1.1, therefore it must support HTTP 1.1 features, most importantly pipelining (client has a right to send multiple requests over the same socket). In any case, if you chose to close the client socket immediately you should inform client with a Connection: close header.

-
You expect to consume a complete request with a single read. In a streaming world of TCP you never know how many bytes has actually been consumed. You should be prepared to get as little as one byte at a time (same goes for send/write).

A correct way to read the request is to read it in the loop until the end of headers (i.e. an empty string) is seen.

-
Network program must be defensive. A malicious client can play tricks with your server.

For example, it may never send anything; eventually the server would run out of file descriptors (or pthreads), resulting in denial of service. Another client may close the socket immediately upon sending a request; the server receives a SIGPIPE and dies with a core dump.

Context

StackExchange Code Review Q#83632, answer score: 7

Revisions (0)

No revisions yet.