Channel.hpp
cpp
复制代码
#pragma once
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <memory>
#include <functional>
#include "Common.hpp"
#include "Connection.hpp"
#include "Log.hpp"
#include "InetAddr.hpp"
using namespace LogModule;
#define SIZE 1024
// 普通sockfd的封装
class Channel : public Connection
{
public:
Channel(int sockfd, const InetAddr &client) : _sockfd(sockfd), _client_addr(client)
{
SetNonBlock(_sockfd);
}
void Recver() override
{
// 我们读到的是字符串
char buffer[SIZE];
while (true)
{
buffer[0] = 0; // 清空字符串
ssize_t n = recv(_sockfd, buffer, sizeof(buffer) - 1, 0); // 非阻塞读取的
if (n > 0)
{
buffer[n] = 0;
_inbuffer += buffer; // 接受缓冲区中,入队列的过程
}
else if (n == 0)
{
Excepter();
return;
}
else
{
if (errno == EAGAIN || errno == EWOULDBLOCK)
{
break;
}
else if (errno == EINTR)
{
continue;
}
else
{
Excepter();
return;
}
}
}
LOG(LogLevel::DEBUG) << "Channel: Inbuffer:\n"
<< _inbuffer;
if (!_inbuffer.empty())
_outbuffer += _handler(_inbuffer); // 和protocol相关的匿名函数里面!
if (!_outbuffer.empty())
{
Sender(); // 最佳实践
//GetOwner()->EnableReadWrite(_sockfd, true, true);
}
}
void Sender() override
{
while (true)
{
ssize_t n = send(_sockfd, _outbuffer.c_str(), _outbuffer.size(), 0);
if (n > 0)
{
_outbuffer.erase(0, n);
if (_outbuffer.empty())
break;
}
else if (n == 0)
{
break;
}
else
{
if (errno == EAGAIN || errno == EWOULDBLOCK)
break;
if (errno == EINTR)
continue;
else
{
Excepter();
return;
}
}
}
// 1. 数据发送完毕
// 2. 发送条件不具备
if (!_outbuffer.empty())
{
// 开启对写事件的关心
GetOwner()->EnableReadWrite(_sockfd, true, true);
}
else
{
GetOwner()->EnableReadWrite(_sockfd, true, false);
}
}
void Excepter() override
{
// 所有的异常,都被我归一到了这个函数内部!!
GetOwner()->DelConnection(_sockfd);
}
int GetSockFd() override
{
return _sockfd;
}
std::string &Inbuffer()
{
return _inbuffer;
}
void AppendOutBuffer(const std::string &out)
{
_outbuffer += out;
}
~Channel()
{
}
private:
int _sockfd;
std::string _inbuffer; // 充当缓冲区,vector<char>
std::string _outbuffer;
InetAddr _client_addr;
// handler_t _handler;
};
Connection.hpp
cpp
复制代码
#pragma once
#include <iostream>
#include <string>
#include "InetAddr.hpp"
// 封装fd,保证给每一个fd一套缓冲
class Reactor;
class Connection;
using handler_t = std::function<std::string (std::string &)>;
// 基类
class Connection
{
public:
Connection():_events(0), _owner(nullptr)
{
}
void SetEvent(const uint32_t &events)
{
_events = events;
}
uint32_t GetEvent()
{
return _events;
}
void SetOwner(Reactor *owner)
{
_owner = owner;
}
Reactor *GetOwner()
{
return _owner;
}
virtual void Recver() = 0;
virtual void Sender() = 0;
virtual void Excepter() = 0;
virtual int GetSockFd() = 0;
void RegisterHandler(handler_t handler)
{
_handler = handler;
}
~Connection()
{
}
private:
// 关心事件
uint32_t _events;
// 回指指针
Reactor *_owner;
public:
handler_t _handler; // 基类中定义了一个回调函数
};
Epoller.hpp
cpp
复制代码
#pragma once
#include <iostream>
#include <string>
#include "InetAddr.hpp"
// 封装fd,保证给每一个fd一套缓冲
class Reactor;
class Connection;
using handler_t = std::function<std::string (std::string &)>;
// 基类
class Connection
{
public:
Connection():_events(0), _owner(nullptr)
{
}
void SetEvent(const uint32_t &events)
{
_events = events;
}
uint32_t GetEvent()
{
return _events;
}
void SetOwner(Reactor *owner)
{
_owner = owner;
}
Reactor *GetOwner()
{
return _owner;
}
virtual void Recver() = 0;
virtual void Sender() = 0;
virtual void Excepter() = 0;
virtual int GetSockFd() = 0;
void RegisterHandler(handler_t handler)
{
_handler = handler;
}
~Connection()
{
}
private:
// 关心事件
uint32_t _events;
// 回指指针
Reactor *_owner;
public:
handler_t _handler; // 基类中定义了一个回调函数
};
Listener.hpp
cpp
复制代码
#pragma once
#include <iostream>
#include <memory>
#include "Epoller.hpp"
#include "Socket.hpp"
#include "Common.hpp"
#include "Connection.hpp"
#include "Channel.hpp"
using namespace SocketModule;
// Listener 专门进行获取新连接
class Listener : public Connection
{
public:
Listener(int port = defaultport)
:_port(port), _listensock(std::make_unique<TcpSocket>())
{
_listensock->BuildTcpSocketMethod(_port);
SetEvent(EPOLLIN | EPOLLET); //ET todo
SetNonBlock(_listensock->Fd());
}
~Listener()
{}
void Recver() override
{
//accept
//LOG(LogLevel::DEBUG) << "进入Listener模块的Recver函数";
InetAddr client;
while(true)
{
int sockfd = _listensock->Accept(&client);
if(sockfd == ACCEPT_ERR)
break;
else if(sockfd == ACCEPT_CONTINUE)
continue;
else if(sockfd == ACCEPT_DONE)
break;
else
{
// 我们获得的是一个合法的fd,普通的文件描述符
std::shared_ptr<Connection> conn = std::make_shared<Channel>(sockfd, client);
conn->SetEvent(EPOLLIN|EPOLLET);
if(_handler != nullptr)
conn->RegisterHandler(_handler);
GetOwner()->AddConnection(conn);
}
}
}
void Sender() override
{}
void Excepter() override
{}
int GetSockFd() override
{
return _listensock->Fd();
}
private:
int _port;
std::unique_ptr<Socket> _listensock;
};
Reactor.hpp
cpp
复制代码
#pragma once
#include <iostream>
#include <memory>
#include <unordered_map>
#include "Epoller.hpp"
#include "Connection.hpp"
#include "Log.hpp"
using namespace LogModule;
// 反应堆
class Reactor
{
static const int revs_num = 128;
private:
bool IsConnectionExistsHelper(int sockfd)
{
auto iter = _connections.find(sockfd);
if (iter == _connections.end())
return false;
else
return true;
}
bool IsConnectionExists(const std::shared_ptr<Connection> &conn)
{
return IsConnectionExistsHelper(conn->GetSockFd());
}
bool IsConnectionExists(int sockfd)
{
return IsConnectionExistsHelper(sockfd);
}
bool IsConnectionEmpty()
{
return _connections.empty();
}
int LoopOnce(int timeout)
{
return _epoller_ptr->WaitEvents(_revs, revs_num, timeout);
}
void Dispatcher(int n) // 事件派发器
{
for (int i = 0; i < n; i++)
{
int sockfd = _revs[i].data.fd; // 就绪的fd
uint32_t revents = _revs[i].events; // 就绪的事件
// 1. 将所有的异常处理,统一转化成IO错误 2. 所有的IO异常,统一转换成为一个异常处理函数
if (revents & EPOLLERR)
revents |= (EPOLLIN | EPOLLOUT); // 1. 将所有的异常处理,统一转化成IO错误
if (revents & EPOLLHUP)
revents |= (EPOLLIN | EPOLLOUT); // 1. 将所有的异常处理,统一转化成IO错误
if (revents & EPOLLIN)
{
// 读事件就绪, 用不用区分是否异常?不用
// 读事件就绪,还用不用区分是listenfd还是普通socketfd?不用
if (IsConnectionExists(sockfd))
_connections[sockfd]->Recver();
}
if (revents & EPOLLOUT)
{
// 写事件就绪
if (IsConnectionExists(sockfd))
_connections[sockfd]->Sender();
}
}
}
public:
Reactor()
: _epoller_ptr(std::make_unique<Epoller>()),
_isrunning(false)
{
}
void Loop()
{
if (IsConnectionEmpty())
return;
_isrunning = true;
int timeout = -1;
while (_isrunning)
{
PrintConnection(); //debug
int n = LoopOnce(timeout);
Dispatcher(n);
}
_isrunning = false;
}
// 该接口要把所有的新连接添加到_connections,并且,写透到epoll内核中!!!!!
void AddConnection(std::shared_ptr<Connection> &conn)
{
// 0. 不要重复添加
if (IsConnectionExists(conn))
{
LOG(LogLevel::WARNING) << "conn is exists: " << conn->GetSockFd();
return;
}
// 1. conn对应的fd和他要关心的事件,写透到内核中!
uint32_t events = conn->GetEvent();
int sockfd = conn->GetSockFd();
_epoller_ptr->AddEvent(sockfd, events);
// 2. 设置当前conn的拥有者回指指针
conn->SetOwner(this);
// 3. 将具体的connection添加到_connections
_connections[sockfd] = conn;
}
void EnableReadWrite(int sockfd, bool enableread, bool enablewrite)
{
// 0. 不要重复添加
if (!IsConnectionExists(sockfd))
{
LOG(LogLevel::WARNING) << "EnableReadWrite, conn is exists: " << sockfd;
return;
}
// 1. 修改当前sockfd对应的connection关心的事件
uint32_t new_event = (EPOLLET | (enableread ? EPOLLIN : 0) | (enablewrite ? EPOLLOUT:0));
_connections[sockfd]->SetEvent(new_event);
// 2. 写透到内核,调整sockfd对特定事件的关心
_epoller_ptr->ModEvent(sockfd, new_event);
}
void DelConnection(int sockfd)
{
//1. epoll移除的时候,sockfd必须是合法的
_epoller_ptr->DelEvent(sockfd);
//2. 从_connections移除自己
_connections.erase(sockfd);
//3. 关闭不要的sockfd
close(sockfd);
LOG(LogLevel::INFO) << "client quit: " << sockfd;
}
void Stop()
{
_isrunning = false;
}
void PrintConnection()
{
std::cout << "当前Reactor正在进行管理的fd List:";
for(auto &conn : _connections)
{
std::cout << conn.second->GetSockFd() << " ";
}
std::cout << "\r\n";
}
~Reactor()
{
}
private:
// 1. epoll模型
std::unique_ptr<Epoller> _epoller_ptr;
// 2. 是否启动
bool _isrunning;
// 3. 管理所有的connection,本质是管理未来所有我获取到的fd
// fd : Connection
std::unordered_map<int, std::shared_ptr<Connection>> _connections;
// 4. 就绪的所有事件
struct epoll_event _revs[revs_num];
};
main.cpp
cpp
复制代码
#include <iostream>
#include <string>
#include "Reactor.hpp"
#include "Listener.hpp"
#include "Channel.hpp"
#include "Log.hpp"
#include "Common.hpp"
#include "Protocol.hpp"
#include "NetCal.hpp"
static void Usage(std::string proc)
{
std::cerr << "Usage: " << proc << " port" << std::endl;
}
//./server port
int main(int argc, char *argv[])
{
if (argc != 2)
{
Usage(argv[0]);
exit(USAGE_ERR);
}
LogModule::ConsoleLogStrategy();
uint16_t port = std::stoi(argv[1]);
// 构建一个业务模块
std::shared_ptr<Cal> cal = std::make_shared<Cal>();
// 构建协议对象
std::shared_ptr<Protocol> protocol = std::make_shared<Protocol>([&cal](Request &req) -> Response
{ return cal->Execute(req); });
// 构建Listener对象
std::shared_ptr<Connection> conn = std::make_shared<Listener>(port);
conn->RegisterHandler([&protocol](std::string &inbuffer) -> std::string { // 这个匿名函数就是要被Channel
LOG(LogLevel::DEBUG) << "进入到匿名函数中...";
std::string response_str;
while (true)
{
std::string package;
if (!protocol->Decode(inbuffer, &package))
break;
// 我敢保证,我的packge一定是一个完整的请求,是字节流的
response_str += protocol->Execute(package);
}
LOG(LogLevel::DEBUG) << "结束匿名函数中...: " << response_str;
return response_str;
});
// 构建一个reactor模块
std::unique_ptr<Reactor> R = std::make_unique<Reactor>();
R->AddConnection(conn);
R->Loop();
return 0;
}