-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathexample_server.c
More file actions
151 lines (122 loc) · 2.49 KB
/
Copy pathexample_server.c
File metadata and controls
151 lines (122 loc) · 2.49 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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <fcntl.h>
#include "coroutine.h"
static int co_ids[COROUTINE_SIZE];
void SetNoBlock(int fd)
{
int flag = fcntl(fd, F_GETFL, 0);
flag |= O_NONBLOCK;
fcntl(fd, F_SETFL, flag);
}
int socket_init()
{
int lst_fd = socket(AF_INET, SOCK_STREAM, 0);
if(lst_fd == -1)
{
perror("socket.\n");
exit(1);
}
int op = 1;
setsockopt(lst_fd, SOL_SOCKET, SO_REUSEADDR, &op, sizeof(op));
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(9200);
addr.sin_addr.s_addr = inet_addr("192.168.0.128");
if(bind(lst_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
{
perror("bind.\n");
exit(1);
}
if(listen(lst_fd, SOMAXCONN) < 0)
{
perror("listen.\n");
exit(1);
}
return lst_fd;
}
void accept_conn(int lst_fd, schedule *s, int* co_ids, void *(*call_back)(schedule *s, void *args))
{
while(1)
{
int new_fd = accept(lst_fd, NULL, NULL);
//如果有新连接到来则创建一个协程来管理这个连接
if(new_fd > 0)
{
SetNoBlock(new_fd);
int args[] = {lst_fd, new_fd};
int cid = coroutine_create(s, call_back, args);
if(cid >= COROUTINE_SIZE)
{
perror("too many connections.\n");
return;
}
co_ids[cid] = 1;
coroutine_running(s, cid);
}
//如果当前没有连接,则切换至协程上下文中继续运行
else
{
int i = 0;
for(i = 0; i < COROUTINE_SIZE; i++)
{
if(co_ids[i] == -1)
{
continue;
}
coroutine_resume(s, i);
}
}
}
}
void *handle(schedule *s, void *args)
{
int* arr = (int*)args;
int cfd = arr[1];
char buf[1024] = { 0 };
while(1)
{
memset(buf, 0, sizeof(buf));
int ret = recv(cfd, buf, 1024, 0);
if(ret < 0)
{
//如果此时没有数据,则不再等待,直接切换回主流程
coroutine_yield(s);
}
else if(ret == 0)
{
//通信结束
co_ids[s->cur_id] = -1;
break;
}
else
{
printf("=> : %s\n", buf);
if(strncasecmp(buf, "exit", 4) == 0)
{
co_ids[s->cur_id] = -1;
break;
}
send(cfd, buf, ret, 0);
}
}
}
int main()
{
static int co_ids[COROUTINE_SIZE];
int lst_fd = socket_init();
SetNoBlock(lst_fd);
schedule* s = schedule_create();
int i;
for(i = 0; i < COROUTINE_SIZE; i++)
{
co_ids[i] = -1;
}
accept_conn(lst_fd, s, co_ids, handle);
schedule_destroy(s);
}