1 /*
2 * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <arpa/inet.h>
17 #include <assert.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <netinet/in.h>
21 #include <pthread.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/epoll.h>
26 #include <sys/resource.h>
27 #include <sys/socket.h>
28 #include <sys/time.h>
29 #include <sys/types.h>
30 #include <sys/wait.h>
31 #include <unistd.h>
32
33 #define MAXBUF 1024
34 #define MAXEPOLLSIZE 100
35
setnonblocking(int sockfd)36 int setnonblocking(int sockfd)
37 {
38 return fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK);
39 }
40
pthread_handle_message(void * sock_fd)41 void *pthread_handle_message(void *sock_fd)
42 {
43 char recvbuf[MAXBUF + 1];
44 char sendbuf[MAXBUF + 1];
45 int ret;
46 int new_fd;
47 struct sockaddr_in client_addr;
48 socklen_t cli_len = sizeof(client_addr);
49 int *sock_fd_new = (int *)sock_fd;
50 new_fd = *sock_fd_new;
51
52 bzero(recvbuf, MAXBUF + 1);
53 bzero(sendbuf, MAXBUF + 1);
54
55 do {
56 ret = recvfrom(new_fd, recvbuf, MAXBUF, 0, (struct sockaddr *)&client_addr, &cli_len);
57 if (ret > 0) {
58 printf("socket %d recv from :%s:%d success.msg=[%s]total %d bytes\n", new_fd,
59 inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), recvbuf, ret);
60 } else {
61 printf("rece msg failed.ret=%d,error code=%d,error msg=%s\n", ret, errno, strerror(errno));
62 }
63 } while (ret > 0);
64
65 fflush(stdout);
66 pthread_exit(NULL);
67 }
68
main(int argc,char ** argv)69 int main(int argc, char **argv)
70 {
71 int listener, kdpfd, nfds, n;
72 socklen_t len;
73 struct sockaddr_in my_addr;
74 unsigned int myport;
75 struct epoll_event ev;
76 struct epoll_event events[MAXEPOLLSIZE];
77 struct rlimit rt;
78
79 myport = 9999;
80
81 pthread_t thread;
82 pthread_attr_t attr;
83
84 rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE;
85 if (setrlimit(RLIMIT_NOFILE, &rt) == -1) {
86 perror("setrlimit");
87 exit(1);
88 } else {
89 printf("set param success\n");
90 }
91
92 if ((listener = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
93 perror("socket create failed.\n");
94 exit(1);
95 } else {
96 printf("socket create success\n");
97 }
98
99 int opt = SO_REUSEADDR;
100 setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
101
102 setnonblocking(listener);
103 bzero(&my_addr, sizeof(my_addr));
104 my_addr.sin_family = PF_INET;
105 my_addr.sin_port = htons(myport);
106 my_addr.sin_addr.s_addr = INADDR_ANY;
107 if (bind(listener, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
108 perror("bind");
109 exit(1);
110 } else {
111 printf("IP bind success\n");
112 }
113
114 kdpfd = epoll_create(MAXEPOLLSIZE);
115 len = sizeof(struct sockaddr_in);
116 ev.events = EPOLLIN | EPOLLET;
117 ev.data.fd = listener;
118 if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, listener, &ev) < 0) {
119 fprintf(stderr, "epoll set insertion error: fd=%d\n", listener);
120 return -1;
121 } else {
122 printf("epoll add success\n");
123 }
124
125 while (1) {
126 nfds = epoll_wait(kdpfd, events, 10000, -1);
127 if (nfds == -1) {
128 perror("epoll_wait");
129 break;
130 }
131
132 for (n = 0; n < nfds; ++n) {
133 if (events[n].data.fd == listener) {
134 pthread_attr_init(&attr);
135 pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
136
137 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
138
139 if (pthread_create(&thread, &attr, pthread_handle_message, (void *)&(events[n].data.fd))) {
140 perror("pthread_creat error!");
141 exit(-1);
142 }
143 }
144 }
145 }
146 close(listener);
147 return 0;
148 }