Refine the draft timeout control from server side.

master
Adam Gu 7 years ago
parent fb37d759a0
commit 919fa54a98

@ -3,8 +3,6 @@
#include <list>
#include "boost/lexical_cast.hpp"
#include "boost/thread.hpp"
#include "boost/date_time/posix_time/posix_time.hpp"
////////////////////////////////////////////////////////////////////////////////
@ -115,10 +113,6 @@ bool BookListService::Handle(const std::string& http_method,
std::string* response_content) {
if (http_method == webcc::kHttpGet) {
*response_content = CreateBookListJson(g_book_store.books());
// Sleep for testing timeout control.
//boost::this_thread::sleep(boost::posix_time::seconds(2));
return true;
}
@ -146,9 +140,6 @@ bool BookDetailService::Handle(const std::string& http_method,
*response_content = CreateBookJson(book);
// Sleep for testing timeout control.
//boost::this_thread::sleep(boost::posix_time::seconds(2));
return true;
} else if (http_method == webcc::kHttpPost) {

@ -27,11 +27,6 @@ int main(int argc, char* argv[]) {
server.RegisterService(std::make_shared<BookDetailService>(),
"/books/(\\d+)");
// For test purpose.
// Timeout like 60s makes more sense in a real product.
// Leave it as default (0) for no timeout control.
server.set_timeout_seconds(1);
server.Run();
} catch (std::exception& e) {

@ -16,8 +16,7 @@ namespace webcc {
HttpServer::HttpServer(unsigned short port, std::size_t workers)
: signals_(io_context_)
, workers_(workers)
, timeout_seconds_(0) {
, workers_(workers) {
// Register to handle the signals that indicate when the server should exit.
// It is safe to register for the same signal multiple times in a program,
@ -78,7 +77,7 @@ void HttpServer::DoAccept() {
HttpSessionPtr session{
new HttpSession(std::move(socket), GetRequestHandler())
};
session->Start(timeout_seconds_);
session->Start();
}
DoAccept();

@ -28,10 +28,6 @@ public:
virtual ~HttpServer();
void set_timeout_seconds(long seconds) {
timeout_seconds_ = seconds;
}
// Run the server's io_service loop.
void Run();
@ -57,10 +53,6 @@ private:
// Acceptor used to listen for incoming connections.
boost::scoped_ptr<boost::asio::ip::tcp::acceptor> acceptor_;
// Timeout in seconds for socket connection.
// Default is 0 which means no timeout.
long timeout_seconds_;
};
} // namespace webcc

@ -22,27 +22,13 @@ HttpSession::HttpSession(boost::asio::ip::tcp::socket socket,
HttpSession::~HttpSession() {
}
void HttpSession::Start(long timeout_seconds) {
if (timeout_seconds > 0) {
// Create timer only necessary.
boost::asio::io_context& ioc = socket_.get_executor().context();
timer_.reset(new boost::asio::deadline_timer(ioc));
timer_->expires_from_now(boost::posix_time::seconds(timeout_seconds));
timer_->async_wait(std::bind(&HttpSession::HandleTimer,
shared_from_this(),
std::placeholders::_1));
}
void HttpSession::Start() {
DoRead();
}
void HttpSession::Stop() {
CancelTimer();
boost::system::error_code ignored_ec;
socket_.close(ignored_ec);
boost::system::error_code ec;
socket_.close(ec);
}
void HttpSession::SetResponseContent(const std::string& content_type,
@ -78,8 +64,6 @@ void HttpSession::HandleRead(boost::system::error_code ec,
if (ec) {
if (ec != boost::asio::error::operation_aborted) {
Stop();
} else {
CancelTimer();
}
return;
}
@ -116,53 +100,25 @@ void HttpSession::HandleWrite(boost::system::error_code ec,
#endif
if (!ec) {
CancelTimer();
#if WEBCC_DEBUG_OUTPUT
std::cout << "Response has been sent back (thread: " << thread_id << ")\n";
#endif
// Initiate graceful connection closure.
boost::system::error_code ec;
socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
#if WEBCC_DEBUG_OUTPUT
std::cout << "Response has been sent back (thread: " << thread_id << ")\n";
#endif
} else {
#if WEBCC_DEBUG_OUTPUT
std::cout << "(thread: " << thread_id << ") Sending response error: "
<< ec.message()
<< std::endl;
<< ec.message()
<< std::endl;
#endif
if (ec == boost::asio::error::operation_aborted) {
CancelTimer();
} else {
if (ec != boost::asio::error::operation_aborted) {
Stop();
}
}
}
void HttpSession::HandleTimer(boost::system::error_code ec) {
std::cout << "HandleTimer: ";
if (!ec) {
if (socket_.is_open()) {
std::cout << "socket is open, close it.\n";
socket_.close();
} else {
std::cout << "socket is not open.\n";
}
} else {
if (ec == boost::asio::error::operation_aborted) {
std::cout << "Timer aborted\n";
}
}
}
void HttpSession::CancelTimer() {
if (timer_) {
// The wait handler will be invoked with the operation_aborted error code.
boost::system::error_code ec;
timer_->cancel(ec);
}
}
} // namespace webcc

@ -5,7 +5,6 @@
#include <memory>
#include "boost/asio/ip/tcp.hpp" // for ip::tcp::socket
#include "boost/asio/deadline_timer.hpp"
#include "webcc/common.h"
#include "webcc/http_request.h"
@ -30,8 +29,7 @@ public:
return request_;
}
// Start the session with an optional timeout.
void Start(long timeout_seconds = 0);
void Start();
void Stop();
@ -54,17 +52,10 @@ private:
void HandleRead(boost::system::error_code ec, std::size_t length);
void HandleWrite(boost::system::error_code ec, std::size_t length);
void HandleTimer(boost::system::error_code ec);
void CancelTimer();
private:
// Socket for the connection.
boost::asio::ip::tcp::socket socket_;
// Timeout timer (optional).
std::unique_ptr<boost::asio::deadline_timer> timer_;
// The handler used to process the incoming request.
HttpRequestHandler* request_handler_;

Loading…
Cancel
Save