Improve transmission efficiency

This commit is contained in:
antao 2018-12-30 22:18:20 +08:00
parent ed70959fe5
commit f58d73991f
5 changed files with 52 additions and 51 deletions

View File

@ -20,6 +20,7 @@
#include <trantor/utils/Logger.h> #include <trantor/utils/Logger.h>
#include <stdio.h> #include <stdio.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <memory>
using namespace trantor; using namespace trantor;
using namespace drogon; using namespace drogon;
@ -307,13 +308,14 @@ std::string HttpResponseImpl::web_response_code_to_string(int code)
return "Undefined Error"; return "Undefined Error";
} }
} }
void HttpResponseImpl::makeHeaderString(MsgBuffer *output) const void HttpResponseImpl::makeHeaderString(const std::shared_ptr<std::string> &headerStringPtr) const
{ {
char buf[64]; char buf[64];
assert(headerStringPtr);
snprintf(buf, sizeof buf, "HTTP/1.1 %d ", _statusCode); snprintf(buf, sizeof buf, "HTTP/1.1 %d ", _statusCode);
output->append(buf); headerStringPtr->append(buf);
output->append(_statusMessage); headerStringPtr->append(_statusMessage);
output->append("\r\n"); headerStringPtr->append("\r\n");
if (_sendfileName.empty()) if (_sendfileName.empty())
{ {
snprintf(buf, sizeof buf, "Content-Length: %lu\r\n", static_cast<long unsigned int>(_bodyPtr->size())); snprintf(buf, sizeof buf, "Content-Length: %lu\r\n", static_cast<long unsigned int>(_bodyPtr->size()));
@ -329,12 +331,12 @@ void HttpResponseImpl::makeHeaderString(MsgBuffer *output) const
snprintf(buf, sizeof buf, "Content-Length: %llu\r\n", static_cast<long long unsigned int>(filestat.st_size)); snprintf(buf, sizeof buf, "Content-Length: %llu\r\n", static_cast<long long unsigned int>(filestat.st_size));
} }
output->append(buf); headerStringPtr->append(buf);
if (_headers.find("Connection") == _headers.end()) if (_headers.find("Connection") == _headers.end())
{ {
if (_closeConnection) if (_closeConnection)
{ {
output->append("Connection: close\r\n"); headerStringPtr->append("Connection: close\r\n");
} }
else else
{ {
@ -347,18 +349,18 @@ void HttpResponseImpl::makeHeaderString(MsgBuffer *output) const
it != _headers.end(); it != _headers.end();
++it) ++it)
{ {
output->append(it->first); headerStringPtr->append(it->first);
output->append(": "); headerStringPtr->append(": ");
output->append(it->second); headerStringPtr->append(it->second);
output->append("\r\n"); headerStringPtr->append("\r\n");
} }
output->append("Server: drogon/"); headerStringPtr->append("Server: drogon/");
output->append(drogon::getVersion()); headerStringPtr->append(drogon::getVersion());
output->append("\r\n"); headerStringPtr->append("\r\n");
} }
void HttpResponseImpl::appendToBuffer(MsgBuffer *output) const std::shared_ptr<std::string> HttpResponseImpl::renderToString() const
{ {
if (_expriedTime >= 0) if (_expriedTime >= 0)
{ {
@ -366,24 +368,25 @@ void HttpResponseImpl::appendToBuffer(MsgBuffer *output) const
{ {
bool isDateChanged = false; bool isDateChanged = false;
auto newDate = getHttpFullDate(trantor::Date::now(), &isDateChanged); auto newDate = getHttpFullDate(trantor::Date::now(), &isDateChanged);
{ {
std::lock_guard<std::mutex> lock(*_httpStringMutex); std::lock_guard<std::mutex> lock(*_httpStringMutex);
if (isDateChanged) if (isDateChanged)
{ {
_httpString = std::make_shared<std::string>(*_httpString);
memcpy(_httpString->data() + _datePos, newDate, strlen(newDate)); memcpy(_httpString->data() + _datePos, newDate, strlen(newDate));
} }
output->append(*_httpString);
} }
return; return _httpString;
} }
} }
auto httpString = std::make_shared<std::string>();
if (!_fullHeaderString) if (!_fullHeaderString)
{ {
makeHeaderString(output); makeHeaderString(httpString);
} }
else else
{ {
output->append(*_fullHeaderString); httpString->append(*_fullHeaderString);
} }
//output cookies //output cookies
@ -392,22 +395,23 @@ void HttpResponseImpl::appendToBuffer(MsgBuffer *output) const
for (auto it = _cookies.begin(); it != _cookies.end(); it++) for (auto it = _cookies.begin(); it != _cookies.end(); it++)
{ {
output->append(it->second.cookieString()); httpString->append(it->second.cookieString());
} }
} }
//output Date header //output Date header
output->append("Date: "); httpString->append("Date: ");
auto datePos = output->readableBytes(); auto datePos = httpString->length();
output->append(getHttpFullDate(trantor::Date::date())); httpString->append(getHttpFullDate(trantor::Date::date()));
output->append("\r\n\r\n"); httpString->append("\r\n\r\n");
LOG_TRACE << "reponse(no body):" << output->peek(); LOG_TRACE << "reponse(no body):" << httpString->c_str();
output->append(*_bodyPtr); httpString->append(*_bodyPtr);
if (_expriedTime >= 0) if (_expriedTime >= 0)
{ {
std::lock_guard<std::mutex> lock(*_httpStringMutex); std::lock_guard<std::mutex> lock(*_httpStringMutex);
_datePos = datePos; _datePos = datePos;
_httpString = std::make_shared<std::string>(output->peek(), output->readableBytes()); _httpString = httpString;
} }
return httpString;
} }

View File

@ -207,7 +207,7 @@ class HttpResponseImpl : public HttpResponse
{ {
_headers["Location"] = url; _headers["Location"] = url;
} }
void appendToBuffer(MsgBuffer *output) const; std::shared_ptr<std::string> renderToString() const;
virtual void clear() override virtual void clear() override
{ {
@ -292,9 +292,8 @@ class HttpResponseImpl : public HttpResponse
} }
void makeHeaderString() void makeHeaderString()
{ {
trantor::MsgBuffer buf; _fullHeaderString = std::make_shared<std::string>();
makeHeaderString(&buf); makeHeaderString(_fullHeaderString);
_fullHeaderString = std::make_shared<std::string>(buf.peek(), buf.readableBytes());
} }
protected: protected:
@ -304,7 +303,7 @@ class HttpResponseImpl : public HttpResponse
static std::string web_response_code_to_string(int code); static std::string web_response_code_to_string(int code);
void makeHeaderString(MsgBuffer *output) const; void makeHeaderString(const std::shared_ptr<std::string> &headerStringPtr) const;
private: private:
std::map<std::string, std::string> _headers; std::map<std::string, std::string> _headers;

View File

@ -120,15 +120,16 @@ void HttpServer::onMessage(const TcpConnectionPtr &conn,
if (context->firstReq() && isWebSocket(conn, context->request())) if (context->firstReq() && isWebSocket(conn, context->request()))
{ {
auto wsConn = std::make_shared<WebSocketConnectionImpl>(conn); auto wsConn = std::make_shared<WebSocketConnectionImpl>(conn);
newWebsocketCallback_(context->request(), [=](const HttpResponsePtr &resp) mutable { newWebsocketCallback_(context->request(),
if (resp->statusCode() == HttpResponse::k101SwitchingProtocols) [=](const HttpResponsePtr &resp) mutable {
{ if (resp->statusCode() == HttpResponse::k101SwitchingProtocols)
context->setWebsockConnection(wsConn); {
} context->setWebsockConnection(wsConn);
MsgBuffer buffer; }
std::dynamic_pointer_cast<HttpResponseImpl>(resp)->appendToBuffer(&buffer); MsgBuffer buffer;
conn->send(std::move(buffer)); auto httpString = std::dynamic_pointer_cast<HttpResponseImpl>(resp)->renderToString();
}, conn->send(httpString);
},
wsConn); wsConn);
} }
else else
@ -252,8 +253,8 @@ void HttpServer::sendResponse(const TcpConnectionPtr &conn,
const HttpResponsePtr &response) const HttpResponsePtr &response)
{ {
MsgBuffer buf; MsgBuffer buf;
std::dynamic_pointer_cast<HttpResponseImpl>(response)->appendToBuffer(&buf); auto httpString = std::dynamic_pointer_cast<HttpResponseImpl>(response)->renderToString();
conn->send(std::move(buf)); conn->send(httpString);
auto &sendfileName = std::dynamic_pointer_cast<HttpResponseImpl>(response)->sendfileName(); auto &sendfileName = std::dynamic_pointer_cast<HttpResponseImpl>(response)->sendfileName();
if (!sendfileName.empty()) if (!sendfileName.empty())
{ {

View File

@ -129,10 +129,8 @@ bool HttpServerContext::parseRequest(MsgBuffer *buf)
{ {
auto resp = HttpResponse::newHttpResponse(); auto resp = HttpResponse::newHttpResponse();
resp->setStatusCode(HttpResponse::k100Continue); resp->setStatusCode(HttpResponse::k100Continue);
MsgBuffer buffer; auto httpString = std::dynamic_pointer_cast<HttpResponseImpl>(resp)->renderToString();
std::dynamic_pointer_cast<HttpResponseImpl>(resp) connPtr->send(httpString);
->appendToBuffer(&buffer);
connPtr->send(std::move(buffer));
} }
} }
else if (!expect.empty()) else if (!expect.empty())
@ -144,9 +142,8 @@ bool HttpServerContext::parseRequest(MsgBuffer *buf)
auto resp = HttpResponse::newHttpResponse(); auto resp = HttpResponse::newHttpResponse();
resp->setStatusCode(HttpResponse::k417ExpectationFailed); resp->setStatusCode(HttpResponse::k417ExpectationFailed);
MsgBuffer buffer; MsgBuffer buffer;
std::dynamic_pointer_cast<HttpResponseImpl>(resp) auto httpString = std::dynamic_pointer_cast<HttpResponseImpl>(resp)->renderToString();
->appendToBuffer(&buffer); connPtr->send(httpString);
connPtr->send(std::move(buffer));
buf->retrieveAll(); buf->retrieveAll();
connPtr->forceClose(); connPtr->forceClose();

@ -1 +1 @@
Subproject commit 088af9a4d5351d7e027894836c3f93ff2b7191f5 Subproject commit 69f6ece8d83b251842d633aa7a2fb3a6bd6ba2e5