-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlibev_server.c
More file actions
190 lines (160 loc) · 4.55 KB
/
Copy pathlibev_server.c
File metadata and controls
190 lines (160 loc) · 4.55 KB
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#include <ev.h>
#include <stdio.h>
#include <netinet/in.h>
#include<stdlib.h>
#include <string.h>
#define PORT 57789
#define BUFFER_SIZE 2048
#define MAX_ALLOWED_CLIENT 10240
struct ev_io *libevlist[MAX_ALLOWED_CLIENT] = {NULL};
void accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents);
void read_cb(struct ev_loop *loop, struct ev_io *watcher, int revents);
void timer_beat(struct ev_loop *loop, struct ev_timer *watcher, int revents);
int freelibev(struct ev_loop *loop, int fd);
int main()
{
struct ev_loop *loop=ev_default_loop(0);
int sd;
struct sockaddr_in addr;
int addr_len = sizeof(addr);
struct ev_io socket_accept;
struct ev_timer timeout_w;
sd = socket(PF_INET, SOCK_STREAM, 0);
if(sd < 0)
{
printf("socket error\n");
return -1;
}
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = INADDR_ANY;
if(bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0)
{
printf("bind error\n");
return -1;
}
if(listen(sd, SOMAXCONN) < 0)
{
printf("listen error\n");
return -1;
}
int bReuseaddr=1;
if(setsockopt(sd,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(bReuseaddr)) != 0)
{
printf("setsockopt error in reuseaddr[%d]\n", sd);
return ;
}
ev_io_init(&socket_accept, accept_cb, sd, EV_READ);
ev_io_start(loop, &socket_accept);
ev_timer_init(&timeout_w, timer_beat, 1., 0.);
ev_timer_start(loop, &timeout_w);
ev_run(loop, 0);
return 1;
}
void accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
{
/*
如果有链接,则继续监听fd;
*/
struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
int client_sd;
struct ev_io *w_client = (struct ev_io*) malloc(sizeof(struct ev_io));
if(w_client == NULL)
{
printf("malloc error in accept_cb\n");
return ;
}
if(EV_ERROR & revents)
{
printf("error event in accept\n");
return ;
}
client_sd = accept(watcher->fd, (struct sockaddr*)&client_addr, &client_len);
if(client_sd < 0)
{
printf("accept error\n");
return;
}
if( client_sd > MAX_ALLOWED_CLIENT)
{
printf("fd too large[%d]\n", client_sd);
close(client_sd);
return ;
}
if(libevlist[client_sd] != NULL)
{
printf("client_sd not NULL fd is [%d]\n", client_sd);
return ;
}
printf("client connected\n");
ev_io_init(w_client, read_cb, client_sd, EV_READ);
ev_io_start(loop, w_client);
libevlist[client_sd] = w_client;
}
void read_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
{
char buffer[BUFFER_SIZE];
ssize_t read;
if(EV_ERROR & revents)
{
printf("error event in read\n");
return ;
}
read = recv(watcher->fd, buffer, BUFFER_SIZE, 0);
if(read < 0)
{
printf("read error\n");
return;
}
if(read == 0)
{
printf("client disconnected.\n");
/* 如果客户端断开连接,释放响应的资源,并且关闭监听 */
freelibev(loop, watcher->fd);
ev_io_stop(loop, watcher);
free(watcher);
return;
}
else
{
buffer[read] = '\0';
printf("receive message:%s\n", buffer);
}
send(watcher->fd, buffer, read, 0);
bzero(buffer, read);
}
void timer_beat(struct ev_loop *loop, struct ev_timer *watcher, int revents)
{
float timeout = 2.0;
/* 这里可以发送心跳包,也可以什么都不做 */
printf("send beat per[%f]\n",timeout);
fflush(stdout);
if(EV_ERROR & revents)
{
printf("error event in timer_beat\n");
return ;
}
ev_timer_set(watcher, timeout,0.);
ev_timer_start(loop, watcher);
return;
}
int freelibev(struct ev_loop *loop, int fd)
{
/*if(fd > MAX_ALLOWED_CLIENT)
{
printf("more than MAX_ALLOWED_CLIENT[%d]", fd);
return -1;
}*/
if(libevlist[fd] == NULL)
{
printf("the fd already freed[%d]\n", fd);
return -1;
}
close(fd);
ev_io_stop(loop, libevlist[fd]);
free(libevlist[fd]);
libevlist[fd] = NULL;
return 1;
}