From 38d595daafadf67cca5c9fcf9a70e3615696f82d Mon Sep 17 00:00:00 2001 From: lianyun Date: Sun, 21 Apr 2024 12:41:06 +0800 Subject: [PATCH] feat: refactor class Epoll --- Epoll.cpp | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ Epoll.h | 24 ++++++++++++++++++++++ MakeFile | 2 +- README.md | 3 +++ Socket.cpp | 18 ++++++++--------- Socket.h | 2 +- client.cpp | 2 +- server.cpp | 30 +++++++++++++-------------- 8 files changed, 113 insertions(+), 27 deletions(-) create mode 100644 Epoll.cpp create mode 100644 Epoll.h diff --git a/Epoll.cpp b/Epoll.cpp new file mode 100644 index 0000000..e3ab0ae --- /dev/null +++ b/Epoll.cpp @@ -0,0 +1,59 @@ +#include "Epoll.h" +#include "utils.h" + + + +Epoll::Epoll(int max_fd) +{ + this->_fd = epoll_create(max_fd); + print_error(this->_fd == -1, "epoll_create failed"); + +} +Epoll::~Epoll() +{ + if (this->events != nullptr) + { + delete[] this->events; + } + ::close(this->_fd); +} + +void Epoll::ctl_add(int fd, epoll_event *ev_ptr) +{ + int ret = epoll_ctl(this->_fd, EPOLL_CTL_ADD, fd, ev_ptr); + print_error(ret == -1, "epoll_ctl add failed"); +} + +void Epoll::ctl_mod(int fd, epoll_event *ev_ptr) +{ + int ret = epoll_ctl(this->_fd, EPOLL_CTL_MOD, fd, ev_ptr); + print_error(ret == -1, "epoll_ctl mod failed"); +} + +void Epoll::ctl_del(int fd, epoll_event *ev_ptr) +{ + int ret = epoll_ctl(this->_fd, EPOLL_CTL_DEL, fd, ev_ptr); + print_error(ret == -1, "epoll_ctl del failed"); +} + +int Epoll::wait(int max_event, int timeout) +{ + if (this->events != nullptr) + { + delete[] this->events; + } + this->events = new epoll_event[max_event]; + int event_num = epoll_wait(this->_fd, events, max_event, timeout); + print_error(event_num == -1, "epoll_wait failed"); + return event_num; +} + +struct epoll_event creat_event(int fd, uint32_t events, bool is_et) +{ + struct epoll_event event; + memset(&event, 0, sizeof(event)); + event.data.fd = fd; + event.events = events; + if (is_et){ event.events |= EPOLLET; } + return event; // 怕返回的是局部變數,所以要用拷貝 +} \ No newline at end of file diff --git a/Epoll.h b/Epoll.h new file mode 100644 index 0000000..67ee533 --- /dev/null +++ b/Epoll.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include + + +using namespace std; + +class Epoll +{ + int _fd; + +public: + struct epoll_event* events = nullptr; + Epoll(int max_fd=10); + ~Epoll(); + void ctl_add(int fd, epoll_event *event); + void ctl_mod(int fd, epoll_event *event); + void ctl_del(int fd, epoll_event *event); + int wait(int max_event, int timeout=-1); +}; + +struct epoll_event create_event(int fd, uint32_t events, bool is_et); \ No newline at end of file diff --git a/MakeFile b/MakeFile index f17f031..9c53e20 100644 --- a/MakeFile +++ b/MakeFile @@ -1,4 +1,4 @@ server: @echo "Starting server..." - g++ server.cpp utils.cpp Socket.cpp -o output/server + g++ server.cpp utils.cpp Socket.cpp Epoll.cpp -o output/server g++ client.cpp utils.cpp Socket.cpp -o output/client \ No newline at end of file diff --git a/README.md b/README.md index 41c4ed6..dbc534d 100644 --- a/README.md +++ b/README.md @@ -36,5 +36,8 @@ - study epoll model, Edge Triggered and Level Triggered - 實作epoll模型 + 4/21 + - 重構socket成一個class + - 重構epoll成一個class diff --git a/Socket.cpp b/Socket.cpp index b2da54b..b40c9c7 100644 --- a/Socket.cpp +++ b/Socket.cpp @@ -16,15 +16,15 @@ using namespace std; Socket::Socket(Domain domain, Type type, int protocol) { - this->fd = socket(static_cast(domain), static_cast(type), protocol); - print_error(this->fd == -1, "Socket creation failed"); + this->_fd = socket(static_cast(domain), static_cast(type), protocol); + print_error(this->_fd == -1, "Socket creation failed"); }; Socket::~Socket() { - if (this->fd != -1) + if (this->_fd != -1) { - close(this->fd); + close(this->_fd); } }; @@ -32,7 +32,7 @@ void Socket::bind(const struct sockaddr_in &addr) { cout << "server start at " << inet_ntoa(addr.sin_addr) << ":" << ntohs(addr.sin_port) << endl; cout << "binding..." << endl; - int status = ::bind(this->fd, (const sockaddr*)&addr, sizeof(addr)); + int status = ::bind(this->_fd, (const sockaddr*)&addr, sizeof(addr)); print_error(status == -1, "Bind failed"); cout << "bind success" << endl; }; @@ -44,7 +44,7 @@ void Socket::listen(u_int16_t max_conn_sock) throw runtime_error("Max connection socket is greater than SOMAXCONN"); } cout << "listening..." << endl; - int status = ::listen(this->fd, (int)max_conn_sock); + int status = ::listen(this->_fd, (int)max_conn_sock); if (status == -1) { throw runtime_error(strerror(errno)); @@ -53,7 +53,7 @@ void Socket::listen(u_int16_t max_conn_sock) int Socket::accept(const struct sockaddr_in &client_addr){ socklen_t s_len = sizeof(client_addr); - int client_fd = ::accept(this->fd, (sockaddr *)&client_addr, &s_len); + int client_fd = ::accept(this->_fd, (sockaddr *)&client_addr, &s_len); print_error(client_fd == -1, "Accept failed"); printf("new client fd %d! IP: %s Port: %d\n", client_fd, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); return client_fd; @@ -61,14 +61,14 @@ int Socket::accept(const struct sockaddr_in &client_addr){ void Socket::connect(const struct sockaddr_in &addr){ cout << "connecting..." << endl; - int status = ::connect(this->fd, (sockaddr *)&addr, sizeof(addr)); + int status = ::connect(this->_fd, (sockaddr *)&addr, sizeof(addr)); print_error(status == -1, "Connect failed"); }; int Socket::get_fd() { - return this->fd; + return this->_fd; }; diff --git a/Socket.h b/Socket.h index 3a17155..c46baf2 100644 --- a/Socket.h +++ b/Socket.h @@ -18,7 +18,7 @@ enum class Type class Socket { - int fd = -1; + int _fd = -1; public: Socket(Domain domain, Type type, int protocol=0); ~Socket(); diff --git a/client.cpp b/client.cpp index 89ed138..26d9ac9 100644 --- a/client.cpp +++ b/client.cpp @@ -44,7 +44,7 @@ int main(){ close(client->get_fd()); } else if (read_bytes == 0){ cout << "EOF" << endl; - + break; }else{ cout << "echo : " << buff <bind(serv_addr); server->listen(); - int epfd = epoll_create(5); // create epoll instance + Epoll epoll = Epoll(5); - int max_events = 1024; - struct epoll_event ev, events[max_events]; + struct epoll_event ev; ev.events = EPOLLIN | EPOLLET; // set epoll event to read and edge-triggered ev.data.fd = server->get_fd(); - epoll_ctl(epfd, EPOLL_CTL_ADD, server->get_fd(), &ev); // add socket_fd to epoll instance - int epoll_status = epoll_ctl(epfd, EPOLL_CTL_ADD, server->get_fd(), &ev); // add socket_fd to epoll instance + + + epoll.ctl_add(server->get_fd(), &ev); + while(true) { - int event_num = epoll_wait(epfd, events, max_events, -1); // wait for epoll event + int event_num = epoll.wait(1024); for(int i = 0; i < event_num; i++) { - if(events[i].data.fd == server->get_fd()) // if the event is from socket_fd, it means there is a new client + if(epoll.events[i].data.fd == server->get_fd()) // if the event is from socket_fd, it means there is a new client { 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 = server->accept(clit_addr); - printf("new client fd %d! IP: %s Port: %d\n", clit_socket_fd, inet_ntoa(clit_addr.sin_addr), ntohs(clit_addr.sin_port)); + set_non_blocking(clit_socket_fd); struct epoll_event ev_c; ev_c.events = EPOLLIN | EPOLLET; // set epoll event to read and edge-triggered ev_c.data.fd = clit_socket_fd; - fcntl(clit_socket_fd, F_SETFL, fcntl(clit_socket_fd, F_GETFL, 0) | O_NONBLOCK); // set socket_fd to non-blocking mode - epoll_ctl(epfd, EPOLL_CTL_ADD, clit_socket_fd, &ev_c); // add socket_fd to epoll instance + epoll.ctl_add(clit_socket_fd, &ev_c); cout << "add client" << endl; - }else if (events[i].events == EPOLLIN){ + }else if (epoll.events[i].events == EPOLLIN){ while(true){ char buff[1024]; memset(buff, 0, sizeof(buff)); - ssize_t read_bytes = recv(events[i].data.fd, buff, sizeof(buff), 0); + ssize_t read_bytes = recv(epoll.events[i].data.fd, buff, sizeof(buff), 0); if (read_bytes > 0){ cout <<"get message from client : "<< buff <