-
Notifications
You must be signed in to change notification settings - Fork 28
/
Copy pathConccurentUDPEchoServer.c
130 lines (117 loc) · 3.47 KB
/
ConccurentUDPEchoServer.c
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <signal.h>
#include <errno.h>
#define SVR_PORT 50001
typedef void(*sig_handler)(int);
sig_handler fuck(int signo, sig_handler newhandler)
{
struct sigaction newact, oldact;
bzero(&newact, sizeof(newact));
newact.sa_handler = newhandler;
if (signo == SIGALRM) {
#ifdef SA_INTERRUPT
newact.sa_flags |= SA_INTERRUPT;
#endif
} else {
#ifdef SA_RESTART
newact.sa_flags |= SA_RESTART;
#endif
}
if (sigaction(signo, &newact, &oldact) < 0)
return SIG_ERR;
return oldact.sa_handler;
}
int udp_server(unsigned short port)
{
int fd = -1;
if ((fd = socket(AF_INET,SOCK_DGRAM, 0)) < 0) {
perror("socket error!");
return -1;
}
struct sockaddr_in svraddr;
bzero(&svraddr, sizeof(svraddr));
svraddr.sin_family = AF_INET;
svraddr.sin_port = htons(port);
svraddr.sin_addr.s_addr = htonl(INADDR_ANY);
int on = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
perror("setsockopt error!");
return -1;
}
if (bind(fd, (struct sockaddr *)&svraddr, sizeof(svraddr)) < 0) {
perror("bind error!");
exit(1);
}
return fd;
}
static unsigned short port_used = SVR_PORT;
int main(int argc, char *argv[])
{
int fd = -1;
if ((fd = udp_server(SVR_PORT)) < 0) {
perror("udp_server start error!");
exit(1);
}
struct sockaddr_in cliaddr;
socklen_t clilen = sizeof(cliaddr);
char c = 0;
char buf[1024];
ssize_t nread = 0;
for (;;) {
socklen_t len = clilen;
if ((nread = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&cliaddr, &len)) < 0) {
perror("recvfrom error!");
continue;
}
buf[nread] = 0;
printf("recv from client %s\n", buf);
if (strncmp(buf, "syn", 3) != 0)
continue;
if (port_used - SVR_PORT > 5) {
printf("connection refused!\n");
continue;
}
int connfd = -1;
if ((connfd = udp_server(++port_used)) < 0) {
perror("udp_server select new sockaddr fail!\n");
exit(1);
}
pid_t pid;
if ((pid = fork()) < 0) {
perror("fork error!");
exit(1);
} else if (pid == 0) {
snprintf(buf, sizeof(buf), "ack:%d", port_used);
if (sendto(fd, buf, strlen(buf), 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr)) < 0) {
perror("sendto error!");
exit(0);
}
for (;;) {
char buf[1024];
socklen_t len = clilen;
ssize_t nread = 0;
if ((nread = recvfrom(connfd, buf, sizeof(buf), 0, (struct sockaddr *)&cliaddr, &len)) < 0) {
perror("recvfrom error!");
break;
}
buf[nread] = 0;
if (strncmp(buf, "fin", 3) == 0) {
printf("udp connection close\n");
break;
}
if (sendto(connfd, buf, nread, 0, (struct sockaddr *)&cliaddr, sizeof(cliaddr)) < 0) {
perror("sendto error!");
break;
}
}
exit(0);
}
/* parent process */
close(connfd);
}
}