aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuangxiong Lin <[email protected]>2022-12-01 23:20:33 +0800
committerGuangxiong Lin <[email protected]>2022-12-01 23:20:33 +0800
commita9501d10847d7993fad2e0778fe9c11317b4f7be (patch)
tree470302a8a27b460c7f1fc5411e9f8dac0707743f
parent122a69f715acfe73963a2347cbb335e41bce944c (diff)
downloadtinyserver-a9501d10847d7993fad2e0778fe9c11317b4f7be.tar.gz
tinyserver-a9501d10847d7993fad2e0778fe9c11317b4f7be.tar.bz2
tinyserver-a9501d10847d7993fad2e0778fe9c11317b4f7be.zip
Simplify logic by structure
-rw-r--r--Makefile4
-rw-r--r--client.c4
-rw-r--r--common.c8
-rw-r--r--common.h1
-rw-r--r--eventloop.c39
-rw-r--r--eventloop.h22
-rw-r--r--server.c96
-rw-r--r--tsocket.c60
-rw-r--r--tsocket.h18
-rw-r--r--util.c22
-rw-r--r--util.h10
11 files changed, 239 insertions, 45 deletions
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 <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
diff --git a/server.c b/server.c
index 63f3062..1e3ad68 100644
--- a/server.c
+++ b/server.c
@@ -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
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 <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;
+}
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