From a9501d10847d7993fad2e0778fe9c11317b4f7be Mon Sep 17 00:00:00 2001 From: Guangxiong Lin Date: Thu, 1 Dec 2022 23:20:33 +0800 Subject: Simplify logic by structure --- Makefile | 4 +-- client.c | 4 +-- common.c | 8 ------ common.h | 1 - eventloop.c | 39 +++++++++++++++++++++++++ eventloop.h | 22 ++++++++++++++ server.c | 96 ++++++++++++++++++++++++++++++++++++++++--------------------- tsocket.c | 60 ++++++++++++++++++++++++++++++++++++++ tsocket.h | 18 ++++++++++++ util.c | 22 ++++++++++++++ util.h | 10 +++++++ 11 files changed, 239 insertions(+), 45 deletions(-) delete mode 100644 common.c delete mode 100644 common.h create mode 100644 eventloop.c create mode 100644 eventloop.h create mode 100644 tsocket.c create mode 100644 tsocket.h create mode 100644 util.c create mode 100644 util.h diff --git a/Makefile b/Makefile index eee72d1..2a0167a 100644 --- a/Makefile +++ b/Makefile @@ -10,8 +10,8 @@ clean: %.o: %.c $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ -client: client.o common.o +client: client.o util.o $(CC) -o $@ $^ -server: server.o common.o +server: server.o util.o eventloop.o tsocket.o $(CC) -o $@ $^ diff --git a/client.c b/client.c index 9e3a421..0b9cbfe 100644 --- a/client.c +++ b/client.c @@ -6,7 +6,7 @@ #include #include -#include "common.h" +#include "util.h" int main() @@ -24,7 +24,7 @@ main() if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) panic("socket connect error"); - while (true) { + for (;;) { char buf[1024]; bzero(&buf, sizeof(buf)); scanf("%s", buf); diff --git a/common.c b/common.c deleted file mode 100644 index 154e60d..0000000 --- a/common.c +++ /dev/null @@ -1,8 +0,0 @@ -#include -#include - -void panic(const char *msg) -{ - perror(msg); - exit(EXIT_FAILURE); -} diff --git a/common.h b/common.h deleted file mode 100644 index fbb7267..0000000 --- a/common.h +++ /dev/null @@ -1 +0,0 @@ -void panic(const char *); diff --git a/eventloop.c b/eventloop.c new file mode 100644 index 0000000..f79114d --- /dev/null +++ b/eventloop.c @@ -0,0 +1,39 @@ +#include +#include +#include "eventloop.h" + +struct eventLoop *eventLoopNew() +{ + int epollfd = epoll_create1(0); + if (epollfd == -1) + return NULL; + + struct eventLoop *eventLoop = malloc(sizeof(*eventLoop)); + eventLoop->epollfd = epollfd; + eventLoop->size = EVENT_LOOP_MAX_EVENTS; + + return eventLoop; +} + +int eventLoopAddSocket(struct eventLoop *el, struct tsocket *sock, int flag) +{ + struct epoll_event ev; + ev.events = flag; + ev.data.fd = sock->fd; + + // TODO: How the fd ranges? Will it be larger than the MAX_EVENTS? + el->socks[sock->fd] = sock; + + return epoll_ctl(el->epollfd, EPOLL_CTL_ADD, sock->fd, &ev); +} + +int eventLoopWait(struct eventLoop *el, int timeout) +{ + return epoll_wait(el->epollfd, el->events, el->size, timeout); +} + +struct tsocket *eventLoopGetSocket(struct eventLoop *el, int index) +{ + int fd = el->events[index].data.fd; + return el->socks[fd]; +} diff --git a/eventloop.h b/eventloop.h new file mode 100644 index 0000000..39c05d5 --- /dev/null +++ b/eventloop.h @@ -0,0 +1,22 @@ +#include + +#include "tsocket.h" + +#ifndef __EVENT_LOOP_H +#define __EVENT_LOOP_H + +#define EVENT_LOOP_MAX_EVENTS 1024 + +struct eventLoop { + int epollfd; + struct epoll_event events[EVENT_LOOP_MAX_EVENTS]; + struct tsocket *socks[EVENT_LOOP_MAX_EVENTS]; + int size; +}; + +struct eventLoop *eventLoopNew(); +int eventLoopAddSocket(struct eventLoop *el, struct tsocket *sock, int flag); +int eventLoopWait(struct eventLoop *el, int timeout); +struct tsocket *eventLoopGetSocket(struct eventLoop *el, int index); + +#endif diff --git a/server.c b/server.c index 63f3062..1e3ad68 100644 --- a/server.c +++ b/server.c @@ -7,51 +7,83 @@ #include #include #include +#include +#include -#include "common.h" +#include "eventloop.h" +#include "tsocket.h" +#include "util.h" + +#define READ_BUFFER_SIZE 1024 + +void handleEvent(struct tsocket *sock) +{ + char buf[READ_BUFFER_SIZE]; + ssize_t n_read_bytes; + + for (;;) { + n_read_bytes = read(sock->fd, buf, sizeof(buf)); + if (n_read_bytes > 0) { + printf("message from conn %d: %s\n", sock->fd, buf); + write(sock->fd, buf, sizeof(buf)); + } else if (n_read_bytes == 0) { + printf("conn %d disconnected\n", sock->fd); + tsocketDelete(sock); + break; + } else if (n_read_bytes == -1) { + if (errno == EAGAIN || errno == EWOULDBLOCK) + break; + } + } +} int main() { - int sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (sockfd == -1) + struct tsocket *sock = tsocketNew(); + if (sock == NULL) panic("socket creation error"); - struct sockaddr_in serv_addr; - bzero(&serv_addr, sizeof(serv_addr)); - serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); - serv_addr.sin_port = htons(8888); - - if (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) + if (tsocketBind(sock, "127.0.0.1", 8888) == -1) panic("socket bind error"); - if (listen(sockfd, SOMAXCONN) == -1) + if (tsocketListen(sock) == -1) panic("socket listen error"); - struct sockaddr_in clnt_addr; - socklen_t clnt_addr_len = sizeof(clnt_addr); - bzero(&clnt_addr, sizeof(clnt_addr)); + struct eventLoop *el = eventLoopNew(); + if (el == NULL) + panic("eventloop creation"); - int clnt_sockfd = accept(sockfd, (struct sockaddr *)&clnt_addr, &clnt_addr_len); - if (clnt_sockfd == -1) - panic("socket accept error"); + if (eventLoopAddSocket(el, sock, EPOLLIN) == -1) + panic("eventloop add fd"); - printf("New client fd %d, ip: %s, port: %d\n", clnt_sockfd, inet_ntoa(clnt_addr.sin_addr), ntohs(clnt_addr.sin_port)); + int nfds; + struct tsocket *conn_sock; + for (;;) { + nfds = eventLoopWait(el, -1); + if (nfds == -1) + panic("eventloop wait"); - while (true) { - char buf[1024]; - bzero(&buf, sizeof(buf)); - ssize_t n_read_bytes = read(clnt_sockfd, buf, sizeof(buf)); - if (n_read_bytes > 0) { - printf("message from client fd %d: %s\n", clnt_sockfd, buf); - write(clnt_sockfd, buf, sizeof(buf)); - } else if (n_read_bytes == 0) { - printf("client fd %d disconnected\n", clnt_sockfd); - close(clnt_sockfd); - break; - } else if (n_read_bytes == -1) { - close(clnt_sockfd); - panic("socket read error"); + for (int i = 0; i < nfds; i++) { + if (eventLoopGetSocket(el, i) == sock) { + conn_sock = tsocketAccept(sock); + if (conn_sock == NULL) + panic("socket accept error"); + + printf("New client fd %d, ip: %s, port: %d\n", + conn_sock->fd, conn_sock->addr, conn_sock->port); + + if (setblocking(conn_sock->fd, false) == -1) { + close(conn_sock->fd); + continue; + } + + if (eventLoopAddSocket(el, conn_sock, EPOLLIN | EPOLLET) == -1) + panic("eventloop add fd: conn_sockfd"); + + tsocketDelete(conn_sock); + } else { + handleEvent(eventLoopGetSocket(el, i)); + } } } } diff --git a/tsocket.c b/tsocket.c new file mode 100644 index 0000000..d1d0368 --- /dev/null +++ b/tsocket.c @@ -0,0 +1,60 @@ +#include +#include +#include +#include + +#include "tsocket.h" + +struct tsocket * +tsocketNew() +{ + int fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd == -1) + return NULL; + + struct tsocket *sock = malloc(sizeof(*sock)); + sock->fd = fd; + + return sock; +} + +int tsocketBind(struct tsocket *sock, const char *addr, int hostport) +{ + struct sockaddr_in sock_addr; + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = inet_addr(addr); + sock_addr.sin_port = htons(hostport); + + sock->addr = addr; + sock->port = hostport; + + return bind(sock->fd, (struct sockaddr *)&sock_addr, sizeof(sock_addr)); +} + +int tsocketListen(struct tsocket *sock) +{ + return listen(sock->fd, SOMAXCONN); +} + +struct tsocket *tsocketAccept(struct tsocket *sock) +{ + struct sockaddr_in addr; + socklen_t addr_len = sizeof(addr); + + int fd = accept(sock->fd, (struct sockaddr *)&addr, &addr_len); + if (fd == -1) + return NULL; + + struct tsocket *conn_sock = malloc(sizeof(*conn_sock)); + conn_sock->fd = fd; + conn_sock->addr = inet_ntoa(addr.sin_addr); + conn_sock->port = ntohs(addr.sin_port); + + return conn_sock; +} + +void tsocketDelete(struct tsocket *sock) +{ + close(sock->fd); + free(sock); +} diff --git a/tsocket.h b/tsocket.h new file mode 100644 index 0000000..5a8826c --- /dev/null +++ b/tsocket.h @@ -0,0 +1,18 @@ +#include + +#ifndef __TSOCKET_H +#define __TSOCKET_H + +struct tsocket { + int fd; + const char *addr; + int port; +}; + +struct tsocket *tsocketNew(); +int tsocketBind(struct tsocket *sock, const char *addr, int hostport); +int tsocketListen(struct tsocket *sock); +struct tsocket *tsocketAccept(struct tsocket *sock); +void tsocketDelete(struct tsocket *sock); + +#endif diff --git a/util.c b/util.c new file mode 100644 index 0000000..a44cc66 --- /dev/null +++ b/util.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include +#include + +#include "util.h" + +void panic(const char *msg) +{ + perror(msg); + exit(EXIT_FAILURE); +} + +int setblocking(int fd, bool blocking) +{ + u_long mode = blocking ? 0 : 1; + if (ioctl(fd, FIONBIO, &mode) == -1) + return ERROR; + + return OK; +} diff --git a/util.h b/util.h new file mode 100644 index 0000000..6e9c8cf --- /dev/null +++ b/util.h @@ -0,0 +1,10 @@ +#ifndef __UTIL_H +#define __UTIL_H + +#define ERROR -1 +#define OK 0 + +void panic(const char *); +int setblocking(int fd, bool blocking); + +#endif -- cgit v1.2.3