-
Notifications
You must be signed in to change notification settings - Fork 0
/
Poll_TcpServer.c
132 lines (111 loc) · 3.73 KB
/
Poll_TcpServer.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
131
132
/*
* Poll Usage Sample
* int poll (struct pollfd *fds, nfds_t nfds, int timeout);
* Note:
* As a tcp server, this program can accept multi-client connections simultaneously.
*
* Copyright (c) 2016 Liming Shao <lmshao@163.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <poll.h>
#define BACKLOG 5
#define BUFF_SIZE 200
#define DEFAULT_PORT 6666
#define OPEN_MAX 1024
int main(int argc, char **argv)
{
int SERV_PORT = DEFAULT_PORT;
if (argc > 2)
printf("param err:\nUsage:\n\t%s port | %s\n\n", argv[0], argv[0]);
if (argc == 2)
SERV_PORT = atoi(argv[1]);
int i, maxi, nready;
int servSocket, cliSocket;
ssize_t nbytes;
char buf[BUFF_SIZE];
socklen_t addrLen;
struct pollfd client[OPEN_MAX];
struct sockaddr_in cliAddr, servAddr;
if ((servSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(1);
}
int optval = 1;
if (setsockopt(servSocket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) {
perror("setsockopt");
exit(0);
}
bzero(&servAddr, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(SERV_PORT);
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(servSocket, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0) {
perror("bind");
exit(1);
}
if (listen(servSocket, BACKLOG) < 0) {
perror("listen err");
exit(1);
}
printf("Listen Port: %d\nListening ...\n", SERV_PORT);
client[0].fd = servSocket;
client[0].events = POLLRDNORM;
for (i = 1; i < OPEN_MAX; i++)
client[i].fd = -1; /* -1 indicates available entry */
maxi = 0; /* max index into client[] array */
for (;;) {
nready = poll(client, maxi + 1, -1);
if (nready < 0) {
printf("poll err");
exit(1);
}
if (client[0].revents & POLLRDNORM) /* new client connection */
{
addrLen = sizeof(cliAddr);
if ((cliSocket = accept(servSocket, (struct sockaddr *)&cliAddr, &addrLen)) < 0) {
printf("accept err");
exit(1);
}
for (i = 1; i < OPEN_MAX; i++)
if (client[i].fd < 0) {
client[i].fd = cliSocket; /* save descriptor */
break;
}
printf("\nNew client connections client[%d] %s:%d\n", i, inet_ntoa(cliAddr.sin_addr),
ntohs(cliAddr.sin_port));
if (i == OPEN_MAX)
printf("too many clients");
client[i].events = POLLRDNORM;
if (i > maxi)
maxi = i; /* max index in client[] array */
if (--nready <= 0)
continue; /* no more readable descriptors */
}
for (i = 1; i <= maxi; i++) /* check all clients for data */
{
if ((cliSocket = client[i].fd) < 0)
continue;
if (client[i].revents & (POLLRDNORM | POLLERR)) {
memset(buf, 0, BUFF_SIZE);
nbytes = recv(cliSocket, buf, BUFF_SIZE, 0);
if (nbytes < 0) {
printf("recv err");
continue;
} else if (nbytes == 0) {
printf("client[%d] closed connection\n", i);
close(cliSocket);
client[i].fd = -1;
} else {
printf("\nFrom client[%d]\n", i);
printf("Recv: %sLength: %d\n\n", buf, (int)nbytes);
}
if (--nready <= 0)
break; /* no more readable descriptors */
}
}
}
}