Coder Social home page Coder Social logo

http-server's Introduction

Simple HTTP/1.1 server

Implementation of a simple HTTP server in C++

Features

  • Can handle multiple concurrent connections, tested up to 10k.
  • Support basic HTTP request and response. Provide an extensible framework to implement other HTTP features.
  • HTTP/1.1: Persistent connection is enabled by default.

Quick start

mkdir build && cd build
cmake ..
make
./test_SimpleHttpServer # Run unit tests
./SimpleHttpServer      # Start the HTTP server on port 8080
  • There are two endpoints available at / and /hello.html which are created for demo purpose.
  • In order to have multiple concurrent connections, make sure to raise the resource limit (with ulimit) before running the server. A non-root user by default can have about 1000 file descriptors opened, which corresponds to 1000 active clients.

Design

The server program consists of:

  • 1 main thread for user interaction.
  • 1 listener thread to accept incoming clients.
  • 5 worker threads to process HTTP requests and sends response back to client.
  • Utility functions to parse and manipulate HTTP requests and repsonses conveniently.

Benchmark

I used a tool called wrk to benchmark this HTTP server. The tests were performed on my laptop with the following specs:

Model: Thinkpad T480
OS: Ubuntu 18.04 TLS x84_64
Kernel: 4.18.0-24-generic
CPU: Intel i7-8550 (8) @ 4.000 GHz
GPU: Intel UHD Graphics 620
Memory: 6010 MiB / 15803 MiB

Here are the results for two test runs. Each test ran for 1 minute, with 10 client threads. The first test had only 500 concurrent connections, while the second test had 10000.

$ ./wrk -t10 -c500 -d60s http://0.0.0.0:8080/
Running 1m test @ http://0.0.0.0:8080/
  10 threads and 500 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     5.01ms    1.31ms  57.86ms   86.35%
    Req/Sec     9.94k     0.99k   36.28k    76.69%
  5933266 requests in 1.00m, 441.36MB read
Requests/sec:  98760.82
Transfer/sec:      7.35MB
$ ./wrk -t10 -c10000 -d60s http://0.0.0.0:8080/
Running 1m test @ http://0.0.0.0:8080/
  10 threads and 10000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   111.78ms   21.38ms 403.80ms   76.79%
    Req/Sec     8.73k     1.42k   18.77k    75.62%
  5174508 requests in 1.00m, 384.91MB read
Requests/sec:  86123.84
Transfer/sec:      6.41MB

http-server's People

Contributors

jojo2massol avatar trungams avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

http-server's Issues

Would you let me know which compiler I have to use?

Hi, Thanks for your good work.
I'm really glad to see you and your project.
I have tried to compile this project in Msys to cross-compile.
But there is several errors.
Would you let me know which compiler I have to use?
I'm looking for your reply.
Thanks.
Best regards!!!

to_string fpermissive error

I just got this error while trying to make:
image

In file included from /home/pi/http-server/test/main.cc:10:
/home/pi/http-server/src/http_message.h:150:22: error: friend declaration of ‘std::string to_string(const simple_http_server::HttpResponse&, bool)’ specifies default arguments and isn’t a definition [-fpermissive]
150 | friend std::string to_string(const HttpResponse& request, bool send_content = true);
| ^~~~~~~~~
/home/pi/http-server/src/http_message.h:159:13: error: friend declaration of ‘std::string simple_http_server::to_string(const simple_http_server::HttpResponse&, bool)’ specifies default arguments and isn’t the only declaration [-fpermissive]
159 | std::string to_string(const HttpResponse& response, bool send_content);
| ^~~~~~~~~
/home/pi/http-server/src/http_message.h:150:22: note: previous declaration of ‘std::string simple_http_server::to_string(const simple_http_server::HttpResponse&, bool)’
150 | friend std::string to_string(const HttpResponse& request, bool send_content = true);
| ^~~~~~~~~
make[2]: *** [CMakeFiles/test_SimpleHttpServer.dir/build.make:82: CMakeFiles/test_SimpleHttpServer.dir/test/main.cc.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:97: CMakeFiles/test_SimpleHttpServer.dir/all] Error 2
make: *** [Makefile:103: all] Error 2

3rd argument in memcpy.

Hi, thank you for the great work.

I've encountered a seg fault after registering a new uri. The issue seems to related to memcpy of response_string. I think the 3rd argument should be the size of the response string to be copied instead of kMaxBufferSize, or whichever is smaller.

response_string =
to_string(http_response, http_request.method() != HttpMethod::HEAD);
memcpy(raw_response->buffer, response_string.c_str(), kMaxBufferSize);
raw_response->length = response_string.length();
}

this is a potential fix.

  response_string
      = to_string (http_response, http_request.method () != HttpMethod::HEAD);
  const size_t res_len = response_string.length ();
  size_t len_to_copy = (res_len < kMaxBufferSize) 
    ? res_len : kMaxBufferSize;

  memmove (raw_response->buffer, response_string.c_str (), len_to_copy);
  
  raw_response->buffer[response_string.length ()] = '\0';
  raw_response->length = response_string.length ();

I've forked the project to reproduce my error at this repo.

Server stops sending data when a 0x00 byte is in content

I'm trying to send raw data with the server, but when I have null values in the content, the next bytes are all null. The file size is correct, but I assume it's due to the length header. This is how I did:

    HttpResponse response(HttpStatusCode::Ok);
    // send the framebuffer to the client as an arraybuffer
    response.SetHeader("Content-Type", "arraybuffer");

    const char *framebuffer_ptr = (const char *)framebuffer;
    const std::string framebuffer_str = std::move(std::string(framebuffer_ptr, sizeof(framebuffer)));
    response.SetContent(framebuffer_str);
    
    
    // print framebuffer_str as hex values with 2 digits per byte
    for (uint16_t i = 0; i < sizeof(framebuffer); i++)
    {
      std::cout << std::hex << std::setfill('0') << std::setw(2) << (int)framebuffer[i];
    }
    std::cout << framebuffer_str << std::endl;

The bytes are correctly printing in the console of the program, but on the client, only the first bytes are received:
server cout:

1d de ab 41 cd 26 e6 41 79 0 a4 6f 0 a3 84 0 a3 87 0 a3 35 0 86 46 0 92 6d 0 a3 7c 0 a4 7a 0 a4 7a 0 a4 70 0 a3 
...

client :

1D DE AB 41 CD 26 E6 41 79 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
...

I can't find by myself where the problem is, I know that all these pointers conversions are not the best choice, but since the server is minimal, there is no other type for adding content, and I think there is probably a condition where if the string have a null byte, stop sending data.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.