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;
72 int kdpfd;
73 int nfds;
74 int n;
75 socklen_t len;
76 struct sockaddr_in my_addr;
77 unsigned int myport;
78 struct epoll_event ev;
79 struct epoll_event events[MAXEPOLLSIZE];
80 struct rlimit rt;
81
82 myport = 9999;
83
84 pthread_t thread;
85 pthread_attr_t attr;
86
87 rt.rlim_max = rt.rlim_cur = MAXEPOLLSIZE;
88 if (setrlimit(RLIMIT_NOFILE, &rt) == -1) {
89 perror("setrlimit");
90 exit(1);
91 } else {
92 printf("set param success\n");
93 }
94
95 if ((listener = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
96 perror("socket create failed.\n");
97 exit(1);
98 } else {
99 printf("socket create success\n");
100 }
101
102 int opt = SO_REUSEADDR;
103 setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
104
105 setnonblocking(listener);
106 bzero(&my_addr, sizeof(my_addr));
107 my_addr.sin_family = PF_INET;
108 my_addr.sin_port = htons(myport);
109 my_addr.sin_addr.s_addr = INADDR_ANY;
110 if (bind(listener, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
111 perror("bind");
112 exit(1);
113 } else {
114 printf("IP bind success\n");
115 }
116
117 kdpfd = epoll_create(MAXEPOLLSIZE);
118 len = sizeof(struct sockaddr_in);
119 ev.events = EPOLLIN | EPOLLET;
120 ev.data.fd = listener;
121 if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, listener, &ev) < 0) {
122 fprintf(stderr, "epoll set insertion error: fd=%d\n", listener);
123 return -1;
124 } else {
125 printf("epoll add success\n");
126 }
127
128 while (1) {
129 nfds = epoll_wait(kdpfd, events, 10000, -1);
130 if (nfds == -1) {
131 perror("epoll_wait");
132 break;
133 }
134
135 for (n = 0; n < nfds; ++n) {
136 if (events[n].data.fd == listener) {
137 pthread_attr_init(&attr);
138 pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
139
140 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
141
142 if (pthread_create(&thread, &attr, pthread_handle_message, (void *)&(events[n].data.fd))) {
143 perror("pthread_creat error!");
144 exit(-1);
145 }
146 }
147 }
148 }
149 close(listener);
150 return 0;
151 }