Skip to content

Commit

Permalink
feat: refactor class Epoll
Browse files Browse the repository at this point in the history
  • Loading branch information
lianyun0502 committed Apr 21, 2024
1 parent 6a1fb25 commit 38d595d
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 27 deletions.
59 changes: 59 additions & 0 deletions Epoll.cpp
Original file line number Diff line number Diff line change
@@ -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; // 怕返回的是局部變數,所以要用拷貝
}
24 changes: 24 additions & 0 deletions Epoll.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#pragma once

#include <sys/epoll.h>
#include <string>
#include <cstring>


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);
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 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
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,8 @@
- study epoll model, Edge Triggered and Level Triggered
- 實作epoll模型

4/21
- 重構socket成一個class
- 重構epoll成一個class


18 changes: 9 additions & 9 deletions Socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,23 @@ using namespace std;

Socket::Socket(Domain domain, Type type, int protocol)
{
this->fd = socket(static_cast<int>(domain), static_cast<int>(type), protocol);
print_error(this->fd == -1, "Socket creation failed");
this->_fd = socket(static_cast<int>(domain), static_cast<int>(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);
}
};

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;
};
Expand All @@ -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));
Expand All @@ -53,22 +53,22 @@ 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;
};

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;
};


Expand Down
2 changes: 1 addition & 1 deletion Socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ int main(){
close(client->get_fd());
} else if (read_bytes == 0){
cout << "EOF" << endl;

break;
}else{
cout << "echo : " << buff <<endl;
}
Expand Down
30 changes: 15 additions & 15 deletions server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include "utils.h"
#include "Socket.h"
#include "Epoll.h"
using namespace std;


Expand All @@ -21,7 +22,6 @@ uint16_t port = 8888;


int main(){
// int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
Socket *server = new Socket(Domain::IPv4, Type::TCP);
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
Expand All @@ -31,45 +31,45 @@ int main(){
server->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 <<endl;
send(events[i].data.fd, buff, sizeof(buff), 0);
send(epoll.events[i].data.fd, buff, sizeof(buff), 0);
} else if (read_bytes == -1 && errno == EINTR){
// client normal interrupt;
cout <<"interrupted "<< buff <<endl;
Expand All @@ -80,7 +80,7 @@ int main(){
break;
} else if (read_bytes == 0){
cout << "End of file" << endl;
close(events[i].data.fd);
close(epoll.events[i].data.fd);
break;
}
}
Expand Down

0 comments on commit 38d595d

Please sign in to comment.