//// Created by chenshun on 2022/3/21.//#include <sys/socket.h>#include <sys/event.h>#include <netinet/in.h>#include <arpa/inet.h>#include <fcntl.h>#include <unistd.h>#include <stdio.h>#include <string.h>#include <stdlib.h>const size_t PAGE = 1024 * 16;const int kReadEvent = 1;const int kWriteEvent = 2;void updateEvent(int kqFd, int fd, int events) { struct kevent ke; if (events & kReadEvent) { EV_SET(&ke, fd, EVFILT_READ, EV_ADD, 0, 0, 0); kevent(kqFd, &ke, 1, NULL, 0, NULL); } if (events & kWriteEvent) { EV_SET(&ke, fd, EVFILT_WRITE, EV_ADD, 0, 0, 0); kevent(kqFd, &ke, 1, NULL, 0, NULL); }}void delEvent(int kqFd, int fd, int events) { struct kevent ke; if (events & kReadEvent) { EV_SET(&ke, fd, EVFILT_READ, EV_DELETE, 0, 0, 0); kevent(kqFd, &ke, 1, NULL, 0, NULL); } if (events & kWriteEvent) { EV_SET(&ke, fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0); kevent(kqFd, &ke, 1, NULL, 0, NULL); }}void handleAccept(int kq, int socket_fd) { struct sockaddr_storage sa; socklen_t salen = sizeof(sa); int client = accept(socket_fd, (struct sockaddr *) &sa, &salen); int flags = fcntl(client, F_GETFL, 0); fcntl(client, F_SETFL, flags | O_NONBLOCK); updateEvent(kq, client, kReadEvent);}void handleRead(int kq, int fd) { char buf[PAGE]; size_t rr = read(fd, &buf, PAGE); if (rr == 0) { delEvent(kq, fd, kReadEvent | kWriteEvent); close(fd); return; } delEvent(kq, fd, kReadEvent); if (rr == 6 && !strcmp("exit\r\n", buf)) { write(fd, "good bye!\n", strlen("good bye!\n")); close(fd); return; } printf("receive bytes: %zu, i have receive your message: %s\n", rr, buf); updateEvent(kq, fd, kWriteEvent);}void handleWrite(int kq, int fd) { char *send = "i have receive your message, expect your next message\n"; write(fd, send, strlen(send)); delEvent(kq, fd, kWriteEvent); updateEvent(kq, fd, kReadEvent);}void loop_once(int kq, int socket_fd, int waitms) { struct timespec timeout; timeout.tv_sec = waitms / 1000; timeout.tv_nsec = (waitms % 1000) * 1000 * 1000; struct kevent *event = malloc(sizeof(struct kevent *)); int retval = kevent(kq, NULL, 0, event, 20, &timeout); if (retval > 0) { printf("收到事件: %d 件\n", retval); } for (int i = 0; i < retval; i++) { struct kevent ev = event[i]; uintptr_t fd = ev.ident; if (ev.filter == EVFILT_READ) { //处理可读时间 if (fd == socket_fd) { handleAccept(kq, socket_fd); } else { handleRead(kq, (int) fd); } } if (ev.filter == EVFILT_WRITE) { //处理可写事件 handleWrite(kq, (int) fd); } } free(event);}int main() { int port = 19999; int socket_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); struct sockaddr_in *serv_addr = malloc(sizeof(struct sockaddr_in)); if (serv_addr == NULL) { printf("分配内存失败"); exit(1); } serv_addr->sin_family = AF_INET; serv_addr->sin_addr.s_addr = inet_addr("127.0.0.1"); serv_addr->sin_port = htons(port); // int on = 1; setsockopt(socket_fd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)); int flags = fcntl(socket_fd, F_GETFL, 0); fcntl(socket_fd, F_SETFL, flags | O_NONBLOCK); if (bind(socket_fd, (struct sockaddr *) serv_addr, sizeof(struct sockaddr)) < 0) { printf("bind 失败!"); exit(1); } listen(socket_fd, 20); printf("使用telnet 127.0.0.1 19999 来进行测试\n"); printf("输入exit来断开TCP链接\n"); int queue = kqueue(); //注册 updateEvent(queue, socket_fd, kReadEvent); for (;;) { loop_once(queue, socket_fd, 10000); } return 0;}