1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
| #include <stdio.h> // fprintf #include <sys/event.h> // kqueue #include <netdb.h> // addrinfo #include <arpa/inet.h> // AF_INET #include <sys/socket.h> // socket #include <assert.h> // assert #include <string.h> // bzero #include <stdbool.h> // bool #include <unistd.h> // close
const size_t BUF_SIZE = 1024; static bool s_stop = true; // 信号处理函数 static void handle_signal(int sig) { s_stop = false; }
int learn_kqueue(const char* ip, int32_t port) { std::cout << "ip: " << ip << " port: " << port << std::endl; signal(SIGTERM, handle_signal); int sock = socket(PF_INET, SOCK_STREAM, 0); assert(sock > 0);
// 强制使用TIME_WAIT状态的socket地址 int reuse = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
struct sockaddr_in address; bzero(&address, sizeof(address)); address.sin_family = AF_INET; inet_pton(AF_INET, ip, &address.sin_addr); //主机序转网络序ip address.sin_port = htons(port); //主机序转网络序
int ret = bind(sock, (struct sockaddr*)&address, sizeof(address)); assert(ret != -1); ret = listen(sock, BACK_LOG); assert(ret != -1);
//创建一个消息队列并返回kqueue描述符 int kq = kqueue(); assert(kq != -1);
struct kevent change_list[10]; //想要监控的事件 struct kevent event_list[10]; //用于kevent返回 char buf[BUF_SIZE]; // 监听sock的读事件 EV_SET(&change_list[0], sock, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); // 监听stdin的读事件 EV_SET(&change_list[1], fileno(stdin), EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); int nevents; while (s_stop) { printf("new loop...\n"); // 等待监听事件的发生 nevents = kevent(kq, change_list, 2, event_list, 2, NULL); if (nevents < 0) { printf("kevent error.\n"); // 监听出错 } else if (nevents > 0) { printf("get events number: %d\n", nevents); for (int i = 0; i < nevents; ++i) { printf("loop index: %d\n", i); struct kevent event = event_list[i]; //监听事件的event数据结构 int clientfd = (int) event.ident; // 监听描述符 // 表示该监听描述符出错 if (event.flags & EV_ERROR) { close(clientfd); printf("EV_ERROR: %s\n", strerror(event_list[i].data)); } // 表示sock有新的连接 if (clientfd == sock) { printf("new connection\n"); struct sockaddr_in client_addr; socklen_t client_addr_len = sizeof(client_addr); int new_fd = accept(sock, (struct sockaddr *) &client_addr, &client_addr_len); char remote[INET_ADDRSTRLEN]; printf("connected with ip: %s, port: %d\n", inet_ntop(AF_INET, &client_addr.sin_addr, remote, INET_ADDRSTRLEN), ntohs(client_addr.sin_port)); } if (clientfd == fileno(stdin)) { memset(buf, 0, BUF_SIZE); fgets(buf, BUF_SIZE, stdin); printf("data from stdin: %s\n", buf); } } } } close(sock); return 0; }
|