diff options
author | Guangxiong Lin <[email protected]> | 2022-12-01 23:20:33 +0800 |
---|---|---|
committer | Guangxiong Lin <[email protected]> | 2022-12-01 23:20:33 +0800 |
commit | a9501d10847d7993fad2e0778fe9c11317b4f7be (patch) | |
tree | 470302a8a27b460c7f1fc5411e9f8dac0707743f | |
parent | 122a69f715acfe73963a2347cbb335e41bce944c (diff) | |
download | tinyserver-a9501d10847d7993fad2e0778fe9c11317b4f7be.tar.gz tinyserver-a9501d10847d7993fad2e0778fe9c11317b4f7be.tar.bz2 tinyserver-a9501d10847d7993fad2e0778fe9c11317b4f7be.zip |
Simplify logic by structure
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | client.c | 4 | ||||
-rw-r--r-- | common.c | 8 | ||||
-rw-r--r-- | common.h | 1 | ||||
-rw-r--r-- | eventloop.c | 39 | ||||
-rw-r--r-- | eventloop.h | 22 | ||||
-rw-r--r-- | server.c | 96 | ||||
-rw-r--r-- | tsocket.c | 60 | ||||
-rw-r--r-- | tsocket.h | 18 | ||||
-rw-r--r-- | util.c | 22 | ||||
-rw-r--r-- | util.h | 10 |
11 files changed, 239 insertions, 45 deletions
@@ -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 $@ $^ @@ -6,7 +6,7 @@ #include <stdbool.h> #include <stdio.h> -#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 <stdlib.h> -#include <stdio.h> - -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 <stdlib.h> +#include <sys/epoll.h> +#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 <sys/epoll.h> + +#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 @@ -7,51 +7,83 @@ #include <stdio.h> #include <sys/types.h> #include <unistd.h> +#include <sys/epoll.h> +#include <errno.h> -#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 <arpa/inet.h> +#include <stdlib.h> +#include <sys/socket.h> +#include <unistd.h> + +#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 <netinet/in.h> + +#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 @@ -0,0 +1,22 @@ +#include <stdlib.h> +#include <stdbool.h> +#include <stdio.h> +#include <sys/ioctl.h> +#include <sys/types.h> + +#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; +} @@ -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 |