-
Notifications
You must be signed in to change notification settings - Fork 0
/
Server.cpp
223 lines (182 loc) · 5.92 KB
/
Server.cpp
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#include <iostream>
#include "Server.h"
using namespace std;
// 服务端类成员函数
// 服务端类构造函数
Server::Server(){
// 初始化服务器地址和端口
serverAddr.sin_family = PF_INET;
serverAddr.sin_port = htons(SERVER_PORT);
serverAddr.sin_addr.s_addr = inet_addr(SERVER_IP);
// 初始化socket
listener = 0;
// epool fd
epfd = 0;
}
// 初始化服务端并启动监听
void Server::Init() {
cout << "Init Server..." << endl;
//创建监听socket
listener = socket(PF_INET, SOCK_STREAM, 0);
if(listener < 0) { perror("listener"); exit(-1);}
//绑定地址
if( bind(listener, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) {
perror("bind error");
exit(-1);
}
//监听
int ret = listen(listener, 5);
if(ret < 0) {
perror("listen error");
exit(-1);
}
cout << "Start to listen: " << SERVER_IP << endl;
//在内核中创建事件表
epfd = epoll_create(EPOLL_SIZE);
if(epfd < 0) {
perror("epfd error");
exit(-1);
}
//往事件表里添加监听事件
addfd(epfd, listener, true);
}
// 关闭服务,清理并关闭文件描述符
void Server::Close() {
//关闭socket
close(listener);
//关闭epoll监听
close(epfd);
}
// 发送广播消息给所有客户端
int Server::SendBroadcastMessage(int clientfd)
{
// buf[BUF_SIZE] 接收新消息
// message[BUF_SIZE] 保存格式化的消息
char buf[BUF_SIZE], message[BUF_SIZE];
bzero(buf, BUF_SIZE);
bzero(message, BUF_SIZE);
// 接收新消息
cout << "read from client(clientID = " << clientfd << ")" << endl;
int len = recv(clientfd, buf, BUF_SIZE, 0);
// 如果客户端关闭了连接
if(len == 0)
{
close(clientfd);
// 在客户端列表中删除该客户端
clients_list.remove(clientfd);
cout << "ClientID = " << clientfd
<< " closed.\n now there are "
<< clients_list.size()
<< " client in the char room"
<< endl;
}
// 发送广播消息给所有客户端
else
{
// 判断是否聊天室还有其他客户端
if(clients_list.size() == 1) {
// 发送提示消息
send(clientfd, CAUTION, strlen(CAUTION), 0);
return len;
}
string ret_1(buf);//初始化ret_1
istringstream is(ret_1);//初始化is
string str1,str2;
is>>str1>>str2;//通过空格划分字符串
int number=atoi(str1.c_str());
if(str1=="group")//若为group,则进行广播
{
// 格式化发送的消息内容
sprintf(message, SERVER_MESSAGE, clientfd, strcpy(buf,str2.c_str()));
// 遍历客户端列表依次发送消息,需要判断不要给来源客户端发
list<int>::iterator it;
for(it = clients_list.begin(); it != clients_list.end(); ++it) {
if(*it != clientfd){
if( send(*it, message, BUF_SIZE, 0) < 0 ) {
return -1;
}
}
}
}
else if(number>=0 && number<=100)//若是0到100的数字则根据数字来实现点对点通信
{
sprintf(message, SERVER_MESSAGE, clientfd, strcpy(buf,str2.c_str()));
// 遍历客户端列表依次发送消息,发送信息给指定方
list<int>::iterator it;
for(it = clients_list.begin(); it != clients_list.end(); ++it) {
if(*it == number){
if( send(*it, message, BUF_SIZE, 0) < 0 ) {
return -1;
}
}
}
}
//若输入格式不符合,则不进行任何操作
else//若是其他情况则不进行任何操作
{
;
}
}
return len;
}
// 启动服务端
void Server::Start() {
// epoll 事件队列
static struct epoll_event events[EPOLL_SIZE];
// 初始化服务端
Init();
//主循环
while(1)
{
//epoll_events_count表示就绪事件的数目
int epoll_events_count = epoll_wait(epfd, events, EPOLL_SIZE, -1);
if(epoll_events_count < 0) {
perror("epoll failure");
break;
}
cout << "epoll_events_count =\n" << epoll_events_count << endl;
//处理这epoll_events_count个就绪事件
for(int i = 0; i < epoll_events_count; ++i)
{
int sockfd = events[i].data.fd;
//新用户连接
if(sockfd == listener)
{
struct sockaddr_in client_address;
socklen_t client_addrLength = sizeof(struct sockaddr_in);
int clientfd = accept( listener, ( struct sockaddr* )&client_address, &client_addrLength );
cout << "client connection from: "
<< inet_ntoa(client_address.sin_addr) << ":"
<< ntohs(client_address.sin_port) << ", clientfd = "
<< clientfd << endl;
addfd(epfd, clientfd, true);
// 服务端用list保存用户连接
clients_list.push_back(clientfd);
cout << "Add new clientfd = " << clientfd << " to epoll" << endl;
cout << "Now there are " << clients_list.size() << " clients int the chat room" << endl;
// 服务端发送欢迎信息
cout << "welcome message" << endl;
char message[BUF_SIZE];
bzero(message, BUF_SIZE);
sprintf(message, SERVER_WELCOME, clientfd);
int ret = send(clientfd, message, BUF_SIZE, 0);
if(ret < 0) {
perror("send error");
Close();
exit(-1);
}
}
//处理用户发来的消息,并广播,使其他用户收到信息
else {
int ret = SendBroadcastMessage(sockfd);
if(ret < 0) {
perror("error");
Close();
exit(-1);
}
}
}
}
// 关闭服务
Close();
}