qwer is a funcional network library with little web support.
Http server
//! @brief multi thread server
int deamon_1() {
// set log
LOG_SET_FILE_P("./tmp_log.txt", false);
LOG_SET_LEVEL("DEBUG");
LOG_DEBUG(" \n \n in test_multithread");
//
// set http api
shared_ptr<HttpResponse> x_http_response(new HttpResponse());
x_http_response->version_ = HttpMsg::HttpVersion ::Http1_1;
x_http_response->statuscode_ = HttpMsg::HttpStatusCodes::c_200;
x_http_response->headers_lines_[0] = make_pair("Connection", " close");
x_http_response->body_ = string("<html><body>") +
string("<h1>Hello, World!</h1>") +
string("</body></html>") ; //!< you can also use FileReader("filename").to_string();
shared_ptr<HttpSetting> httpsettings(new HttpSetting());
HttpServer<MultiServer> httpserver(100,
Ipv4Addr(Ipv4Addr::host2ip_str("localhost"), 8080),
httpsettings);
httpsettings->cash_response_of("GET", "/hello.html", move(x_http_response))
.set_action_of("GET", "/hello.html", [&httpserver]
(TCPConnection& this_con, shared_ptr<HttpRequest> req, shared_ptr<HttpResponse> res){ //!< you don't need to modify this res, because res is cashed, (effective consider)
//! you can add your header handler and filters here like Nginx provide
// your_header_handler(req->headers_lines_);
this_con.to_lazy_close(); //!< close this connection after write the content, because your response headers_lines_[0]
});
// serve and block until functor return true;
cout << "begin server" << endl;
httpserver.Start([](){
std::this_thread::sleep_for(10000ms); //!< sleep of this command thread won't affect threads in pool
return true;
});
cout << "end of server" << endl;
httpserver.Exit();
}
int main() { return deamon_1(); }
- supporting single thread and multithread
- supporting http server.
-
compile:
cd ./qwer/qwer_main mkdir ./bin cd ./bin ../runme_instead_of_cmake.sh // or cmake .. make && make check // or ctest -V
-
add dependency in your CMakeLists.txt easily:
add_subdirectoryy(${QWER_LIBRARY_ROOT})
include_directories(${QWER_INCLUDES})
- using wrk to benchmark "real_example_using_this":
using common TCP 4 hands close, which would cause too many socket TIME_WAIT
Running 30s test @ http://127.0.0.1:8080/hello.html
2 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 10.23ms 19.15ms 435.35ms 98.98%
Req/Sec 3.67k 2.77k 8.17k 51.95%
28798 requests in 30.04s, 2.42MB read
Socket errors: connect 265, read 28798, write 0, timeout 0
Requests/sec: 958.50
Transfer/sec: 82.37KB
if you compile with SO_LINGER or some way avoid '4 hands close' like tell wrk 'Keep-Alive' and close socket on your back, socket would end up with RST and rise the QPS
Running 30s test @ http://127.0.0.1:8080/hello.html
1 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 55.11us 168.17us 8.66ms 97.96%
Req/Sec 14.73k 3.62k 20.46k 64.76%
332716 requests in 30.01s, 35.86MB read
Socket errors: connect 0, read 332717, write 7, timeout 0
Requests/sec: 11086.55
Transfer/sec: 1.19MB
-
http :
-
web framework:
-
other :
- one reactor per thread(one event-loop per thread)
- thread pool with main thread to accept connection, and other thread to handle connections
- TCP for IPC
- message format : json or google protocol buffers
- thread safe queue for thread communication and data passing
-
network library :
- libevent --> reactor
- asio boostc++11 example --> proactor
- muduo github
- handy github
- Proactor
- Design.Pattern-orented software architecture Vol2
- JAWS p35
- Reactor p154
- ZMQ ref what you should know about, when implement a error sensitive project with cpp
- gtest error : recipe for target 'test' failed; type make test in /bin
- vim-instant-markdown : install nodejs-legacy fail
- make logging cpp stream style
- running time logging level set
- git third party, gtest
- try something about corutine, about microservices-architecture : WON'tref
- can I create a object in one thread and use it in another thread? Yes, of course. ref
- try something about reflection
- [] wrap http_parser into a class to use
- [] loging page ref ref
- cmake config.h, is generated one by cmake:configure_file()