Skip to content

Commit

Permalink
feat: add class Accpeptor for encupsulation of newconnection function
Browse files Browse the repository at this point in the history
- 寫一個新類去裝了建立新客戶端連結的流程,練習了 bind 與 function類別的用法
- 有發現 include header file的順序會造成unique_ptr的編譯錯誤,目前還不確定原因
- modify make file
  • Loading branch information
lianyun0502 committed Apr 29, 2024
1 parent bf9c6f4 commit 053f6b1
Show file tree
Hide file tree
Showing 13 changed files with 220 additions and 89 deletions.
12 changes: 11 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,15 @@
"liveshare.accessibility.accessibilityFeaturesEnabled": "on",
"liveshare.allowGuestDebugControl": true,
"liveshare.allowGuestTaskControl": true,
"liveshare.alwaysFollowHost": true
"liveshare.alwaysFollowHost": true,
"files.associations": {
"array": "cpp",
"*.tcc": "cpp",
"memory": "cpp",
"istream": "cpp",
"functional": "cpp",
"tuple": "cpp",
"utility": "cpp",
"new": "cpp"
}
}
2 changes: 1 addition & 1 deletion MakeFile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
server:
@echo "Starting server..."
g++ server.cpp src/utils.cpp src/Socket.cpp src/Epoll.cpp src/Event.cpp src/EventLoop.cpp --std c++23 -o output/server
g++ src/utils.cpp src/Socket.cpp src/Epoll.cpp src/Event.cpp src/EventLoop.cpp src/Acceptor.cpp server.cpp --std c++23 -o output/server
g++ client.cpp src/utils.cpp src/Socket.cpp -o output/client
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,6 @@
4/25
- 封裝了新的類 Event 類,用來封裝epoll_event的事件類型,因為覺得每個事件驅動的事件函數應該是與事件本身相關的,所以將事件函數封裝在Event類中


4/26
- 封裝了accpet事件的accpetor類,將各個部件都進行了封裝,解偶了各個模組並增加了可讀性與擴充性
- 目前的reactor模型是單線程的,之後會進行多線程的改進
44 changes: 16 additions & 28 deletions server.cpp
Original file line number Diff line number Diff line change
@@ -1,49 +1,37 @@
#include<iostream>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
#include<unistd.h>
#include<assert.h>
#include<errno.h>
#include<sys/epoll.h>
#include<fcntl.h>
#include<sys/types.h>
#include<unistd.h>
#include<memory>
#include<string>
#include<functional>

#include "src/utils.h"
#include "src/Socket.h"
#include "src/Epoll.h"
#include "src/EventLoop.h"
#include "src/Event.h"
#include "src/Acceptor.h"
using namespace std;


const char * addr = "0.0.0.0";
string addr = "0.0.0.0";
uint16_t port = 8888;

void test(){
auto i = inet_addr(Domain::IPv4, addr.c_str(), port);
}

int main(){
cout << __cplusplus << endl;
Socket *server = new Socket(Domain::IPv4, Type::TCP);
auto serv_addr = inet_addr(Domain::IPv4, addr, port);
server->bind(*serv_addr.get());
server->listen();

Epoll *epoll = new Epoll(5);
// auto ev = gen_epoll_event(server->get_fd(), EPOLLIN | EPOLLET);
Event *event = new Event(epoll, server->get_fd(), EPOLLIN | EPOLLET);
auto ev = event->gen_epoll_event();
auto cb = bind(accept_connection_handler, server, epoll);
event->set_callback(cb);
epoll->ctl_add(server->get_fd(), ev.get());
EventLoop * loop = new EventLoop(epoll);
Acceptor *acceptor = new Acceptor(loop, addr, port);

EventLoop * loop = new EventLoop(epoll, server);
auto cb = bind(accept_connection_handler, placeholders::_1, epoll);
acceptor->set_connection_handler(cb);

loop->run();

delete event;
delete server;

delete acceptor;
delete epoll;
delete loop;
return 0;
}
}
82 changes: 82 additions & 0 deletions src/Acceptor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include "Acceptor.h"

#include <string>
#include <functional>
#include <memory>

using namespace std;


void et_read_event_handler(int read_fd){
while(true){
char buff[1024];
memset(buff, 0, sizeof(buff));
ssize_t read_bytes = recv(read_fd, buff, sizeof(buff), 0);
// printf("read_bytes: %ld\n", read_bytes);
if (read_bytes > 0){
cout <<"get message from client : "<< buff <<";"<<endl;
send(read_fd, buff, sizeof(buff), 0);
} else if (read_bytes == -1 && errno == EINTR){
// client normal interrupt;
cout <<"interrupted "<< buff <<endl;
continue;
} else if (read_bytes == -1 &&(errno == EAGAIN || errno == EWOULDBLOCK)){
// data is all recived
cout <<"message end! "<< buff <<endl;
break;
} else if (read_bytes == 0){
cout << "End of file" << endl;
close(read_fd);
break;
}
}
}
void accept_connection_handler(Socket* socket, Epoll *epoll){
cout << "new client connected" << endl;
struct sockaddr_in clit_addr;
socklen_t clit_sock_len = sizeof(clit_addr);
memset(&clit_addr, 0, clit_sock_len);

int clit_socket_fd = socket->accept(clit_addr);
set_non_blocking(clit_socket_fd);

// auto ev_c = gen_epoll_event(clit_socket_fd, EPOLLIN | EPOLLET);
Event* e = new Event(epoll, clit_socket_fd, EPOLLIN | EPOLLET); // 有內存洩漏風險
auto ev_c = e->gen_epoll_event();
auto cb = bind(et_read_event_handler, clit_socket_fd);
e->set_callback(cb);
epoll->ctl_add(clit_socket_fd, ev_c.get());
cout << "add client" << endl;
}

Acceptor::Acceptor(EventLoop* ev_lp, string& addr, u_int16_t port, Domain domain, Type type): _loop(ev_lp)
{
cout << "Acceptor created" << endl;
_sock = new Socket(domain, type);
auto serv_addr = inet_addr(domain, addr.c_str(), port);
_sock->bind(*serv_addr.get());
_sock->listen();

_event = new Event(_sock->get_fd(), EPOLLIN | EPOLLET);
_loop->add_event(*_event);
auto cb = bind(&Acceptor::new_connection, this);
_event->set_callback(cb);

}
Acceptor::~Acceptor()
{
delete _sock;
delete _event;
::close(_sock->get_fd());
cout << "Acceptor destroyed" << endl;
}

void Acceptor::set_connection_handler(function<void (Socket*)> connection_handler)
{
new_connection_callback = connection_handler;
}

void Acceptor::new_connection()
{
new_connection_callback(_sock);
}
33 changes: 33 additions & 0 deletions src/Acceptor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma once
#include <iostream>
#include <string>
#include <functional>
#include <memory>


#include "utils.h"
#include "Socket.h" // 不放在 utils.h 後面會有編譯錯誤error: ‘unique_ptr’ does not name a type,原因不明
#include "Event.h"
#include "EventLoop.h"


using namespace std;

class Acceptor
{
Socket* _sock;
Event* _event; // connection accpet event
EventLoop* _loop;
function<void (Socket*)> new_connection_callback;

public:
Acceptor(EventLoop* ev_lp, string& addr, u_int16_t port, Domain domain=Domain::IPv4, Type type = Type::TCP);
~Acceptor();
void set_connection_handler(function<void (Socket*)> connection_handler);
void new_connection();
};


void et_read_event_handler(int read_fd);
void accept_connection_handler(Socket* socket, Epoll* epoll);

2 changes: 1 addition & 1 deletion src/Epoll.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ using namespace std;

class Epoll
{
int _fd;
int _fd; // epoll fd

public:
struct epoll_event* _events = nullptr;
Expand Down
3 changes: 3 additions & 0 deletions src/Event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
Event::Event(Epoll* epoll, int fd, uint32_t events):_ep(epoll), _fd(fd), _events(events){
_callback = [](){cout << "default callback" << endl;};
}
Event::Event(int fd, uint32_t events): _fd(fd), _events(events){
_callback = [](){cout << "default callback" << endl;};
}

Event::~Event(){cout << "Event destructor" << endl;}

Expand Down
5 changes: 3 additions & 2 deletions src/Event.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ using namespace std;
class Event
{
Epoll* _ep = nullptr; //記錄這是屬於哪個epoll
int _fd = -1;
uint32_t _events = 0;
int _fd = -1; // 監聽的文件描述符
uint32_t _events = 0; // 監聽的事件類型 bitmap
function<void()> _callback;
public:
Event(Epoll *epoll, int fd, uint32_t events);
Event(int fd, uint32_t events);
~Event();
void run_event_handle();
int get_fd();
Expand Down
93 changes: 51 additions & 42 deletions src/EventLoop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@

using namespace std;

EventLoop::EventLoop(Epoll* epoll, Socket* socket):_epoll(epoll), _socket(socket)
{

}
EventLoop::EventLoop(Epoll* epoll):_epoll(epoll){}

EventLoop::~EventLoop() {
// Close the epoll file descriptor
Expand All @@ -26,45 +23,57 @@ void EventLoop::run() {
}
}

void accept_connection_handler(Socket* socket, Epoll *epoll){
cout << "new client connected" << endl;
struct sockaddr_in clit_addr;
socklen_t clit_sock_len = sizeof(clit_addr);
memset(&clit_addr, 0, clit_sock_len);
void EventLoop::add_event(Event& event) {
_epoll->ctl_add(event.get_fd(), event.gen_epoll_event().get());
}

int clit_socket_fd = socket->accept(clit_addr);
set_non_blocking(clit_socket_fd);
void EventLoop::remove_event(Event& event) {
_epoll->ctl_del(event.get_fd(), event.gen_epoll_event().get());
}

// auto ev_c = gen_epoll_event(clit_socket_fd, EPOLLIN | EPOLLET);
Event* e = new Event(epoll, clit_socket_fd, EPOLLIN | EPOLLET); // 有內存洩漏風險
auto ev_c = e->gen_epoll_event();
auto cb = bind(et_read_event_handler, clit_socket_fd);
e->set_callback(cb);
epoll->ctl_add(clit_socket_fd, ev_c.get());
cout << "add client" << endl;
void EventLoop::modify_event(Event& event) {
_epoll->ctl_mod(event.get_fd(), event.gen_epoll_event().get());
}

void et_read_event_handler(int read_fd){
while(true){
char buff[1024];
memset(buff, 0, sizeof(buff));
ssize_t read_bytes = recv(read_fd, buff, sizeof(buff), 0);
// printf("read_bytes: %ld\n", read_bytes);
if (read_bytes > 0){
cout <<"get message from client : "<< buff <<";"<<endl;
send(read_fd, buff, sizeof(buff), 0);
} else if (read_bytes == -1 && errno == EINTR){
// client normal interrupt;
cout <<"interrupted "<< buff <<endl;
continue;
} else if (read_bytes == -1 &&(errno == EAGAIN || errno == EWOULDBLOCK)){
// data is all recived
cout <<"message end! "<< buff <<endl;
break;
} else if (read_bytes == 0){
cout << "End of file" << endl;
close(read_fd);
break;
}
}
}
// void accept_connection_handler(Socket* socket, Epoll *epoll){
// cout << "new client connected" << endl;
// struct sockaddr_in clit_addr;
// socklen_t clit_sock_len = sizeof(clit_addr);
// memset(&clit_addr, 0, clit_sock_len);

// int clit_socket_fd = socket->accept(clit_addr);
// set_non_blocking(clit_socket_fd);

// // auto ev_c = gen_epoll_event(clit_socket_fd, EPOLLIN | EPOLLET);
// Event* e = new Event(epoll, clit_socket_fd, EPOLLIN | EPOLLET); // 有內存洩漏風險
// auto ev_c = e->gen_epoll_event();
// auto cb = bind(et_read_event_handler, clit_socket_fd);
// e->set_callback(cb);
// epoll->ctl_add(clit_socket_fd, ev_c.get());
// cout << "add client" << endl;
// }

// void et_read_event_handler(int read_fd){
// while(true){
// char buff[1024];
// memset(buff, 0, sizeof(buff));
// ssize_t read_bytes = recv(read_fd, buff, sizeof(buff), 0);
// // printf("read_bytes: %ld\n", read_bytes);
// if (read_bytes > 0){
// cout <<"get message from client : "<< buff <<";"<<endl;
// send(read_fd, buff, sizeof(buff), 0);
// } else if (read_bytes == -1 && errno == EINTR){
// // client normal interrupt;
// cout <<"interrupted "<< buff <<endl;
// continue;
// } else if (read_bytes == -1 &&(errno == EAGAIN || errno == EWOULDBLOCK)){
// // data is all recived
// cout <<"message end! "<< buff <<endl;
// break;
// } else if (read_bytes == 0){
// cout << "End of file" << endl;
// close(read_fd);
// break;
// }
// }
// }
11 changes: 6 additions & 5 deletions src/EventLoop.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,18 @@

using namespace std;


class EventLoop
{
Epoll* _epoll;
Socket* _socket;

public:
EventLoop(Epoll *epoll, Socket *_socket);
EventLoop(Epoll *epoll);
~EventLoop();
void run();
void add_event(Event& event);
void remove_event(Event& event);
void modify_event(Event& event);
};

void et_read_event_handler(int read_fd);
void accept_connection_handler(Socket* socket, Epoll* epoll);
// void et_read_event_handler(int read_fd);
// void accept_connection_handler(Socket* socket, Epoll* epoll);
Loading

0 comments on commit 053f6b1

Please sign in to comment.