Error[8]: Undefined offset: 6398, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

文章目录


前引

目前性能还是有一些差距 我初步揣测
是不是由于我httpserver的分析函数 是完全按照我的思路写的
但是比muduo库更为复杂 处理就更细致一点 而且也引入了多个参数…
我觉得是这个原因

主要是性能差距也没有那么大… 而且确实
我是先判断是否存在一行 对每个字符判断
个人觉得判断函数写的也不是那么好 用std::search应该感觉效果好一些

但是主要 我觉得这个地方 状态机 用一个checked_index 判断过的字符就可以不用判断了 但是其实 如果用webbench来判断的话 其实这个过程肯定是没有必要的… 因为发送的情况不会出现的 每次只发送一两个字节的情况

后面再改改 看看性能会不会提升到和muduo库持平 之后大概率要改用ET工作模式
现在性能差距相比之前已经相对来说很小了 下面给张截图吧
明天再来改改了



(九)— 目前总览代码如下 得继续脚步前行

当然代码还在持续迭代
之后可能还要重构一下http分析函数 让他更简单一点


1、主要核心部分代码
1、main.cc
#include 

#include 
#include 

#include "eventloop.h"
#include "address.h"
#include "httpserver.h"
#include "httprequest.h"
#include "httpresponse.h"

#include "httpresponsefile.h"

using namespace tiny_muduo;

using tiny_muduo::Method;
using tiny_muduo::HttpStatusCode;

void HttpResponseCallback(const HttpRequest& request, HttpResponse& response) {
  if (request.method() != kGet) {
    response.SetStatusCode(k400BadRequest);
    response.SetStatusMessage("Bad Request");
    response.SetCloseConnection(true);
    return;
  }    
  
  {
    const string& path = request.path(); 
    if (path == "/") {
      response.SetStatusCode(k200OK);
      response.SetBodyType("text/html");
      response.SetBody(love6_website);
    } else if (path == "/hello") {
      response.SetStatusCode(k200OK);
      response.SetBodyType("text/plain");
      response.SetBody("Hello, world!\n");
    } else if (path == "/favicon.ico" || path == "/favicon") {
      response.SetStatusCode(k200OK);
      response.SetBodyType("image/png");
      response.SetBody(string(favicon, sizeof(favicon))); 
    } else {
      response.SetStatusCode(k404NotFound);
      response.SetStatusMessage("Not Found");
      response.SetCloseConnection(true);
      return;
    }
  }
}

int main( int argc , char* argv[] )
{
  if (argc <= 1)
  {
    printf( "Usage: %s portname\n", argv[0] );
    return 0;
  }

  EventLoop loop;
  Address listen_address(argv[1]);
  HttpServer server(&loop, listen_address);
  server.SetHttpResponseCallback(HttpResponseCallback);
  server.Start();
  loop.Loop();
  
  return 0;
}

2、httpserver.h
#ifndef TINY_MUDUO_HTTPSERVER_H_
#define TINY_MUDUO_HTTPSERVER_H_

#include 

#include 
#include 

#include "callback.h"
#include "tcpserver.h"
#include "tcpconnection.h"
#include "buffer.h"
#include "httpcontent.h"
#include "httprequest.h"
#include "httpresponse.h"

using tiny_muduo::HttpStatusCode;

namespace tiny_muduo {

static const int kThreadNums = 6;

class EventLoop;

class HttpServer{
 typedef std::function<void (const HttpRequest&, HttpResponse&)> HttpResponseCallback;

 public:
  HttpServer(EventLoop* loop, const Address& address);
  ~HttpServer();

  void Start() {
    server_.Start();
  }

  void HttpDefaultCallback(const HttpRequest& request, HttpResponse& response) {
    response.SetStatusCode(k404NotFound);
    response.SetStatusMessage("Not Found");
    response.SetCloseConnection(true);
  }

  void ConnectionCallback(const TcpConnectionPtr& connection) {
  }

  void MessageCallback(const TcpConnectionPtr& connection, Buffer* buffer);
  void SetHttpResponseCallback(HttpResponseCallback response_callback) { 
    response_callback_ = std::move(response_callback); 
  } 

  void DealWithRequest(const HttpRequest& request, const TcpConnectionPtr& connection);

 private:
  EventLoop* loop_;
  TcpServer server_;

  HttpResponseCallback response_callback_;
};

}

#endif

2、httpserver.cc
#include "httpserver.h"

#include 

using namespace tiny_muduo;

using tiny_muduo::Version;

HttpServer::HttpServer(EventLoop* loop, const Address& address) : loop_(loop),
                                                                  server_(loop, address) {
  server_.SetConnectionCallback(
          std::bind(&HttpServer::ConnectionCallback, this, _1));
  server_.SetMessageCallback(
          std::bind(&HttpServer::MessageCallback, this, _1, _2));
  server_.SetThreadNums(kThreadNums);
  SetHttpResponseCallback(std::bind(&HttpServer::HttpDefaultCallback, this, _1, _2));
}

HttpServer::~HttpServer() {
}

void HttpServer::MessageCallback(const TcpConnectionPtr& connection, 
                                 Buffer* buffer) {
 HttpContent* content = connection->GetHttpContent();
 if (connection->IsShutdown()) return;

 if (!content->ParseContent(buffer)) {
   connection->Send("HTTP/1.1 400 Bad Request\r\n\r\n");
   connection->Shutdown();
   return;
 }   

 if (content->GetCompleteRequest()) {
   DealWithRequest(content->request(), connection);
   content->ResetContentState();
 }   
}

void HttpServer::DealWithRequest(const HttpRequest& request, 
                                 const TcpConnectionPtr& connection) {
  string connection_state = std::move(request.GetHeader("Connection"));
  bool close = (connection_state == "Close" || 
               (request.version() == kHttp10 &&
                connection_state != "Keep-Alive"));

  HttpResponse response(close); 
  response_callback_(request, response);
  Buffer buffer;
  response.AppendToBuffer(&buffer);
  connection->Send(&buffer);

  if (response.CloseConnection()) {
    connection->Shutdown();
  }   
}

3、tcpserver.h
#ifndef TINY_MUDUO_TCPSERVER_H_
#define TINY_MUDUO_TCPSERVER_H_

#include 
#include 

#include "callback.h"
#include "eventloop.h"
#include "acceptor.h"
#include "eventloopthreadpool.h"
#include "tcpconnection.h"

namespace tiny_muduo {

class Address;

class TcpServer {
 public:
  TcpServer(EventLoop* loop, const Address& address);
  ~TcpServer();

  void Start() {
    threads_->StartLoop();
    loop_->RunOneFunc(std::bind(&Acceptor::Listen, acceptor_.get()));
  }

  void SetConnectionCallback(const ConnectionCallback& callback) { 
    connection_callback_ = callback;
  }

  void SetMessageCallback(const MessageCallback& callback) {
    message_callback_ = callback;
  }

  void SetThreadNums(int thread_nums) {
    threads_->SetThreadNums(thread_nums);    
  }

  void HandleClose(const TcpConnectionPtr& conn);
  void HandleCloseInLoop(const TcpConnectionPtr& ptr);
  void HandleNewConnection(int connfd);

 private:
  typedef std::unordered_map<int, TcpconnectionPtr> ConnectionMap;

  EventLoop* loop_;
  std::unique_ptr<EventLoopThreadPool> threads_;
  std::unique_ptr<Acceptor> acceptor_;

  ConnectionCallback connection_callback_;
  MessageCallback message_callback_;
  ConnectionMap connections_;
};

}// namespace tiny_muduo
#endif

3、tcpserver.cc
#include "tcpserver.h"

#define NDEBUG
#include 

#include 

#include "eventloopthreadpool.h"
#include "acceptor.h"
#include "tcpconnection.h"

using namespace tiny_muduo;

TcpServer::TcpServer(EventLoop* loop, const Address& address)
    : loop_(loop),
      threads_(new EventLoopThreadPool(loop_)),
      acceptor_(new Acceptor(loop_, address)) {
  acceptor_->SetNewConnectionCallback(std::bind(&TcpServer::HandleNewConnection, this, _1));
}

TcpServer::~TcpServer() {
  for (auto& pair : connections_) {
    TcpConnectionPtr ptr(pair.second);
    pair.second.reset();
    ptr->loop()->RunOneFunc(std::bind(&TcpConnection::ConnectionDestructor, ptr));
  }
}

void TcpServer::HandleClose(const TcpConnectionPtr& ptr) {
  loop_->QueueOneFunc(std::bind(&TcpServer::HandleCloseInLoop, this, ptr));
}

void TcpServer::HandleCloseInLoop(const TcpConnectionPtr& ptr) {
  assert(connections_.find(ptr->fd()) != connections_.end());
  connections_.erase(connections_.find(ptr->fd()));
  EventLoop* loop = ptr->loop(); 
  loop->QueueOneFunc(std::bind(&TcpConnection::ConnectionDestructor, ptr));
}

void TcpServer::HandleNewConnection(int connfd) {
  EventLoop* loop = threads_->NextLoop(); 
  TcpConnectionPtr ptr(new TcpConnection(loop, connfd));
  connections_[connfd] = ptr;
  ptr->SetConnectionCallback(connection_callback_);
  ptr->SetMessageCallback(message_callback_);
  ptr->SetCloseCallback(std::bind(&TcpServer::HandleClose, this, _1));
  loop->RunOneFunc(std::bind(&TcpConnection::ConnectionEstablished, ptr));
}

4、acceptor.h
#ifndef TINY_MUDUO_ACCEPTOR_H_
#define TINY_MUDUO_ACCEPTOR_H_

#include 
#include 

namespace tiny_muduo {

class EventLoop;
class Address;
class Channel;

class Acceptor {
 public:
  typedef std::function<void (int)> NewConnectionCallback;
  
  Acceptor(EventLoop* loop, const Address& address);
  ~Acceptor();

  void SetNonBlocking(int fd); // for accept non-blocking not for accept4
  void BindListenFd(const Address& address); 
  void Listen();
  void NewConnection();

  void SetNewConnectionCallback(const NewConnectionCallback& callback) {
    new_connection_callback_ = std::move(callback);
  }

 private:
   EventLoop* loop_;
   int listenfd_;
   std::unique_ptr<Channel> channel_;

   NewConnectionCallback new_connection_callback_; 
};

}
#endif

4、acceptor.cc
#include "acceptor.h"

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 

#include "address.h"
#include "channel.h"

using namespace tiny_muduo;

Acceptor::Acceptor(EventLoop* loop, const Address& address)
    : loop_(loop),
      listenfd_(::socket(PF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP)),
      channel_(new Channel(loop, listenfd_)) {
  int option_val = 1;
  ::setsockopt(listenfd_, SOL_SOCKET, SO_KEEPALIVE,
               &option_val, static_cast<socklen_t>(sizeof option_val));
  BindListenFd(address);
  channel_->SetReadCallback(std::bind(&Acceptor::NewConnection, this));
}

Acceptor::~Acceptor() {
  channel_->DisableAll();
  loop_->Remove(channel_.get());
  ::close(listenfd_);
}

void Acceptor::SetNonBlocking(int fd) {
  int old_state = fcntl(fd, F_GETFL);
  int new_state = old_state | O_NONBLOCK;
  fcntl(fd, F_SETFL, new_state);
  (void)new_state;
}

void Acceptor::BindListenFd(const Address& addr) {
  struct sockaddr_in address;
  memset(&address, 0, sizeof(address));
  address.sin_family = AF_INET;
  address.sin_port = htons(addr.port());
  inet_pton(AF_INET, addr.ip(), &address.sin_addr); 
  int ret = bind(listenfd_, (struct sockaddr*)(&address), sizeof(address));
  assert(ret != -1); 
}

void Acceptor::Listen() {
  int ret = listen(listenfd_, SOMAXCONN);
  assert(ret != -1);
  channel_->EnableReading(); 
}

void Acceptor::NewConnection() {
  struct sockaddr_in client;
  socklen_t client_addrlength = sizeof(client);
  int connfd = ::accept4(listenfd_, (struct sockaddr*)&client, &client_addrlength, SOCK_NONBLOCK | SOCK_CLOEXEC);
  int option_val = 1;
  ::setsockopt(listenfd_, SOL_SOCKET, SO_KEEPALIVE,
               &option_val, static_cast<socklen_t>(sizeof option_val)); 
  assert(connfd > 0);
  new_connection_callback_(connfd);
}

5、eventloop.h
#ifndef TINY_MUDUO_EVENTLOOP_H_
#define TINY_MUDUO_EVENTLOOP_H_

#include 
#include 
#include 
#include 

#include 
#include 
#include 

#include "mutex.h"
#include "epoller.h"

namespace tiny_muduo {

class Epoller;
class Channel;

class EventLoop {
 public:
  typedef std::vector<Channel*> Channels;
  typedef std::function<void()> BasicFunc; 
  typedef std::vector<BasicFunc> ToDoList;  
  
  EventLoop();
  ~EventLoop();

  bool IsInThreadLoop() { return ::pthread_self() == tid_; }
  void Update(Channel* channel) { epoller_->Update(channel); }
  void Remove(Channel* channel) { epoller_->Remove(channel); }

  void Loop();
  void HandleRead();
  void QueueOneFunc(BasicFunc func);
  void RunOneFunc(BasicFunc func);
  void DoToDoList();

 private:
  pthread_t tid_; 
  std::unique_ptr<Epoller> epoller_;
  int wakeup_fd_;
  std::unique_ptr<Channel> wakeup_channel_;
  bool calling_functors_;
  Channels active_channels_;
  ToDoList to_do_list_;

  MutexLock mutex_;
};
 
}  // namespace tiny_muduo
#endif

5、eventloop.cc
#include "eventloop.h"

#include 
#include 
#include 

#include 

#include "mutex.h"
#include "channel.h"

using namespace tiny_muduo;

EventLoop::EventLoop()
    : tid_(::pthread_self()),
      epoller_(new Epoller()),
      wakeup_fd_(::eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC)),
      wakeup_channel_(new Channel(this, wakeup_fd_)),
      calling_functors_(false) {
  wakeup_channel_->SetReadCallback(std::bind(&EventLoop::HandleRead, this));
  wakeup_channel_->EnableReading();
}

EventLoop::~EventLoop() {
  wakeup_channel_->DisableAll();
  Remove(wakeup_channel_.get());
}

void EventLoop::Loop() {
  while (1) {
    active_channels_.clear();
    epoller_->Poll(active_channels_);
    for (const auto& channel : active_channels_) {
      channel->HandleEvent();
    }
    DoToDoList();
  }
}

void EventLoop::HandleRead() {
  uint64_t read_one_byte = 1;
  ::read(wakeup_fd_, &read_one_byte, sizeof(read_one_byte));
  return;
}

void EventLoop::QueueOneFunc(BasicFunc func) {
  {  
    MutexLockGuard lock(mutex_);
    to_do_list_.emplace_back(std::move(func));
  }   

  if (!IsInThreadLoop() || calling_functors_) {
    uint64_t write_one_byte = 1;  
    ::write(wakeup_fd_, &write_one_byte, sizeof(write_one_byte));
  } 
}

void EventLoop::RunOneFunc(BasicFunc func) { 
  if (IsInThreadLoop()) {   
    func(); 
  } else {
    QueueOneFunc(std::move(func));  
  } 
}

void EventLoop::DoToDoList() {
  ToDoList functors;
  calling_functors_ = true;
  {
    MutexLockGuard lock(mutex_);
    functors.swap(to_do_list_);
  }

  for (const auto& func : functors) {
    func();
  }
  calling_functors_ = false;
}

6、epoller.h
#ifndef TINY_MUDUO_EPOLLER_H_
#define TINY_MUDUO_EPOLLER_H_

#include 
#include 
#include 

namespace {
  const int kDefaultEvents = 16;
}

namespace tiny_muduo {

class Channel;

class Epoller {
 public: 
  typedef std::vector<epoll_event> Events;
  typedef std::vector<Channel*> Channels;
  
  Epoller();
  ~Epoller();
  
  void Remove(Channel* channel_);
  void Poll(Channels& channels);
  int EpollWait()  { return epoll_wait(epollfd_, &*events_.begin(), static_cast<int>(events_.size()), -1); }  
  void FillActiveChannels(int eventnums, Channels& channels); 
  void Update(Channel* channel);
  void UpdateChannel(int operation, Channel* channel);
        
 private: 
  typedef std::unordered_map<int, Channel*> ChannelMap;

  int epollfd_;
  Events events_;
  ChannelMap channels_;
};

}
#endif

6、epoller.cc
#include "epoller.h"

#define NDEBUG
#include 
#include 
#include 

#include 

#include "channel.h"

using namespace tiny_muduo;

Epoller::Epoller()
    : epollfd_(::epoll_create1(EPOLL_CLOEXEC)),
      events_(kDefaultEvents), 
      channels_() {
}

Epoller::~Epoller() {
  ::close(epollfd_);
}

void Epoller::Poll(Channels& channels) {
  int eventnums = EpollWait();
  FillActiveChannels(eventnums, channels);
}

void Epoller::FillActiveChannels(int eventnums, Channels& channels) {
  for (int i = 0; i < eventnums; ++i) {
    Channel* ptr = static_cast<Channel*> (events_[i].data.ptr);
    ptr->SetReceivedEvents(events_[i].events);
    channels.emplace_back(ptr);
  }
  if (eventnums == static_cast<int>(events_.size())) {
      events_.resize(eventnums * 2);
  }
}

void Epoller::Remove(Channel* channel) {
  int fd = channel->fd();
  ChannelState state = channel->state();
  assert(state == kDeleted || state == kAdded);

  if (state == kAdded) {
    UpdateChannel(EPOLL_CTL_DEL, channel);
  }
  channel->SetChannelState(kNew);
  channels_.erase(fd);
  return;
}

void Epoller::Update(Channel* channel) {
  int op = 0, events = channel->events();
  ChannelState state = channel->state(); 
  int fd = channel->fd();

  if (state == kNew || state == kDeleted) {
    if (state == kNew) {
      assert(channels_.find(fd) == channels_.end());
      channels_[fd] = channel;
    } else {
      assert(channels_.find(fd) != channels_.end());
      assert(channels_[fd] == channel);
    }
    op = EPOLL_CTL_ADD;
    channel->SetChannelState(kAdded);
  } else {
    assert(channels_.find(fd) != channels_.end());
    assert(channels_[fd] == channel);
    if (events == 0) {
      op = EPOLL_CTL_DEL;
      channel->SetChannelState(kDeleted); 
    } else {
      op = EPOLL_CTL_MOD; 
    }
  }
  
  UpdateChannel(op, channel);
}

void Epoller::UpdateChannel(int operation, Channel* channel) {
  struct epoll_event event;
  memset(&event, ','sizeof ()event);.
  event=events events channel->();.
  event.data=ptr static_cast <void*(>)channel;epoll_ctl

  (,epollfd_, operationfd channel->(),& )event;return
  ;}
#

7、channel.h
ifndefTINY_MUDUO_CHANNEL_H_ #
defineTINY_MUDUO_CHANNEL_H_ #

include# 

include# 

include"eventloop.h" #
include"callback.h" namespace

enum tiny_muduo {

ChannelState , {
  kNew,
  kAdded}
  kDeleted
;class

Channel public {
 :Channel
  (*EventLoop, loopconst int &) fd;~
  Channel();void

  HandleEvent ();void

  SetReadCallback ()ReadCallback callback= { 
    read_callback_ :: stdmove()callback;} 
  void

  SetWriteCallback ()WriteCallback callback= {
    write_callback_ :: stdmove()callback;}
  void

  EnableReading ()|= {
    events_ ( |EPOLLIN ) EPOLLPRI;Update 
    ();}  
  void

  EnableWriting ()|= {
    events_ ; EPOLLOUTUpdate
    ();}
  void

  DisableAll ()= {
    events_ 0 ;Update
    ();} 
  void

  DisableWriting ()&= {
    events_ ~ ;EPOLLOUTUpdate
    ();}  
  void

  Update ()Update {
    loop_->(this);}
  void

  SetReceivedEvents (int) events= {
    recv_events_ ; events}
  void

  SetChannelState ()ChannelState state= {
    state_ ; state}
  int

  fd ()const return { ; fd_} int 
  events ()const return { ; events_} int
  recv_events ()const return { ; recv_events_} state
  ChannelState ()const return { ; state_} bool
  
  IsWriting ()return { & events_ ; EPOLLOUT} bool
  IsReading ()return { & events_ ( |EPOLLIN ) EPOLLPRI;} private

 :*
  EventLoop; loop_int
  ; fd_int
  ; events_// update events      int
  ; recv_events_// epoll received events ;
  
  ChannelState state_;
  ReadCallback read_callback_;
  WriteCallback write_callback_}  
;}

#
endif#

7、channel.cc
include"channel.h" #

includeusing 

namespace ; tiny_muduoChannel

::Channel(*EventLoop, loopconst
                 int &) fd:
    loop_ ()loop,fd_
      ()fd,events_
      (0),recv_events_
      (0),state_
      ()kNew} {
Channel

::~Channel()} {
void

Channel ::HandleEvent()if {
  ( &recv_events_ ( |EPOLLIN | EPOLLPRI ) EPOLLRDHUP)if {
    ()read_callback_read_callback_ {
      ();}
    }
  if 

  ( &recv_events_ ) EPOLLOUTif {
    ()write_callback_write_callback_ {
      ();}
    }
  }
#

8、tcpconnection.h
ifndefTINY_MUDUO_TCPCONNECTION_H_ #
defineTINY_MUDUO_TCPCONNECTION_H_ #

include# 
include# 
include# 

include#  
include# 
include# 

include"callback.h" #
include"channel.h" #
include"buffer.h" #
include"httpcontent.h" using

:: std;stringnamespace

class tiny_muduo {

EventLoop ;class

TcpConnection : public :: stdenable_shared_from_this<TcpConnectionpublic> {
 :enum
  ConnectionState , {
    kConnected}
    kDisconnected
  ;TcpConnection

  (*EventLoop, loopint) connfd;~
  TcpConnection();void

  SetConnectionCallback ()ConnectionCallback callback= { 
    connection_callback_ :: stdmove()callback;}
  void

  SetMessageCallback ()MessageCallback callback= {
    message_callback_ :: stdmove()callback;}
  void

  SetCloseCallback ()CloseCallback callback= {
    close_callback_ :: stdmove()callback;}
  void

  ConnectionEstablished ()= {
    state_ ; kConnectedEnableReading
    channel_->();connection_callback_
    (shared_from_this(),& )input_buffer_;}
  *

  HttpContentGetHttpContent ()return {
    & ;content_}
  void

  Shutdown ();bool  
  IsShutdown ()return { ; shutdown_state_} void
  ConnectionDestructor ();void
  HandleClose ();void
  HandleMessage ();void
  HandleWrite ();void
  Send (*Buffer) buffer;void
  Send (const& string) str;void
  Send (constchar *, messageint ) len;void
  Send (constchar *) messageSend { (,messagestrlen ()message);} int

  fd ()const return { ; fd_} *
  EventLooploop ()const return { ; loop_} private
  
 :*
  EventLoop; loop_int
  ; fd_;
  ConnectionState state_::
  std<unique_ptr;Channel> channel_;
  Buffer input_buffer_;
  Buffer output_buffer_;
  HttpContent content_bool
  ; shutdown_state_;

  ConnectionCallback connection_callback_;
  MessageCallback message_callback_;
  CloseCallback close_callback_}
;typedef

:: std<shared_ptr;TcpConnection> TcpconnectionPtr}

// namespace tiny_muduo  #
endif#

8、tcpconnection.cc
include"tcpconnection.h" // #define NDEBUG

#
include #
include# 
include# 

include"channel.h" #
include"buffer.h" using

namespace ; tiny_muduoTcpConnection

::TcpConnection(*EventLoop, loopint ) connfd: 
    loop_ ()loop,fd_
      ()connfd,state_
      ()kDisconnected,channel_
      (newChannel (,loop_) fd_),shutdown_state_
      (false)SetReadCallback {
  channel_->(::stdbind(&::TcpConnection,HandleMessagethis ));SetWriteCallback
  channel_->(::stdbind(&::TcpConnection,HandleWritethis ));}
TcpConnection

::~TcpConnection()//printf("TcpConnection::~TcpConnection destructor\n"); {
  ::
  close()fd_;}
void

TcpConnection ::ConnectionDestructor()if {
  ( ==state_ ) kConnected= {
    state_ ; kDisconnectedDisableAll
    channel_->();}
  Remove
  loop_->(.channel_get());}
void

TcpConnection ::HandleClose()= {
  state_ ; kDisconnectedDisableAll
  channel_->();guard

  TcpConnectionPtr (shared_from_this());close_callback_
  ()guard;}
void

TcpConnection ::HandleMessage()int {
  = read_size . input_buffer_ReadFd()fd_;if
  ( 0read_size > )message_callback_ {
    (shared_from_this(),& )input_buffer_;}
  else if ( ==read_size 0 )HandleClose {
    ();}
  }
void

TcpConnection ::HandleWrite()int {
  = len . output_buffer_readablebytes();int
  = remaining ; lenint
  = send_size :: write(,fd_. output_buffer_Peek(),) remaining;-=
  remaining ; send_size.
  output_buffer_Retrieve()send_size;assert
  
  (<=remaining ) len;if
  ( !.output_buffer_readablebytes())DisableWriting {
    channel_->();}
  }
void

TcpConnection ::Send(constchar *, messageint ) lenint {
  = remaining ; lenint
  = send_size 0 ;if
  ( !IsWritingchannel_->()&& . output_buffer_readablebytes()== 0 )= {
    send_size :: write(,fd_, message) len;-=
    remaining ; send_size} 
  assert

  (<=remaining ) len;if
  ( 0remaining > ). {
    output_buffer_Append(+message , send_size) remaining;if
    ( !IsWritingchannel_->())EnableWriting {
      channel_->();} 
    }
  }
void

TcpConnection ::Shutdown()if { 
  ( !IsWritingchannel_->()):: {
    shutdown(,fd_) SHUT_WR;=
    shutdown_state_ true ;}
  } 
void

TcpConnection ::Send(*Buffer) bufferSend {
  (Peekbuffer->(),readablebytes buffer->());RetrieveAll 
  buffer->();}
void

TcpConnection ::Send(const& string) messageSend {
  (.messagedata(),. messagesize());}
#

9、buffer.h
ifndefTINY_MUDUO_BUFFER_H_ #
defineTINY_MUDUO_BUFFER_H_ #

include# 
include #
include# 

defineNDEBUG #
include #
includeusing 

:: std;stringnamespace

static tiny_muduo {

const int = kPrePendIndex 8 ;class

Buffer public {
 :Buffer
  (): buffer_ (1024),read_index_ ()kPrePendIndex,write_index_ ()kPrePendIndex} {
  ~
  Buffer()} {int

  ReadFd (int) fd;char
  
  *begin ()return { & *.buffer_begin();} ;const
  char *begin ()const return { & *.buffer_begin();} ;char

  *beginread ()return { begin ()+ ; read_index_} const 
  char *beginread ()const return { begin ()+ ; read_index_} char

  *beginwrite ()return { begin ()+ ; write_index_} const
  char *beginwrite ()const return { begin ()+ ; write_index_} void

  Append (constchar *) messageAppend {
    (,messagestrlen ()message);}
  void

  Append (constchar *, messageint ) lenMakeSureEnoughStorage {
    ()len;::
    stdcopy(,message+ message , lenbeginwrite ());+=
    write_index_ ; len}
  void

  Append (const& string) messageAppend {
    (.messagedata(),. messagesize());} 
  void

  Retrieve (int) lenassert {
    (readablebytes()) >= len;if
    ( +len < read_index_ ) write_index_= {
      read_index_ + read_index_ ; len}
    else = {
      write_index_ ; kPrePendIndex= 
      read_index_ ; write_index_}
    }
  void

  RetrieveUntilIndex (constchar *) indexassert {
    (beginwrite()) >= index;+=
    read_index_ - index beginread ();}
  void

  RetrieveAll ()= {
    write_index_ ; kPrePendIndex=
    read_index_ ; write_index_}
  RetrieveAsString

  string (int) lenassert {
    (+read_index_ <= len ) write_index_;=
    string ret :: stdmove(PeekAsString()len);Retrieve
    ()len;return 
    ; ret}
  RetrieveAllAsString

  string ()= {
    string ret :: stdmove(PeekAllAsString());RetrieveAll
    ();return
    ; ret}
  const

  char *Peek ()const return {
    beginread ();}
  char

  *Peek ()return {
    beginread ();}
  PeekAsString

  string (int) lenreturn {
    string (beginread(),beginread ()+ ) len;}
  PeekAllAsString

  string ()return {
    string (beginread(),beginwrite ());} 
  int
  
  readablebytes ()const return { - write_index_ ; read_index_} int
  writablebytes ()const return { . buffer_capacity()- ; write_index_} int 
  prependablebytes ()const return { ; read_index_} void

  MakeSureEnoughStorage (int) lenif {
    ( writablebytes()) >= lenreturn ;if
    ( writablebytes()+ prependablebytes ()+ >= kPrePendIndex ) len:: {
      stdcopy(beginread(),beginwrite (),begin ()+ ) kPrePendIndex;=
      write_index_ + kPrePendIndex readablebytes ();=
      read_index_ ; kPrePendIndex}
    else . {
      buffer_resize(.buffer_capacity()+ ) len;}
    }
  private

 :::
  std<vectorchar;> buffer_int
  ; read_index_int
  ; write_index_}
;}

#
endif#

9、buffer.cc
include"buffer.h" #

includeusing 

namespace ; tiny_muduoint

Buffer ::ReadFd(int) fdchar {
  [ extrabuf65536]= 0 {};struct
  iovec [ iv2];const
  int = writable writablebytes ();[
  iv0].=iov_base beginwrite ();[
  iv0].=iov_len ; writable[
  iv1].=iov_base ; extrabuf[
  iv1].=iov_len sizeof ()extrabuf;const
  
  int = iovcnt ( <writable static_cast <int(>sizeof()extrabuf)? 2 : 1 );int
  = readn :: readv(,fd, iv) iovcnt;if

  ( <readn 0 )printf {
    ("Buffer::ReadFd readn < 0 SYS_ERR\n");}
  else
  if ( <=readn ) writable+= {
    write_index_ ; readn}
  else = {
    write_index_ . buffer_size();Append
    (,extrabuf- readn ) writable;}
  return

  ; readn}
#

10、thread.h
ifndefTINY_MUDUO_THREAD_H_ #
defineTINY_MUDUO_THREAD_H_ #

include# 

include# 

include"latch.h" namespace

class tiny_muduo {

Thread public {
 :typedef
  :: std<functionvoid( );> ThreadFuncThread

  (const& ThreadFunc) func;~
  Thread();void 

  StartThread ();private

 :;
  pthread_t pthread_id_;
  ThreadFunc func_;
  Latch latch_}
;struct       


ThreadData typedef {

:: tiny_muduo::Thread;ThreadFunc ThreadFunc;
 
ThreadFunc func_*
Latch; latch_ThreadData

(&ThreadFunc, func* Latch) latch:
    func_ ()func,latch_
      ()latch} {
void

RunOneFunc ()CountDown {
  latch_->();=
  latch_ nullptr ;func_  
  ();}
}
;}

#
endif#

10、thread.cc
include"thread.h" #

include# 

include"latch.h" using

namespace ; tiny_muduostatic

void *ThreadRun (void*) arg* {
  ThreadData= ptr static_cast <*ThreadData(>)arg;RunOneFunc
  ptr->();delete
  ; ptrreturn
  nullptr ;}
Thread

::Thread(const& ThreadFunc) func:
    pthread_id_ (-1),func_
      ()func,latch_
      (1)} {
Thread

::~Thread():: {
  pthread_detach()pthread_id_;}
void

Thread ::StartThread()* {
  ThreadData= ptr new ThreadData (,func_& )latch_;::
  pthread_create(&,pthread_id_nullptr ,, ThreadRun) ptr;.
  latch_Wait();}
#

11、eventloopthread.h
ifndefTINY_MUDUO_EVENTLOOPTHREAD_H #
defineTINY_MUDUO_EVENTLOOPTHREAD_H #

include"thread.h" #
include"mutex.h" #
include"condition.h" namespace

class tiny_muduo {

EventLoop ;class

EventLoopThread public {
 :EventLoopThread
  ();~
  EventLoopThread();void

  StartFunc ();*
  EventLoopStartLoop ();private

 :*
  EventLoop; loop_;
  Thread thread_;
  MutexLock mutex_;
  Condition cond_}
;}

#
endif#

11、eventloopthread.cc
include"eventloopthread.h" #

include# 
include# 

include"mutex.h" #
include"condition.h" #
include"eventloop.h" using

namespace ; tiny_muduoEventLoopThread

::EventLoopThread():
    loop_ (nullptr),thread_
      (::stdbind(&::EventLoopThread,StartFuncthis )),mutex_
      (),cond_
      ()mutex_} {
EventLoopThread

::~EventLoopThread()} {*        

EventLoopEventLoopThread ::StartLoop(). {
  thread_StartThread();*
  EventLoop= loop nullptr ;lock
  {   
    MutexLockGuard ()mutex_;while
    ( ==loop_ nullptr ). {
      cond_Wait();}
    =
    loop ; loop_}
  return
  ; loop}
void

EventLoopThread ::StartFunc(); {
  EventLoop looplock

  {
    MutexLockGuard ()mutex_;=
    loop_ & ;loop.
    cond_Signal();}
  Loop

  loop_->();lock
  {
    MutexLockGuard ()mutex_;=
    loop_ nullptr ;}
  }
#

12、eventloopthreadpool.h
ifndefTINY_MUDUO_EVENTLOOPTHREADPOOL_H_ #
defineTINY_MUDUO_EVENTLOOPTHREADPOOL_H_ #

include# 
includenamespace 

class tiny_muduo {

EventLoopThread ;class
EventLoop ;class

EventLoopThreadPool public {
  :typedef
   :: std<vector::std<unique_ptr;EventLoopThread>> Threadtypedef
   :: std<vector*EventLoop;> LoopEventLoopThreadPool

   (*EventLoop) loop;~
   EventLoopThreadPool();void
   
   SetThreadNums (int) thread_nums= {
     thread_nums_ ; thread_nums}
   void

   StartLoop ();*
   EventLoopNextLoop ();private

  :*
   EventLoop; base_loop_;   
   Thread threads_;
   Loop loops_int

   ; thread_nums_int
   ; next_}
;}

#
endif#

12、eventloopthreadpool.cc
include"eventloopthreadpool.h" #

include# 

include"eventloopthread.h" using

namespace ; tiny_muduoEventLoopThreadPool

::EventLoopThreadPool(*EventLoop) loop:
    base_loop_ ()loop,threads_
      (),loops_
      (),thread_nums_
      (0),next_
      (0)} {
EventLoopThreadPool

::~EventLoopThreadPool()} {void

EventLoopThreadPool ::StartLoop()for {
  ( int= i 0 ;< i ; thread_nums_++ )i* {
    EventLoopThread= ptr new EventLoopThread ();.
    threads_emplace_back(::stdunique_ptr<(EventLoopThread>)ptr);.
    loops_emplace_back(StartLoopptr->());}
  }
*

EventLoopEventLoopThreadPool ::NextLoop()* {
  EventLoop= ret ; base_loop_if
  ( !.loops_empty())= {
    ret [ loops_]next_;=
    next_ ( +next_ 1 )% ; thread_nums_}
  return

  ; ret}
#

2、httpserver相关文件
1、httpcontent.h
ifndefTINY_MUDUO_HTTPCONTENT_H_ #
defineTINY_MUDUO_HTTPCONTENT_H_ #

include# 
include #

include"buffer.h" #
include"httprequest.h" #
include"httpparsestate.h" namespace

enum tiny_muduo {

HttpRequestParseLine , {
  kLineOK,
  kLineMore}
  kLineErrno
;class

HttpContent public {
 :HttpContent
  ();~
  HttpContent();void

  ParseLine (*Buffer) buffer;bool
  ParseContent (*Buffer) buffer;bool
  GetCompleteRequest ()return { == parse_state_ ; kParseGotCompleteRequest} const 
  
  & HttpRequestrequest ()const return { ; request_} void
  ResetContentState ()= { 
    parse_state_ ; kParseRequestLine= 
    line_state_ ; kLineOK} 
  private

 :int
  ; checked_index_;
  HttpRequest request_;
  HttpRequestParseLine line_state_;
  HttpRequestParseState parse_state_}
;}

#
endif#

1、httpcontent.cc
include"httpcontent.h" #

include"httprequest.h" #
include"httpparsestate.h" using

namespace ; tiny_muduoHttpContent

::HttpContent(): checked_index_ (0),parse_state_
                             ()kParseRequestLine} {
HttpContent

::~HttpContent()} {void

HttpContent ::ParseLine(*Buffer) buffer= {
  line_state_ ; kLineMoreif
  ( readablebytesbuffer->()== 0 )return ;int

  = readable_index readablebytes buffer->();const
  char *= buf beginread buffer->();for

  ( ;< checked_index_ ; readable_index++ )checked_index_char {
    = chr [ buf]checked_index_;if 
    ( !=chr '\r' && != chr '\n' )continue ;if
    ( ==chr '\r' )if {      
      ( ==checked_index_ - readable_index 1 )continue ;if
      ( [buf+checked_index_ 1 ]== '\n' )= {
        checked_index_ + checked_index_ 2 ;=
        line_state_ ; kLineOK}
      else = { 
        line_state_ ; kLineErrno}
      return
      ;}
    else if {
      ( &&checked_index_ [ buf-checked_index_ 1 ]== '\r' )= {
        checked_index_ + checked_index_ 1 ;=
        line_state_ ; kLineOK}
      else = {
        line_state_ ; kLineErrno}
      return
      ;}
    }
   return

  ;}
bool

HttpContent ::ParseContent(*Buffer) bufferwhile {
  ( !=parse_state_ ) kParseErrnoParseLine {
    ()buffer;if

    ( ==line_state_ || kLineMore == line_state_ ) kLineErrnoif { 
      ( ==line_state_ ) kLineErrno= {
        parse_state_ ; kParseErrno=
        checked_index_ 0 ;}
      break
      ;}
    const

    char *= start beginread buffer->();const
    char *= end + start ( -checked_index_ 2 );if

    ( ==parse_state_ ) kParseRequestLine. {
      request_ParseRequestLine(,start, end) parse_state_;}
    else if ( ==parse_state_ ) kParseHeaders. {
      request_ParseHeaders(,start, end) parse_state_;}
    else if ( ==parse_state_ ) kParseBody. {
      request_ParseBody(,start, end) parse_state_;}
    else if ( ==parse_state_ ) kParseGotCompleteRequestbreak {
      ;}
    RetrieveUntilIndex
    buffer->(+start ) checked_index_;=
    checked_index_ 0 ;}
  return

  != parse_state_ ; kParseErrno}
#

2、httprequest.h
ifndefTINY_MUDUO_HTTPREQUEST_H_ #
defineTINY_MUDUO_HTTPREQUEST_H_ #

include"httpparsestate.h" #

include# 
includeusing 

:: std;stringnamespace

static tiny_muduo {

const char [ http]= "HTTP/1." ;enum

Method , {
  kGet,
  kPost,
  kPut,
  kDelete,
  kTrace,
  kOptions,
  kConnect}
  kPatch
;enum

Version , {
  kHttp10}
  kHttp11
;class

HttpRequest public {
 :HttpRequest
  ();~
  HttpRequest();bool

  ParseRequestMethod (constchar *, startconst char *) end;void

  ParseRequestLine (constchar *, startconst char *, end& 
                    HttpRequestParseState) state;void

  ParseHeaders (constchar *, startconst char *, end&
                    HttpRequestParseState) state;void

  ParseBody (constchar *, startconst char *, end&
                    HttpRequestParseState) state;method

  Method ()const return { ; method_} const
  & stringpath ()const return { ; path_} const
  & stringquery ()const return { ; query_} version
  Version ()const return { ; version_} const
  :: std<map,string& string>headers ()const return { ; headers_} GetHeader

  string (const& string) headerconst auto {
    = iter . headers_find()header;if
    ( ==iter . headers_end())return {
      string ();}
    else return {
      ; iter->second}
    }
  private

 :;
  Method method_;
  string path_;
  string query_;
  Version version_::
  std<map,string; string> headers_}
;}

#
endif#

2、httprequest.cc
include"httprequest.h" #

include# 
include #

include"httpparsestate.h" using

namespace ; tiny_muduousing
:: tiny_muduo;Methodusing
:: tiny_muduo;HttpRequestParseStateHttpRequest

::HttpRequest()} {
HttpRequest

::~HttpRequest()} {
bool

HttpRequest ::ParseRequestMethod(constchar *, startconst char *) endmethod {
  string (,start) end;bool
  = has_method true ;if
  ( ==method "GET" )= {
    method_ ; kGet}
  else if ( ==method "POST" )= {
    method_ ; kPost}
  else if ( ==method "PUT" )= {
    method_ ; kPut}
  else if ( ==method "DELETE" )= {
    method_ ; kDelete}
  else if ( ==method "TRACE" )= {
    method_ ; kTrace}
  else if ( ==method "OPTIONS" )= {
    method_ ; kOptions}
  else if ( ==method "CONNECT" )= {
    method_ ; kConnect}
  else if ( ==method "PATCH" )= {
    method_ ; kPatch}
  else = {
    has_method false ;}
  return

  ; has_method}
void

HttpRequest ::ParseRequestLine(constchar *, startconst char *, end& 
                      HttpRequestParseState) stateconst {
  {      
    char *= space :: stdfind(,start, end' ' );if
    ( ==space ) end= {
      state ; kParseErrnoreturn
      ;}
    if
  
    ( !ParseRequestMethod(,start) space)= {
      state ; kParseErrnoreturn
      ;}
    =
    start + space 1 ;}
  const
 
  {
    char *= space :: stdfind(,start, end' ' );if
    ( ==space ) end= {
      state ; kParseErrnoreturn
      ;}
    const

    char *= query :: stdfind(,start, end'?' );if 
    ( !=query ) end= {
      path_ :: stdmove(string(,start) query);=
      query_ :: stdmove(string(+query 1 ,) space);}
    else = {
      path_ :: stdmove(string(,start) space);}
    =        
    start + space 1 ;}
  const
   
  {
    int = httplen sizeof ()http/ sizeof (char)- 1 ;const
    char *= httpindex :: stdsearch(,start, end, http+ http ) httplen;if
    ( ==httpindex ) end= {
      state ; kParseErrnoreturn
      ;}
    const

    char = chr * (+httpindex ) httplen;if
    ( +httpindex + httplen 1 == && end ( ==chr '1' || == chr '0' ))if {
      ( ==chr '1' )= {
        version_ ; kHttp11}
      else = {
        version_ ; kHttp10}
      }
    else = {
      state ; kParseErrnoreturn
      ;}
    }
  =

  state ; kParseHeaders}
void

HttpRequest ::ParseBody(constchar *, startconst char *, end& 
                            HttpRequestParseState) state} {
void

HttpRequest ::ParseHeaders(constchar *, startconst char *, end& 
                      HttpRequestParseState) stateif {
  ( ==start && end * ==start '\r' && * (+start 1 )== '\n' )= {
    state ; kParseGotCompleteRequestreturn
    ;}
  const

  char *= colon :: stdfind(,start, end':' );if
  ( ==colon ) end= {
    state ; kParseErrnoreturn
    ;}
  const

  char *= vaild + colon 1 ;while
  ( *(++vaild)!= ' ' )} {[
  headers_::stdmove(string(,start) colon)]= :: stdmove(string(+colon 1 ,) vaild);return
  ;}
#

3、httpresponse.h
ifndefTINY_MUDUO_HTTPRESPONSE_H_ #
defineTINY_MUDUO_HTTPRESPONSE_H_ #

include# 
include# 

include"httprequest.h" using

:: std;stringnamespace

static tiny_muduo {

const = string CRLF "\r\n" ;enum

HttpStatusCode = {
  k100Continue 100 ,=
  k200OK 200 ,=
  k400BadRequest 400 ,=
  k403Forbidden 403 ,=
  k404NotFound 404 ,=
  k500InternalServerErrno 500 }
;class

Buffer ;class

HttpResponse public {
 :HttpResponse
  (bool) close_connection: type_ ("text/plain"),close_connection_
                                        ()close_connection} {
  ~
  HttpResponse()} {void

  SetStatusCode ()HttpStatusCode status_code= { status_code_ ; status_code} void
  SetStatusMessage (const& string) status_message= { status_message_ :: stdmove()status_message;} void
  SetCloseConnection (bool) close_connection= { close_connection_ ; close_connection} void

  SetBodyType (const& string) type= { type_ ; type} void
  SetBodyType (constchar *) type= { type_ ; type} void
  SetBody (const& string) body= { body_ ; body} void
  SetBody (constchar *) body= { body_ :: stdmove(string()body);} void
  AppendToBuffer (*Buffer) buffer;bool

  CloseConnection ()return { ; close_connection_} private

 :static
  const ; string server_name_;
  HttpStatusCode status_code_;
  string status_message_;
  string headers_;
  string body_;
  string type_bool
  ; close_connection_}
;}

#

endif#

3、httpresponse.cc
include"httpresponse.h" #

include# 

include# 

include"buffer.h" using

namespace ; tiny_muduousing
:: std;stringconst

:: string HttpResponse=server_name_ "Tiny_muduo" ;void

HttpResponse ::AppendToBuffer(*Buffer) bufferchar {
  [ buf32]= 0 {};snprintf

  (,bufsizeof ()buf,"HTTP/1.1 %d " ,)status_code_;Append
  buffer->()buf;Append
  buffer->()status_message_;Append
  buffer->()CRLF;if
  
  ( )close_connection_Append {
    buffer->("Connection: close\r\n");}
  else snprintf {
    (,bufsizeof ()buf,"Content-Length: %zd\r\n" ,. body_size());// no need to memset this is longer than HTTP... one Append
    buffer->()buf;Append
    buffer->("Connection: Keep-Alive\r\n");}
  Append

  buffer->("Content-Type: ");Append
  buffer->()type_;Append
  buffer->()CRLF;Append

  buffer->("Server: ");Append
  buffer->()server_name_;Append
  buffer->()CRLF;Append
  buffer->()CRLF;Append

  buffer->()body_;return
  ;}
#

4、httpparsestate.h
ifndefTINY_MUDUO_HTTPSTATE_H_ #
defineTINY_MUDUO_HTTPSTATE_H_ namespace

enum tiny_muduo {

HttpRequestParseState , {
  kParseRequestLine,
  kParseHeaders,
  kParseBody,
  kParseGotCompleteRequest,
  kParseErrno}
;}

#

endif#

3、其他组件(mutex makefile等)
1、mutex
ifndefTINY_MUDUO_MUTEX_H_ #
defineTINY_MUDUO_MUTEX_H_ #

include"pthread.h" namespace

class tiny_muduo {

MutexLock public {
 :MutexLock
  ()pthread_mutex_init {
   (&,mutex_nullptr );}
  ~
  MutexLock()pthread_mutex_destroy {
   (&)mutex_;}
  bool
  
  Lock ()return {
    pthread_mutex_lock (&)mutex_== 0 ;}
  bool

  Unlock ()return {
    pthread_mutex_unlock (&)mutex_== 0 ;} 
  *
 
  pthread_mutex_tmutex ()return { & ;mutex_} private 

 :;
  pthread_mutex_t mutex_} 
;class

MutexLockGuard public {
 :MutexLockGuard
  (&MutexLock) mutex: mutex_ ()mutex. {
    mutex_Lock();}
  ~
  MutexLockGuard(). {
    mutex_Unlock();}
  private

 :&
  MutexLock; mutex_}
;}

#
endif#

2、condition.h
ifndefTINY_MUDUO_CONDITION_H_ #
defineTINY_MUDUO_CONDITION_H_ #

include"pthread.h" #

include"mutex.h" namespace

class tiny_muduo {

Condition public {
 :Condition
  (&MutexLock) mutex: mutex_ ()mutexpthread_cond_init {
    (&,cond_nullptr );}
  ~
  Condition()pthread_cond_destroy {
    (&)cond_;}
  bool

  Wait ()int {
    = ret 0 ;=
    ret pthread_cond_wait (&,cond_. mutex_mutex());return
    == ret 0 ;}
  bool

  Signal ()return {
    pthread_cond_signal (&)cond_;}
  bool

  BroadCast ()return {
    pthread_cond_broadcast (&)cond_;}
  private

 :&
  MutexLock; mutex_;
  pthread_cond_t cond_}
;} 

#
endif#

3、latch.h
ifndefTINY_MUDUO_LATCH_H_ #
defineTINY_MUDUO_LATCH_H_ #

include"mutex.h" #
include"condition.h" namespace

class tiny_muduo {

Latch public {
 :Latch
  (int) count: count_ ()count,mutex_ (),cond_ ()mutex_} {void

  CountDown ()lock {
    MutexLockGuard ()mutex_;--
    ;count_if
    ( ==count_ 0 ). {
      cond_BroadCast();}
    }  
  void

  Wait ()lock {
    MutexLockGuard ()mutex_;while
    ( 0count_ > ). {
      cond_Wait();}
    }
  private

 :int
  ; count_;
  MutexLock mutex_;
  Condition cond_}
;}

#
endif#

4、callback.h
ifndefTINY_MUDUO_CALLBACK_H_ #
defineTINY_MUDUO_CALLBACK_H_ #

include# 
includeusing 

:: std::placeholders;_1using
:: std::placeholders;_2using
:: std::placeholders;_3namespace

class tiny_muduo {
  TcpConnection ;typedef
  :: std<shared_ptr;TcpConnection> TcpConnectionPtrclass
  
  Buffer ;typedef
  :: std<functionvoid( const& TcpConnectionPtr,* Buffer);> ConnectionCallbacktypedef
  :: std<functionvoid( const& TcpConnectionPtr,* Buffer);> MessageCallbacktypedef
  :: std<functionvoid( );> ReadCallbacktypedef
  :: std<functionvoid( );> WriteCallbacktypedef
  :: std<functionvoid( const& TcpConnectionPtr);> CloseCallback}
#
endif=

5、makefile
CC ++ g=
CFLAG - -Wall =c
OBJS . main.o httpserver.o httpresponse.o httpcontent.o httprequest.o\
	   tcpserver.o acceptor.o\
	   channel.o eventloop.o epoller.o tcpconnection.o\
	   eventloopthreadpool.o eventloopthread.o thread.o buffer(o\
	   $)TFLAG=
TFLAG - :lpthread

webserver ( $)OBJS( 
	$)CC^ $- .o $@

main:o . main.cc eventloop.h address.h httpserver.h httprequest.h httpresponse.h\
		 httpresponsefile(h
	$)CC( $)CFLAG< $- .o $@
	
httpserver:o . httpserver.cc httpserver.h buffer(h
	$)CC( $)CFLAG< $- .o $@
	
httpresponse:o . httpresponse.cc httpresponse.h buffer(h
	$)CC( $)CFLAG< $- .o $@

httpcontent:o . httpcontent.cc httpcontent.h httprequest.h httpparsestate(h
	$)CC( $)CFLAG< $- .o $@

httprequest:o . httprequest.cc httprequest.h httpparsestate(h
	$)CC( $)CFLAG< $- .o $@

tcpserver:o . tcpserver.cc tcpserver.h acceptor.h tcpconnection.h\
			  eventloopthreadpool(h
	$)CC( $)CFLAG< $- .o $@
	
acceptor:o . acceptor.cc acceptor.h address.h channel(h
	$)CC( $)CFLAG< $- .o $@
	
channel:o . channel.cc channel(h
	$)CC( $)CFLAG< $- .o $@

eventloop:o . eventloop.cc eventloop.h channel.h mutex(h
	$)CC( $)CFLAG< $- .o $@

eventloopthreadpool:o . eventloopthreadpool.cc eventloopthreadpool.h eventloopthread(h
	$)CC( $)CFLAG< $- .o $@
	
eventloopthread:o . eventloopthread.cc eventloopthreadpool.h mutex.h\
					condition.h eventloop(h
	$)CC( $)CFLAG< $- .o $@

thread:o . thread.cc thread.h latch(h
	$)CC( $)CFLAG< $- .o $@
	
epoller:o . epoller.cc epoller.h channel(h
	$)CC( $)CFLAG< $- .o $@
	
tcpconnection:o . tcpconnection.cc tcpconnection.h \
					 channel.h buffer.h httpcontent(h
	$)CC( $)CFLAG< $- .o $@
	
buffer:o . buffer.cc buffer(h
	$)CC( $)CFLAG< $- .o $@

:PHONY : clean
clean*
	rm .[+++]o

结束语

哎 路还有很长的路要走 IO库 定时器
可能还要重构HTTPserver的逻辑处理 后面还要可能修改epoll的工作状态

但是毕竟走到现在了 还是得坚持下去 之后再回头看看这里 可能也觉得别有一番感觉 哈哈

各位下一篇见了~

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
从零开始自制实现WebServer(九)--- 目前总览代码如下 得继续脚步前行_C_内存溢出

从零开始自制实现WebServer(九)--- 目前总览代码如下 得继续脚步前行

从零开始自制实现WebServer(九)--- 目前总览代码如下 得继续脚步前行,第1张

文章目录
    • 前引
    • (九)--- 目前总览代码如下 得继续脚步前行
      • 1、主要核心部分代码
        • 1、main.cc
        • 2、httpserver.h
        • 2、httpserver.cc
        • 3、tcpserver.h
        • 3、tcpserver.cc
        • 4、acceptor.h
        • 4、acceptor.cc
        • 5、eventloop.h
        • 5、eventloop.cc
        • 6、epoller.h
        • 6、epoller.cc
        • 7、channel.h
        • 7、channel.cc
        • 8、tcpconnection.h
        • 8、tcpconnection.cc
        • 9、buffer.h
        • 9、buffer.cc
        • 10、thread.h
        • 10、thread.cc
        • 11、eventloopthread.h
        • 11、eventloopthread.cc
        • 12、eventloopthreadpool.h
        • 12、eventloopthreadpool.cc
      • 2、httpserver相关文件
        • 1、httpcontent.h
        • 1、httpcontent.cc
        • 2、httprequest.h
        • 2、httprequest.cc
        • 3、httpresponse.h
        • 3、httpresponse.cc
        • 4、httpparsestate.h
      • 3、其他组件(mutex makefile等)
        • 1、mutex
        • 2、condition.h
        • 3、latch.h
        • 4、callback.h
        • 5、makefile
    • 结束语


前引

目前性能还是有一些差距 我初步揣测
是不是由于我httpserver的分析函数 是完全按照我的思路写的
但是比muduo库更为复杂 处理就更细致一点 而且也引入了多个参数…
我觉得是这个原因

主要是性能差距也没有那么大… 而且确实
我是先判断是否存在一行 对每个字符判断
个人觉得判断函数写的也不是那么好 用std::search应该感觉效果好一些

但是主要 我觉得这个地方 状态机 用一个checked_index 判断过的字符就可以不用判断了 但是其实 如果用webbench来判断的话 其实这个过程肯定是没有必要的… 因为发送的情况不会出现的 每次只发送一两个字节的情况

后面再改改 看看性能会不会提升到和muduo库持平 之后大概率要改用ET工作模式
现在性能差距相比之前已经相对来说很小了 下面给张截图吧
明天再来改改了



(九)— 目前总览代码如下 得继续脚步前行

当然代码还在持续迭代
之后可能还要重构一下http分析函数 让他更简单一点


1、主要核心部分代码
1、main.cc
#include 

#include 
#include 

#include "eventloop.h"
#include "address.h"
#include "httpserver.h"
#include "httprequest.h"
#include "httpresponse.h"

#include "httpresponsefile.h"

using namespace tiny_muduo;

using tiny_muduo::Method;
using tiny_muduo::HttpStatusCode;

void HttpResponseCallback(const HttpRequest& request, HttpResponse& response) {
  if (request.method() != kGet) {
    response.SetStatusCode(k400BadRequest);
    response.SetStatusMessage("Bad Request");
    response.SetCloseConnection(true);
    return;
  }    
  
  {
    const string& path = request.path(); 
    if (path == "/") {
      response.SetStatusCode(k200OK);
      response.SetBodyType("text/html");
      response.SetBody(love6_website);
    } else if (path == "/hello") {
      response.SetStatusCode(k200OK);
      response.SetBodyType("text/plain");
      response.SetBody("Hello, world!\n");
    } else if (path == "/favicon.ico" || path == "/favicon") {
      response.SetStatusCode(k200OK);
      response.SetBodyType("image/png");
      response.SetBody(string(favicon, sizeof(favicon))); 
    } else {
      response.SetStatusCode(k404NotFound);
      response.SetStatusMessage("Not Found");
      response.SetCloseConnection(true);
      return;
    }
  }
}

int main( int argc , char* argv[] )
{
  if (argc <= 1)
  {
    printf( "Usage: %s portname\n", argv[0] );
    return 0;
  }

  EventLoop loop;
  Address listen_address(argv[1]);
  HttpServer server(&loop, listen_address);
  server.SetHttpResponseCallback(HttpResponseCallback);
  server.Start();
  loop.Loop();
  
  return 0;
}

2、httpserver.h
#ifndef TINY_MUDUO_HTTPSERVER_H_
#define TINY_MUDUO_HTTPSERVER_H_

#include 

#include 
#include 

#include "callback.h"
#include "tcpserver.h"
#include "tcpconnection.h"
#include "buffer.h"
#include "httpcontent.h"
#include "httprequest.h"
#include "httpresponse.h"

using tiny_muduo::HttpStatusCode;

namespace tiny_muduo {

static const int kThreadNums = 6;

class EventLoop;

class HttpServer{
 typedef std::function<void (const HttpRequest&, HttpResponse&)> HttpResponseCallback;

 public:
  HttpServer(EventLoop* loop, const Address& address);
  ~HttpServer();

  void Start() {
    server_.Start();
  }

  void HttpDefaultCallback(const HttpRequest& request, HttpResponse& response) {
    response.SetStatusCode(k404NotFound);
    response.SetStatusMessage("Not Found");
    response.SetCloseConnection(true);
  }

  void ConnectionCallback(const TcpConnectionPtr& connection) {
  }

  void MessageCallback(const TcpConnectionPtr& connection, Buffer* buffer);
  void SetHttpResponseCallback(HttpResponseCallback response_callback) { 
    response_callback_ = std::move(response_callback); 
  } 

  void DealWithRequest(const HttpRequest& request, const TcpConnectionPtr& connection);

 private:
  EventLoop* loop_;
  TcpServer server_;

  HttpResponseCallback response_callback_;
};

}

#endif

2、httpserver.cc
#include "httpserver.h"

#include 

using namespace tiny_muduo;

using tiny_muduo::Version;

HttpServer::HttpServer(EventLoop* loop, const Address& address) : loop_(loop),
                                                                  server_(loop, address) {
  server_.SetConnectionCallback(
          std::bind(&HttpServer::ConnectionCallback, this, _1));
  server_.SetMessageCallback(
          std::bind(&HttpServer::MessageCallback, this, _1, _2));
  server_.SetThreadNums(kThreadNums);
  SetHttpResponseCallback(std::bind(&HttpServer::HttpDefaultCallback, this, _1, _2));
}

HttpServer::~HttpServer() {
}

void HttpServer::MessageCallback(const TcpConnectionPtr& connection, 
                                 Buffer* buffer) {
 HttpContent* content = connection->GetHttpContent();
 if (connection->IsShutdown()) return;

 if (!content->ParseContent(buffer)) {
   connection->Send("HTTP/1.1 400 Bad Request\r\n\r\n");
   connection->Shutdown();
   return;
 }   

 if (content->GetCompleteRequest()) {
   DealWithRequest(content->request(), connection);
   content->ResetContentState();
 }   
}

void HttpServer::DealWithRequest(const HttpRequest& request, 
                                 const TcpConnectionPtr& connection) {
  string connection_state = std::move(request.GetHeader("Connection"));
  bool close = (connection_state == "Close" || 
               (request.version() == kHttp10 &&
                connection_state != "Keep-Alive"));

  HttpResponse response(close); 
  response_callback_(request, response);
  Buffer buffer;
  response.AppendToBuffer(&buffer);
  connection->Send(&buffer);

  if (response.CloseConnection()) {
    connection->Shutdown();
  }   
}

3、tcpserver.h
#ifndef TINY_MUDUO_TCPSERVER_H_
#define TINY_MUDUO_TCPSERVER_H_

#include 
#include 

#include "callback.h"
#include "eventloop.h"
#include "acceptor.h"
#include "eventloopthreadpool.h"
#include "tcpconnection.h"

namespace tiny_muduo {

class Address;

class TcpServer {
 public:
  TcpServer(EventLoop* loop, const Address& address);
  ~TcpServer();

  void Start() {
    threads_->StartLoop();
    loop_->RunOneFunc(std::bind(&Acceptor::Listen, acceptor_.get()));
  }

  void SetConnectionCallback(const ConnectionCallback& callback) { 
    connection_callback_ = callback;
  }

  void SetMessageCallback(const MessageCallback& callback) {
    message_callback_ = callback;
  }

  void SetThreadNums(int thread_nums) {
    threads_->SetThreadNums(thread_nums);    
  }

  void HandleClose(const TcpConnectionPtr& conn);
  void HandleCloseInLoop(const TcpConnectionPtr& ptr);
  void HandleNewConnection(int connfd);

 private:
  typedef std::unordered_map<int, TcpconnectionPtr> ConnectionMap;

  EventLoop* loop_;
  std::unique_ptr<EventLoopThreadPool> threads_;
  std::unique_ptr<Acceptor> acceptor_;

  ConnectionCallback connection_callback_;
  MessageCallback message_callback_;
  ConnectionMap connections_;
};

}// namespace tiny_muduo
#endif

3、tcpserver.cc
#include "tcpserver.h"

#define NDEBUG
#include 

#include 

#include "eventloopthreadpool.h"
#include "acceptor.h"
#include "tcpconnection.h"

using namespace tiny_muduo;

TcpServer::TcpServer(EventLoop* loop, const Address& address)
    : loop_(loop),
      threads_(new EventLoopThreadPool(loop_)),
      acceptor_(new Acceptor(loop_, address)) {
  acceptor_->SetNewConnectionCallback(std::bind(&TcpServer::HandleNewConnection, this, _1));
}

TcpServer::~TcpServer() {
  for (auto& pair : connections_) {
    TcpConnectionPtr ptr(pair.second);
    pair.second.reset();
    ptr->loop()->RunOneFunc(std::bind(&TcpConnection::ConnectionDestructor, ptr));
  }
}

void TcpServer::HandleClose(const TcpConnectionPtr& ptr) {
  loop_->QueueOneFunc(std::bind(&TcpServer::HandleCloseInLoop, this, ptr));
}

void TcpServer::HandleCloseInLoop(const TcpConnectionPtr& ptr) {
  assert(connections_.find(ptr->fd()) != connections_.end());
  connections_.erase(connections_.find(ptr->fd()));
  EventLoop* loop = ptr->loop(); 
  loop->QueueOneFunc(std::bind(&TcpConnection::ConnectionDestructor, ptr));
}

void TcpServer::HandleNewConnection(int connfd) {
  EventLoop* loop = threads_->NextLoop(); 
  TcpConnectionPtr ptr(new TcpConnection(loop, connfd));
  connections_[connfd] = ptr;
  ptr->SetConnectionCallback(connection_callback_);
  ptr->SetMessageCallback(message_callback_);
  ptr->SetCloseCallback(std::bind(&TcpServer::HandleClose, this, _1));
  loop->RunOneFunc(std::bind(&TcpConnection::ConnectionEstablished, ptr));
}

4、acceptor.h
#ifndef TINY_MUDUO_ACCEPTOR_H_
#define TINY_MUDUO_ACCEPTOR_H_

#include 
#include 

namespace tiny_muduo {

class EventLoop;
class Address;
class Channel;

class Acceptor {
 public:
  typedef std::function<void (int)> NewConnectionCallback;
  
  Acceptor(EventLoop* loop, const Address& address);
  ~Acceptor();

  void SetNonBlocking(int fd); // for accept non-blocking not for accept4
  void BindListenFd(const Address& address); 
  void Listen();
  void NewConnection();

  void SetNewConnectionCallback(const NewConnectionCallback& callback) {
    new_connection_callback_ = std::move(callback);
  }

 private:
   EventLoop* loop_;
   int listenfd_;
   std::unique_ptr<Channel> channel_;

   NewConnectionCallback new_connection_callback_; 
};

}
#endif

4、acceptor.cc
#include "acceptor.h"

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 

#include "address.h"
#include "channel.h"

using namespace tiny_muduo;

Acceptor::Acceptor(EventLoop* loop, const Address& address)
    : loop_(loop),
      listenfd_(::socket(PF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP)),
      channel_(new Channel(loop, listenfd_)) {
  int option_val = 1;
  ::setsockopt(listenfd_, SOL_SOCKET, SO_KEEPALIVE,
               &option_val, static_cast<socklen_t>(sizeof option_val));
  BindListenFd(address);
  channel_->SetReadCallback(std::bind(&Acceptor::NewConnection, this));
}

Acceptor::~Acceptor() {
  channel_->DisableAll();
  loop_->Remove(channel_.get());
  ::close(listenfd_);
}

void Acceptor::SetNonBlocking(int fd) {
  int old_state = fcntl(fd, F_GETFL);
  int new_state = old_state | O_NONBLOCK;
  fcntl(fd, F_SETFL, new_state);
  (void)new_state;
}

void Acceptor::BindListenFd(const Address& addr) {
  struct sockaddr_in address;
  memset(&address, 0, sizeof(address));
  address.sin_family = AF_INET;
  address.sin_port = htons(addr.port());
  inet_pton(AF_INET, addr.ip(), &address.sin_addr); 
  int ret = bind(listenfd_, (struct sockaddr*)(&address), sizeof(address));
  assert(ret != -1); 
}

void Acceptor::Listen() {
  int ret = listen(listenfd_, SOMAXCONN);
  assert(ret != -1);
  channel_->EnableReading(); 
}

void Acceptor::NewConnection() {
  struct sockaddr_in client;
  socklen_t client_addrlength = sizeof(client);
  int connfd = ::accept4(listenfd_, (struct sockaddr*)&client, &client_addrlength, SOCK_NONBLOCK | SOCK_CLOEXEC);
  int option_val = 1;
  ::setsockopt(listenfd_, SOL_SOCKET, SO_KEEPALIVE,
               &option_val, static_cast<socklen_t>(sizeof option_val)); 
  assert(connfd > 0);
  new_connection_callback_(connfd);
}

5、eventloop.h
#ifndef TINY_MUDUO_EVENTLOOP_H_
#define TINY_MUDUO_EVENTLOOP_H_

#include 
#include 
#include 
#include 

#include 
#include 
#include 

#include "mutex.h"
#include "epoller.h"

namespace tiny_muduo {

class Epoller;
class Channel;

class EventLoop {
 public:
  typedef std::vector<Channel*> Channels;
  typedef std::function<void()> BasicFunc; 
  typedef std::vector<BasicFunc> ToDoList;  
  
  EventLoop();
  ~EventLoop();

  bool IsInThreadLoop() { return ::pthread_self() == tid_; }
  void Update(Channel* channel) { epoller_->Update(channel); }
  void Remove(Channel* channel) { epoller_->Remove(channel); }

  void Loop();
  void HandleRead();
  void QueueOneFunc(BasicFunc func);
  void RunOneFunc(BasicFunc func);
  void DoToDoList();

 private:
  pthread_t tid_; 
  std::unique_ptr<Epoller> epoller_;
  int wakeup_fd_;
  std::unique_ptr<Channel> wakeup_channel_;
  bool calling_functors_;
  Channels active_channels_;
  ToDoList to_do_list_;

  MutexLock mutex_;
};
 
}  // namespace tiny_muduo
#endif

5、eventloop.cc
#include "eventloop.h"

#include 
#include 
#include 

#include 

#include "mutex.h"
#include "channel.h"

using namespace tiny_muduo;

EventLoop::EventLoop()
    : tid_(::pthread_self()),
      epoller_(new Epoller()),
      wakeup_fd_(::eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC)),
      wakeup_channel_(new Channel(this, wakeup_fd_)),
      calling_functors_(false) {
  wakeup_channel_->SetReadCallback(std::bind(&EventLoop::HandleRead, this));
  wakeup_channel_->EnableReading();
}

EventLoop::~EventLoop() {
  wakeup_channel_->DisableAll();
  Remove(wakeup_channel_.get());
}

void EventLoop::Loop() {
  while (1) {
    active_channels_.clear();
    epoller_->Poll(active_channels_);
    for (const auto& channel : active_channels_) {
      channel->HandleEvent();
    }
    DoToDoList();
  }
}

void EventLoop::HandleRead() {
  uint64_t read_one_byte = 1;
  ::read(wakeup_fd_, &read_one_byte, sizeof(read_one_byte));
  return;
}

void EventLoop::QueueOneFunc(BasicFunc func) {
  {  
    MutexLockGuard lock(mutex_);
    to_do_list_.emplace_back(std::move(func));
  }   

  if (!IsInThreadLoop() || calling_functors_) {
    uint64_t write_one_byte = 1;  
    ::write(wakeup_fd_, &write_one_byte, sizeof(write_one_byte));
  } 
}

void EventLoop::RunOneFunc(BasicFunc func) { 
  if (IsInThreadLoop()) {   
    func(); 
  } else {
    QueueOneFunc(std::move(func));  
  } 
}

void EventLoop::DoToDoList() {
  ToDoList functors;
  calling_functors_ = true;
  {
    MutexLockGuard lock(mutex_);
    functors.swap(to_do_list_);
  }

  for (const auto& func : functors) {
    func();
  }
  calling_functors_ = false;
}

6、epoller.h
#ifndef TINY_MUDUO_EPOLLER_H_
#define TINY_MUDUO_EPOLLER_H_

#include 
#include 
#include 

namespace {
  const int kDefaultEvents = 16;
}

namespace tiny_muduo {

class Channel;

class Epoller {
 public: 
  typedef std::vector<epoll_event> Events;
  typedef std::vector<Channel*> Channels;
  
  Epoller();
  ~Epoller();
  
  void Remove(Channel* channel_);
  void Poll(Channels& channels);
  int EpollWait()  { return epoll_wait(epollfd_, &*events_.begin(), static_cast<int>(events_.size()), -1); }  
  void FillActiveChannels(int eventnums, Channels& channels); 
  void Update(Channel* channel);
  void UpdateChannel(int operation, Channel* channel);
        
 private: 
  typedef std::unordered_map<int, Channel*> ChannelMap;

  int epollfd_;
  Events events_;
  ChannelMap channels_;
};

}
#endif

6、epoller.cc
#include "epoller.h"

#define NDEBUG
#include 
#include 
#include 

#include 

#include "channel.h"

using namespace tiny_muduo;

Epoller::Epoller()
    : epollfd_(::epoll_create1(EPOLL_CLOEXEC)),
      events_(kDefaultEvents), 
      channels_() {
}

Epoller::~Epoller() {
  ::close(epollfd_);
}

void Epoller::Poll(Channels& channels) {
  int eventnums = EpollWait();
  FillActiveChannels(eventnums, channels);
}

void Epoller::FillActiveChannels(int eventnums, Channels& channels) {
  for (int i = 0; i < eventnums; ++i) {
    Channel* ptr = static_cast<Channel*> (events_[i].data.ptr);
    ptr->SetReceivedEvents(events_[i].events);
    channels.emplace_back(ptr);
  }
  if (eventnums == static_cast<int>(events_.size())) {
      events_.resize(eventnums * 2);
  }
}

void Epoller::Remove(Channel* channel) {
  int fd = channel->fd();
  ChannelState state = channel->state();
  assert(state == kDeleted || state == kAdded);

  if (state == kAdded) {
    UpdateChannel(EPOLL_CTL_DEL, channel);
  }
  channel->SetChannelState(kNew);
  channels_.erase(fd);
  return;
}

void Epoller::Update(Channel* channel) {
  int op = 0, events = channel->events();
  ChannelState state = channel->state(); 
  int fd = channel->fd();

  if (state == kNew || state == kDeleted) {
    if (state == kNew) {
      assert(channels_.find(fd) == channels_.end());
      channels_[fd] = channel;
    } else {
      assert(channels_.find(fd) != channels_.end());
      assert(channels_[fd] == channel);
    }
    op = EPOLL_CTL_ADD;
    channel->SetChannelState(kAdded);
  } else {
    assert(channels_.find(fd) != channels_.end());
    assert(channels_[fd] == channel);
    if (events == 0) {
      op = EPOLL_CTL_DEL;
      channel->SetChannelState(kDeleted); 
    } else {
      op = EPOLL_CTL_MOD; 
    }
  }
  
  UpdateChannel(op, channel);
}

void Epoller::UpdateChannel(int operation, Channel* channel) {
  struct epoll_event event;
  memset(&event, ','sizeof ()event);.
  event=events events channel->();.
  event.data=ptr static_cast <void*(>)channel;epoll_ctl

  (,epollfd_, operationfd channel->(),& )event;return
  ;}
#

7、channel.h
ifndefTINY_MUDUO_CHANNEL_H_ #
defineTINY_MUDUO_CHANNEL_H_ #

include# 

include# 

include"eventloop.h" #
include"callback.h" namespace

enum tiny_muduo {

ChannelState , {
  kNew,
  kAdded}
  kDeleted
;class

Channel public {
 :Channel
  (*EventLoop, loopconst int &) fd;~
  Channel();void

  HandleEvent ();void

  SetReadCallback ()ReadCallback callback= { 
    read_callback_ :: stdmove()callback;} 
  void

  SetWriteCallback ()WriteCallback callback= {
    write_callback_ :: stdmove()callback;}
  void

  EnableReading ()|= {
    events_ ( |EPOLLIN ) EPOLLPRI;Update 
    ();}  
  void

  EnableWriting ()|= {
    events_ ; EPOLLOUTUpdate
    ();}
  void

  DisableAll ()= {
    events_ 0 ;Update
    ();} 
  void

  DisableWriting ()&= {
    events_ ~ ;EPOLLOUTUpdate
    ();}  
  void

  Update ()Update {
    loop_->(this);}
  void

  SetReceivedEvents (int) events= {
    recv_events_ ; events}
  void

  SetChannelState ()ChannelState state= {
    state_ ; state}
  int

  fd ()const return { ; fd_} int 
  events ()const return { ; events_} int
  recv_events ()const return { ; recv_events_} state
  ChannelState ()const return { ; state_} bool
  
  IsWriting ()return { & events_ ; EPOLLOUT} bool
  IsReading ()return { & events_ ( |EPOLLIN ) EPOLLPRI;} private

 :*
  EventLoop; loop_int
  ; fd_int
  ; events_// update events      int
  ; recv_events_// epoll received events ;
  
  ChannelState state_;
  ReadCallback read_callback_;
  WriteCallback write_callback_}  
;}

#
endif#

7、channel.cc
include"channel.h" #

includeusing 

namespace ; tiny_muduoChannel

::Channel(*EventLoop, loopconst
                 int &) fd:
    loop_ ()loop,fd_
      ()fd,events_
      (0),recv_events_
      (0),state_
      ()kNew} {
Channel

::~Channel()} {
void

Channel ::HandleEvent()if {
  ( &recv_events_ ( |EPOLLIN | EPOLLPRI ) EPOLLRDHUP)if {
    ()read_callback_read_callback_ {
      ();}
    }
  if 

  ( &recv_events_ ) EPOLLOUTif {
    ()write_callback_write_callback_ {
      ();}
    }
  }
#

8、tcpconnection.h
ifndefTINY_MUDUO_TCPCONNECTION_H_ #
defineTINY_MUDUO_TCPCONNECTION_H_ #

include# 
include# 
include# 

include#  
include# 
include# 

include"callback.h" #
include"channel.h" #
include"buffer.h" #
include"httpcontent.h" using

:: std;stringnamespace

class tiny_muduo {

EventLoop ;class

TcpConnection : public :: stdenable_shared_from_this<TcpConnectionpublic> {
 :enum
  ConnectionState , {
    kConnected}
    kDisconnected
  ;TcpConnection

  (*EventLoop, loopint) connfd;~
  TcpConnection();void

  SetConnectionCallback ()ConnectionCallback callback= { 
    connection_callback_ :: stdmove()callback;}
  void

  SetMessageCallback ()MessageCallback callback= {
    message_callback_ :: stdmove()callback;}
  void

  SetCloseCallback ()CloseCallback callback= {
    close_callback_ :: stdmove()callback;}
  void

  ConnectionEstablished ()= {
    state_ ; kConnectedEnableReading
    channel_->();connection_callback_
    (shared_from_this(),& )input_buffer_;}
  *

  HttpContentGetHttpContent ()return {
    & ;content_}
  void

  Shutdown ();bool  
  IsShutdown ()return { ; shutdown_state_} void
  ConnectionDestructor ();void
  HandleClose ();void
  HandleMessage ();void
  HandleWrite ();void
  Send (*Buffer) buffer;void
  Send (const& string) str;void
  Send (constchar *, messageint ) len;void
  Send (constchar *) messageSend { (,messagestrlen ()message);} int

  fd ()const return { ; fd_} *
  EventLooploop ()const return { ; loop_} private
  
 :*
  EventLoop; loop_int
  ; fd_;
  ConnectionState state_::
  std<unique_ptr;Channel> channel_;
  Buffer input_buffer_;
  Buffer output_buffer_;
  HttpContent content_bool
  ; shutdown_state_;

  ConnectionCallback connection_callback_;
  MessageCallback message_callback_;
  CloseCallback close_callback_}
;typedef

:: std<shared_ptr;TcpConnection> TcpconnectionPtr}

// namespace tiny_muduo  #
endif#

8、tcpconnection.cc
include"tcpconnection.h" // #define NDEBUG

#
include #
include# 
include# 

include"channel.h" #
include"buffer.h" using

namespace ; tiny_muduoTcpConnection

::TcpConnection(*EventLoop, loopint ) connfd: 
    loop_ ()loop,fd_
      ()connfd,state_
      ()kDisconnected,channel_
      (newChannel (,loop_) fd_),shutdown_state_
      (false)SetReadCallback {
  channel_->(::stdbind(&::TcpConnection,HandleMessagethis ));SetWriteCallback
  channel_->(::stdbind(&::TcpConnection,HandleWritethis ));}
TcpConnection

::~TcpConnection()//printf("TcpConnection::~TcpConnection destructor\n"); {
  ::
  close()fd_;}
void

TcpConnection ::ConnectionDestructor()if {
  ( ==state_ ) kConnected= {
    state_ ; kDisconnectedDisableAll
    channel_->();}
  Remove
  loop_->(.channel_get());}
void

TcpConnection ::HandleClose()= {
  state_ ; kDisconnectedDisableAll
  channel_->();guard

  TcpConnectionPtr (shared_from_this());close_callback_
  ()guard;}
void

TcpConnection ::HandleMessage()int {
  = read_size . input_buffer_ReadFd()fd_;if
  ( 0read_size > )message_callback_ {
    (shared_from_this(),& )input_buffer_;}
  else if ( ==read_size 0 )HandleClose {
    ();}
  }
void

TcpConnection ::HandleWrite()int {
  = len . output_buffer_readablebytes();int
  = remaining ; lenint
  = send_size :: write(,fd_. output_buffer_Peek(),) remaining;-=
  remaining ; send_size.
  output_buffer_Retrieve()send_size;assert
  
  (<=remaining ) len;if
  ( !.output_buffer_readablebytes())DisableWriting {
    channel_->();}
  }
void

TcpConnection ::Send(constchar *, messageint ) lenint {
  = remaining ; lenint
  = send_size 0 ;if
  ( !IsWritingchannel_->()&& . output_buffer_readablebytes()== 0 )= {
    send_size :: write(,fd_, message) len;-=
    remaining ; send_size} 
  assert

  (<=remaining ) len;if
  ( 0remaining > ). {
    output_buffer_Append(+message , send_size) remaining;if
    ( !IsWritingchannel_->())EnableWriting {
      channel_->();} 
    }
  }
void

TcpConnection ::Shutdown()if { 
  ( !IsWritingchannel_->()):: {
    shutdown(,fd_) SHUT_WR;=
    shutdown_state_ true ;}
  } 
void

TcpConnection ::Send(*Buffer) bufferSend {
  (Peekbuffer->(),readablebytes buffer->());RetrieveAll 
  buffer->();}
void

TcpConnection ::Send(const& string) messageSend {
  (.messagedata(),. messagesize());}
#

9、buffer.h
ifndefTINY_MUDUO_BUFFER_H_ #
defineTINY_MUDUO_BUFFER_H_ #

include# 
include #
include# 

defineNDEBUG #
include #
includeusing 

:: std;stringnamespace

static tiny_muduo {

const int = kPrePendIndex 8 ;class

Buffer public {
 :Buffer
  (): buffer_ (1024),read_index_ ()kPrePendIndex,write_index_ ()kPrePendIndex} {
  ~
  Buffer()} {int

  ReadFd (int) fd;char
  
  *begin ()return { & *.buffer_begin();} ;const
  char *begin ()const return { & *.buffer_begin();} ;char

  *beginread ()return { begin ()+ ; read_index_} const 
  char *beginread ()const return { begin ()+ ; read_index_} char

  *beginwrite ()return { begin ()+ ; write_index_} const
  char *beginwrite ()const return { begin ()+ ; write_index_} void

  Append (constchar *) messageAppend {
    (,messagestrlen ()message);}
  void

  Append (constchar *, messageint ) lenMakeSureEnoughStorage {
    ()len;::
    stdcopy(,message+ message , lenbeginwrite ());+=
    write_index_ ; len}
  void

  Append (const& string) messageAppend {
    (.messagedata(),. messagesize());} 
  void

  Retrieve (int) lenassert {
    (readablebytes()) >= len;if
    ( +len < read_index_ ) write_index_= {
      read_index_ + read_index_ ; len}
    else = {
      write_index_ ; kPrePendIndex= 
      read_index_ ; write_index_}
    }
  void

  RetrieveUntilIndex (constchar *) indexassert {
    (beginwrite()) >= index;+=
    read_index_ - index beginread ();}
  void

  RetrieveAll ()= {
    write_index_ ; kPrePendIndex=
    read_index_ ; write_index_}
  RetrieveAsString

  string (int) lenassert {
    (+read_index_ <= len ) write_index_;=
    string ret :: stdmove(PeekAsString()len);Retrieve
    ()len;return 
    ; ret}
  RetrieveAllAsString

  string ()= {
    string ret :: stdmove(PeekAllAsString());RetrieveAll
    ();return
    ; ret}
  const

  char *Peek ()const return {
    beginread ();}
  char

  *Peek ()return {
    beginread ();}
  PeekAsString

  string (int) lenreturn {
    string (beginread(),beginread ()+ ) len;}
  PeekAllAsString

  string ()return {
    string (beginread(),beginwrite ());} 
  int
  
  readablebytes ()const return { - write_index_ ; read_index_} int
  writablebytes ()const return { . buffer_capacity()- ; write_index_} int 
  prependablebytes ()const return { ; read_index_} void

  MakeSureEnoughStorage (int) lenif {
    ( writablebytes()) >= lenreturn ;if
    ( writablebytes()+ prependablebytes ()+ >= kPrePendIndex ) len:: {
      stdcopy(beginread(),beginwrite (),begin ()+ ) kPrePendIndex;=
      write_index_ + kPrePendIndex readablebytes ();=
      read_index_ ; kPrePendIndex}
    else . {
      buffer_resize(.buffer_capacity()+ ) len;}
    }
  private

 :::
  std<vectorchar;> buffer_int
  ; read_index_int
  ; write_index_}
;}

#
endif#

9、buffer.cc
include"buffer.h" #

includeusing 

namespace ; tiny_muduoint

Buffer ::ReadFd(int) fdchar {
  [ extrabuf65536]= 0 {};struct
  iovec [ iv2];const
  int = writable writablebytes ();[
  iv0].=iov_base beginwrite ();[
  iv0].=iov_len ; writable[
  iv1].=iov_base ; extrabuf[
  iv1].=iov_len sizeof ()extrabuf;const
  
  int = iovcnt ( <writable static_cast <int(>sizeof()extrabuf)? 2 : 1 );int
  = readn :: readv(,fd, iv) iovcnt;if

  ( <readn 0 )printf {
    ("Buffer::ReadFd readn < 0 SYS_ERR\n");}
  else
  if ( <=readn ) writable+= {
    write_index_ ; readn}
  else = {
    write_index_ . buffer_size();Append
    (,extrabuf- readn ) writable;}
  return

  ; readn}
#

10、thread.h
ifndefTINY_MUDUO_THREAD_H_ #
defineTINY_MUDUO_THREAD_H_ #

include# 

include# 

include"latch.h" namespace

class tiny_muduo {

Thread public {
 :typedef
  :: std<functionvoid( );> ThreadFuncThread

  (const& ThreadFunc) func;~
  Thread();void 

  StartThread ();private

 :;
  pthread_t pthread_id_;
  ThreadFunc func_;
  Latch latch_}
;struct       


ThreadData typedef {

:: tiny_muduo::Thread;ThreadFunc ThreadFunc;
 
ThreadFunc func_*
Latch; latch_ThreadData

(&ThreadFunc, func* Latch) latch:
    func_ ()func,latch_
      ()latch} {
void

RunOneFunc ()CountDown {
  latch_->();=
  latch_ nullptr ;func_  
  ();}
}
;}

#
endif#

10、thread.cc
include"thread.h" #

include# 

include"latch.h" using

namespace ; tiny_muduostatic

void *ThreadRun (void*) arg* {
  ThreadData= ptr static_cast <*ThreadData(>)arg;RunOneFunc
  ptr->();delete
  ; ptrreturn
  nullptr ;}
Thread

::Thread(const& ThreadFunc) func:
    pthread_id_ (-1),func_
      ()func,latch_
      (1)} {
Thread

::~Thread():: {
  pthread_detach()pthread_id_;}
void

Thread ::StartThread()* {
  ThreadData= ptr new ThreadData (,func_& )latch_;::
  pthread_create(&,pthread_id_nullptr ,, ThreadRun) ptr;.
  latch_Wait();}
#

11、eventloopthread.h
ifndefTINY_MUDUO_EVENTLOOPTHREAD_H #
defineTINY_MUDUO_EVENTLOOPTHREAD_H #

include"thread.h" #
include"mutex.h" #
include"condition.h" namespace

class tiny_muduo {

EventLoop ;class

EventLoopThread public {
 :EventLoopThread
  ();~
  EventLoopThread();void

  StartFunc ();*
  EventLoopStartLoop ();private

 :*
  EventLoop; loop_;
  Thread thread_;
  MutexLock mutex_;
  Condition cond_}
;}

#
endif#

11、eventloopthread.cc
include"eventloopthread.h" #

include# 
include# 

include"mutex.h" #
include"condition.h" #
include"eventloop.h" using

namespace ; tiny_muduoEventLoopThread

::EventLoopThread():
    loop_ (nullptr),thread_
      (::stdbind(&::EventLoopThread,StartFuncthis )),mutex_
      (),cond_
      ()mutex_} {
EventLoopThread

::~EventLoopThread()} {*        

EventLoopEventLoopThread ::StartLoop(). {
  thread_StartThread();*
  EventLoop= loop nullptr ;lock
  {   
    MutexLockGuard ()mutex_;while
    ( ==loop_ nullptr ). {
      cond_Wait();}
    =
    loop ; loop_}
  return
  ; loop}
void

EventLoopThread ::StartFunc(); {
  EventLoop looplock

  {
    MutexLockGuard ()mutex_;=
    loop_ & ;loop.
    cond_Signal();}
  Loop

  loop_->();lock
  {
    MutexLockGuard ()mutex_;=
    loop_ nullptr ;}
  }
#

12、eventloopthreadpool.h
ifndefTINY_MUDUO_EVENTLOOPTHREADPOOL_H_ #
defineTINY_MUDUO_EVENTLOOPTHREADPOOL_H_ #

include# 
includenamespace 

class tiny_muduo {

EventLoopThread ;class
EventLoop ;class

EventLoopThreadPool public {
  :typedef
   :: std<vector::std<unique_ptr;EventLoopThread>> Threadtypedef
   :: std<vector*EventLoop;> LoopEventLoopThreadPool

   (*EventLoop) loop;~
   EventLoopThreadPool();void
   
   SetThreadNums (int) thread_nums= {
     thread_nums_ ; thread_nums}
   void

   StartLoop ();*
   EventLoopNextLoop ();private

  :*
   EventLoop; base_loop_;   
   Thread threads_;
   Loop loops_int

   ; thread_nums_int
   ; next_}
;}

#
endif#

12、eventloopthreadpool.cc
include"eventloopthreadpool.h" #

include# 

include"eventloopthread.h" using

namespace ; tiny_muduoEventLoopThreadPool

::EventLoopThreadPool(*EventLoop) loop:
    base_loop_ ()loop,threads_
      (),loops_
      (),thread_nums_
      (0),next_
      (0)} {
EventLoopThreadPool

::~EventLoopThreadPool()} {void

EventLoopThreadPool ::StartLoop()for {
  ( int= i 0 ;< i ; thread_nums_++ )i* {
    EventLoopThread= ptr new EventLoopThread ();.
    threads_emplace_back(::stdunique_ptr<(EventLoopThread>)ptr);.
    loops_emplace_back(StartLoopptr->());}
  }
*

EventLoopEventLoopThreadPool ::NextLoop()* {
  EventLoop= ret ; base_loop_if
  ( !.loops_empty())= {
    ret [ loops_]next_;=
    next_ ( +next_ 1 )% ; thread_nums_}
  return

  ; ret}
#

2、httpserver相关文件
1、httpcontent.h
ifndefTINY_MUDUO_HTTPCONTENT_H_ #
defineTINY_MUDUO_HTTPCONTENT_H_ #

include# 
include #

include"buffer.h" #
include"httprequest.h" #
include"httpparsestate.h" namespace

enum tiny_muduo {

HttpRequestParseLine , {
  kLineOK,
  kLineMore}
  kLineErrno
;class

HttpContent public {
 :HttpContent
  ();~
  HttpContent();void

  ParseLine (*Buffer) buffer;bool
  ParseContent (*Buffer) buffer;bool
  GetCompleteRequest ()return { == parse_state_ ; kParseGotCompleteRequest} const 
  
  & HttpRequestrequest ()const return { ; request_} void
  ResetContentState ()= { 
    parse_state_ ; kParseRequestLine= 
    line_state_ ; kLineOK} 
  private

 :int
  ; checked_index_;
  HttpRequest request_;
  HttpRequestParseLine line_state_;
  HttpRequestParseState parse_state_}
;}

#
endif#

1、httpcontent.cc
include"httpcontent.h" #

include"httprequest.h" #
include"httpparsestate.h" using

namespace ; tiny_muduoHttpContent

::HttpContent(): checked_index_ (0),parse_state_
                             ()kParseRequestLine} {
HttpContent

::~HttpContent()} {void

HttpContent ::ParseLine(*Buffer) buffer= {
  line_state_ ; kLineMoreif
  ( readablebytesbuffer->()== 0 )return ;int

  = readable_index readablebytes buffer->();const
  char *= buf beginread buffer->();for

  ( ;< checked_index_ ; readable_index++ )checked_index_char {
    = chr [ buf]checked_index_;if 
    ( !=chr '\r' && != chr '\n' )continue ;if
    ( ==chr '\r' )if {      
      ( ==checked_index_ - readable_index 1 )continue ;if
      ( [buf+checked_index_ 1 ]== '\n' )= {
        checked_index_ + checked_index_ 2 ;=
        line_state_ ; kLineOK}
      else = { 
        line_state_ ; kLineErrno}
      return
      ;}
    else if {
      ( &&checked_index_ [ buf-checked_index_ 1 ]== '\r' )= {
        checked_index_ + checked_index_ 1 ;=
        line_state_ ; kLineOK}
      else = {
        line_state_ ; kLineErrno}
      return
      ;}
    }
   return

  ;}
bool

HttpContent ::ParseContent(*Buffer) bufferwhile {
  ( !=parse_state_ ) kParseErrnoParseLine {
    ()buffer;if

    ( ==line_state_ || kLineMore == line_state_ ) kLineErrnoif { 
      ( ==line_state_ ) kLineErrno= {
        parse_state_ ; kParseErrno=
        checked_index_ 0 ;}
      break
      ;}
    const

    char *= start beginread buffer->();const
    char *= end + start ( -checked_index_ 2 );if

    ( ==parse_state_ ) kParseRequestLine. {
      request_ParseRequestLine(,start, end) parse_state_;}
    else if ( ==parse_state_ ) kParseHeaders. {
      request_ParseHeaders(,start, end) parse_state_;}
    else if ( ==parse_state_ ) kParseBody. {
      request_ParseBody(,start, end) parse_state_;}
    else if ( ==parse_state_ ) kParseGotCompleteRequestbreak {
      ;}
    RetrieveUntilIndex
    buffer->(+start ) checked_index_;=
    checked_index_ 0 ;}
  return

  != parse_state_ ; kParseErrno}
#

2、httprequest.h
ifndefTINY_MUDUO_HTTPREQUEST_H_ #
defineTINY_MUDUO_HTTPREQUEST_H_ #

include"httpparsestate.h" #

include# 
includeusing 

:: std;stringnamespace

static tiny_muduo {

const char [ http]= "HTTP/1." ;enum

Method , {
  kGet,
  kPost,
  kPut,
  kDelete,
  kTrace,
  kOptions,
  kConnect}
  kPatch
;enum

Version , {
  kHttp10}
  kHttp11
;class

HttpRequest public {
 :HttpRequest
  ();~
  HttpRequest();bool

  ParseRequestMethod (constchar *, startconst char *) end;void

  ParseRequestLine (constchar *, startconst char *, end& 
                    HttpRequestParseState) state;void

  ParseHeaders (constchar *, startconst char *, end&
                    HttpRequestParseState) state;void

  ParseBody (constchar *, startconst char *, end&
                    HttpRequestParseState) state;method

  Method ()const return { ; method_} const
  & stringpath ()const return { ; path_} const
  & stringquery ()const return { ; query_} version
  Version ()const return { ; version_} const
  :: std<map,string& string>headers ()const return { ; headers_} GetHeader

  string (const& string) headerconst auto {
    = iter . headers_find()header;if
    ( ==iter . headers_end())return {
      string ();}
    else return {
      ; iter->second}
    }
  private

 :;
  Method method_;
  string path_;
  string query_;
  Version version_::
  std<map,string; string> headers_}
;}

#
endif#

2、httprequest.cc
include"httprequest.h" #

include# 
include #

include"httpparsestate.h" using

namespace ; tiny_muduousing
:: tiny_muduo;Methodusing
:: tiny_muduo;HttpRequestParseStateHttpRequest

::HttpRequest()} {
HttpRequest

::~HttpRequest()} {
bool

HttpRequest ::ParseRequestMethod(constchar *, startconst char *) endmethod {
  string (,start) end;bool
  = has_method true ;if
  ( ==method "GET" )= {
    method_ ; kGet}
  else if ( ==method "POST" )= {
    method_ ; kPost}
  else if ( ==method "PUT" )= {
    method_ ; kPut}
  else if ( ==method "DELETE" )= {
    method_ ; kDelete}
  else if ( ==method "TRACE" )= {
    method_ ; kTrace}
  else if ( ==method "OPTIONS" )= {
    method_ ; kOptions}
  else if ( ==method "CONNECT" )= {
    method_ ; kConnect}
  else if ( ==method "PATCH" )= {
    method_ ; kPatch}
  else = {
    has_method false ;}
  return

  ; has_method}
void

HttpRequest ::ParseRequestLine(constchar *, startconst char *, end& 
                      HttpRequestParseState) stateconst {
  {      
    char *= space :: stdfind(,start, end' ' );if
    ( ==space ) end= {
      state ; kParseErrnoreturn
      ;}
    if
  
    ( !ParseRequestMethod(,start) space)= {
      state ; kParseErrnoreturn
      ;}
    =
    start + space 1 ;}
  const
 
  {
    char *= space :: stdfind(,start, end' ' );if
    ( ==space ) end= {
      state ; kParseErrnoreturn
      ;}
    const

    char *= query :: stdfind(,start, end'?' );if 
    ( !=query ) end= {
      path_ :: stdmove(string(,start) query);=
      query_ :: stdmove(string(+query 1 ,) space);}
    else = {
      path_ :: stdmove(string(,start) space);}
    =        
    start + space 1 ;}
  const
   
  {
    int = httplen sizeof ()http/ sizeof (char)- 1 ;const
    char *= httpindex :: stdsearch(,start, end, http+ http ) httplen;if
    ( ==httpindex ) end= {
      state ; kParseErrnoreturn
      ;}
    const

    char = chr * (+httpindex ) httplen;if
    ( +httpindex + httplen 1 == && end ( ==chr '1' || == chr '0' ))if {
      ( ==chr '1' )= {
        version_ ; kHttp11}
      else = {
        version_ ; kHttp10}
      }
    else = {
      state ; kParseErrnoreturn
      ;}
    }
  =

  state ; kParseHeaders}
void

HttpRequest ::ParseBody(constchar *, startconst char *, end& 
                            HttpRequestParseState) state} {
void

HttpRequest ::ParseHeaders(constchar *, startconst char *, end& 
                      HttpRequestParseState) stateif {
  ( ==start && end * ==start '\r' && * (+start 1 )== '\n' )= {
    state ; kParseGotCompleteRequestreturn
    ;}
  const

  char *= colon :: stdfind(,start, end':' );if
  ( ==colon ) end= {
    state ; kParseErrnoreturn
    ;}
  const

  char *= vaild + colon 1 ;while
  ( *(++vaild)!= ' ' )} {[
  headers_::stdmove(string(,start) colon)]= :: stdmove(string(+colon 1 ,) vaild);return
  ;}
#

3、httpresponse.h
ifndefTINY_MUDUO_HTTPRESPONSE_H_ #
defineTINY_MUDUO_HTTPRESPONSE_H_ #

include# 
include# 

include"httprequest.h" using

:: std;stringnamespace

static tiny_muduo {

const = string CRLF "\r\n" ;enum

HttpStatusCode = {
  k100Continue 100 ,=
  k200OK 200 ,=
  k400BadRequest 400 ,=
  k403Forbidden 403 ,=
  k404NotFound 404 ,=
  k500InternalServerErrno 500 }
;class

Buffer ;class

HttpResponse public {
 :HttpResponse
  (bool) close_connection: type_ ("text/plain"),close_connection_
                                        ()close_connection} {
  ~
  HttpResponse()} {void

  SetStatusCode ()HttpStatusCode status_code= { status_code_ ; status_code} void
  SetStatusMessage (const& string) status_message= { status_message_ :: stdmove()status_message;} void
  SetCloseConnection (bool) close_connection= { close_connection_ ; close_connection} void

  SetBodyType (const& string) type= { type_ ; type} void
  SetBodyType (constchar *) type= { type_ ; type} void
  SetBody (const& string) body= { body_ ; body} void
  SetBody (constchar *) body= { body_ :: stdmove(string()body);} void
  AppendToBuffer (*Buffer) buffer;bool

  CloseConnection ()return { ; close_connection_} private

 :static
  const ; string server_name_;
  HttpStatusCode status_code_;
  string status_message_;
  string headers_;
  string body_;
  string type_bool
  ; close_connection_}
;}

#

endif#

3、httpresponse.cc
include"httpresponse.h" #

include# 

include# 

include"buffer.h" using

namespace ; tiny_muduousing
:: std;stringconst

:: string HttpResponse=server_name_ "Tiny_muduo" ;void

HttpResponse ::AppendToBuffer(*Buffer) bufferchar {
  [ buf32]= 0 {};snprintf

  (,bufsizeof ()buf,"HTTP/1.1 %d " ,)status_code_;Append
  buffer->()buf;Append
  buffer->()status_message_;Append
  buffer->()CRLF;if
  
  ( )close_connection_Append {
    buffer->("Connection: close\r\n");}
  else snprintf {
    (,bufsizeof ()buf,"Content-Length: %zd\r\n" ,. body_size());// no need to memset this is longer than HTTP... one Append
    buffer->()buf;Append
    buffer->("Connection: Keep-Alive\r\n");}
  Append

  buffer->("Content-Type: ");Append
  buffer->()type_;Append
  buffer->()CRLF;Append

  buffer->("Server: ");Append
  buffer->()server_name_;Append
  buffer->()CRLF;Append
  buffer->()CRLF;Append

  buffer->()body_;return
  ;}
#

4、httpparsestate.h
ifndefTINY_MUDUO_HTTPSTATE_H_ #
defineTINY_MUDUO_HTTPSTATE_H_ namespace

enum tiny_muduo {

HttpRequestParseState , {
  kParseRequestLine,
  kParseHeaders,
  kParseBody,
  kParseGotCompleteRequest,
  kParseErrno}
;}

#

endif#

3、其他组件(mutex makefile等)
1、mutex
ifndefTINY_MUDUO_MUTEX_H_ #
defineTINY_MUDUO_MUTEX_H_ #

include"pthread.h" namespace

class tiny_muduo {

MutexLock public {
 :MutexLock
  ()pthread_mutex_init {
   (&,mutex_nullptr );}
  ~
  MutexLock()pthread_mutex_destroy {
   (&)mutex_;}
  bool
  
  Lock ()return {
    pthread_mutex_lock (&)mutex_== 0 ;}
  bool

  Unlock ()return {
    pthread_mutex_unlock (&)mutex_== 0 ;} 
  *
 
  pthread_mutex_tmutex ()return { & ;mutex_} private 

 :;
  pthread_mutex_t mutex_} 
;class

MutexLockGuard public {
 :MutexLockGuard
  (&MutexLock) mutex: mutex_ ()mutex. {
    mutex_Lock();}
  ~
  MutexLockGuard(). {
    mutex_Unlock();}
  private

 :&
  MutexLock; mutex_}
;}

#
endif#

2、condition.h
ifndefTINY_MUDUO_CONDITION_H_ #
defineTINY_MUDUO_CONDITION_H_ #

include"pthread.h" #

include"mutex.h" namespace

class tiny_muduo {

Condition public {
 :Condition
  (&MutexLock) mutex: mutex_ ()mutexpthread_cond_init {
    (&,cond_nullptr );}
  ~
  Condition()pthread_cond_destroy {
    (&)cond_;}
  bool

  Wait ()int {
    = ret 0 ;=
    ret pthread_cond_wait (&,cond_. mutex_mutex());return
    == ret 0 ;}
  bool

  Signal ()return {
    pthread_cond_signal (&)cond_;}
  bool

  BroadCast ()return {
    pthread_cond_broadcast (&)cond_;}
  private

 :&
  MutexLock; mutex_;
  pthread_cond_t cond_}
;} 

#
endif#

3、latch.h
ifndefTINY_MUDUO_LATCH_H_ #
defineTINY_MUDUO_LATCH_H_ #

include"mutex.h" #
include"condition.h" namespace

class tiny_muduo {

Latch public {
 :Latch
  (int) count: count_ ()count,mutex_ (),cond_ ()mutex_} {void

  CountDown ()lock {
    MutexLockGuard ()mutex_;--
    ;count_if
    ( ==count_ 0 ). {
      cond_BroadCast();}
    }  
  void

  Wait ()lock {
    MutexLockGuard ()mutex_;while
    ( 0count_ > ). {
      cond_Wait();}
    }
  private

 :int
  ; count_;
  MutexLock mutex_;
  Condition cond_}
;}

#
endif#

4、callback.h
ifndefTINY_MUDUO_CALLBACK_H_ #
defineTINY_MUDUO_CALLBACK_H_ #

include# 
includeusing 

:: std::placeholders;_1using
:: std::placeholders;_2using
:: std::placeholders;_3namespace

class tiny_muduo {
  TcpConnection ;typedef
  :: std<shared_ptr;TcpConnection> TcpConnectionPtrclass
  
  Buffer ;typedef
  :: std<functionvoid( const& TcpConnectionPtr,* Buffer);> ConnectionCallbacktypedef
  :: std<functionvoid( const& TcpConnectionPtr,* Buffer);> MessageCallbacktypedef
  :: std<functionvoid( );> ReadCallbacktypedef
  :: std<functionvoid( );> WriteCallbacktypedef
  :: std<functionvoid( const& TcpConnectionPtr);> CloseCallback}
#
endif=

5、makefile
CC ++ g=
CFLAG - -Wall =c
OBJS . main.o httpserver.o httpresponse.o httpcontent.o httprequest.o\
	   tcpserver.o acceptor.o\
	   channel.o eventloop.o epoller.o tcpconnection.o\
	   eventloopthreadpool.o eventloopthread.o thread.o buffer(o\
	   $)TFLAG=
TFLAG - :lpthread

webserver ( $)OBJS( 
	$)CC^ $- .o $@

main:o . main.cc eventloop.h address.h httpserver.h httprequest.h httpresponse.h\
		 httpresponsefile(h
	$)CC( $)CFLAG< $- .o $@
	
httpserver:o . httpserver.cc httpserver.h buffer(h
	$)CC( $)CFLAG< $- .o $@
	
httpresponse:o . httpresponse.cc httpresponse.h buffer(h
	$)CC( $)CFLAG< $- .o $@

httpcontent:o . httpcontent.cc httpcontent.h httprequest.h httpparsestate(h
	$)CC( $)CFLAG< $- .o $@

httprequest:o . httprequest.cc httprequest.h httpparsestate(h
	$)CC( $)CFLAG< $- .o $@

tcpserver:o . tcpserver.cc tcpserver.h acceptor.h tcpconnection.h\
			  eventloopthreadpool(h
	$)CC( $)CFLAG< $- .o $@
	
acceptor:o . acceptor.cc acceptor.h address.h channel(h
	$)CC( $)CFLAG< $- .o $@
	
channel:o . channel.cc channel(h
	$)CC( $)CFLAG< $- .o $@

eventloop:o . eventloop.cc eventloop.h channel.h mutex(h
	$)CC( $)CFLAG< $- .o $@

eventloopthreadpool:o . eventloopthreadpool.cc eventloopthreadpool.h eventloopthread(h
	$)CC( $)CFLAG< $- .o $@
	
eventloopthread:o . eventloopthread.cc eventloopthreadpool.h mutex.h\
					condition.h eventloop(h
	$)CC( $)CFLAG< $- .o $@

thread:o . thread.cc thread.h latch(h
	$)CC( $)CFLAG< $- .o $@
	
epoller:o . epoller.cc epoller.h channel(h
	$)CC( $)CFLAG< $- .o $@
	
tcpconnection:o . tcpconnection.cc tcpconnection.h \
					 channel.h buffer.h httpcontent(h
	$)CC( $)CFLAG< $- .o $@
	
buffer:o . buffer.cc buffer(h
	$)CC( $)CFLAG< $- .o $@

:PHONY : clean
clean*
	rm .o

结束语

哎 路还有很长的路要走 IO库 定时器
可能还要重构HTTPserver的逻辑处理 后面还要可能修改epoll的工作状态

但是毕竟走到现在了 还是得坚持下去 之后再回头看看这里 可能也觉得别有一番感觉 哈哈

各位下一篇见了~

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/578806.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-11
下一篇 2022-04-11

发表评论

登录后才能评论

评论列表(0条)

保存