Repository navigation
Expand file tree
/
Copy pathServer.cpp
More file actions
261 lines (222 loc) · 5.89 KB
/
Copy pathServer.cpp
File metadata and controls
261 lines (222 loc) · 5.89 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
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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
#include"Server.h"
using namespace std;
//服务器端类成员函数
//服务器端类构造函数
Server::Server()
{
//初始化服务器地址和端口
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(SERVER_PORT);
inet_pton(AF_INET,SERVER_IP,&serverAddr.sin_addr.s_addr);
//初始化socket
listener = 0;
//初始化epfd
epfd = 0;
}
//初始化服务端并启动监听
void Server::Init()
{
cout<<"Init Server..."<<endl;
//创建监听socket
listener = socket(AF_INET,SOCK_STREAM,0);
if(listener<0)
{
perror("socket error: ");
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是一个句柄(红黑树的树根)
epfd = epoll_create(EPOLL_SIZE);
if(epfd<0)
{
perror("epoll_create error: ");
exit(1);
}
//往事件表里添加监听事件
addfd(epfd,listener,true);
}
//关闭服务,清理并关闭文件描述符
void Server::Close()
{
close(listener); //关闭listener
close(epfd); //关闭epfd
}
//发送广播给所有客户端
int Server::SendBroadcastMessage(int clientfd)
{
char recv_buf[BUF_SIZE];
char send_buf[BUF_SIZE];
Msg msg;
bzero(recv_buf,BUF_SIZE);
//接受新消息
cout<<"read from client(clientID = "<<clientfd<<")"<<endl;
int len = recv(clientfd,recv_buf,BUF_SIZE,0);
//清空结构体,把接受到的字符串转换为结构体
memset(&msg,0,sizeof(msg));
memcpy(&msg,recv_buf,sizeof(msg));
//判断接受到的信息是私聊还是群聊
msg.fromID = clientfd;
if(msg.content[0]=='\\'&&isdigit(msg.content[1]))
{
msg.type = 1;
msg.toID = msg.content[1] - '0';
memcpy(msg.content,msg.content+2,sizeof(msg.content));
}else
{
msg.type = 0;
}
//如果客户端关闭了连接
if(len == 0)
{
close(clientfd);
//在客户端列表中删除该客户端
clients_list.remove(clientfd);
cout<<"ClientID = "<<clientfd<<" close"<<endl;
cout<<"now there are "<<clients_list.size()<<" client in the chat room"<<endl;
}
//发送广播消息给所有客户端
else
{
//判断聊天室是否还有其它客户端
if(clients_list.size()==1)
{
//发送提示消息
memcpy(msg.content,CAUTION,sizeof(msg.content));
bzero(send_buf,BUF_SIZE);
memcpy(send_buf,&msg,sizeof(msg));
send(clientfd,send_buf,sizeof(send_buf),0);
return len;
}
//存放格式化后的信息
char format_message[BUF_SIZE];
//群聊
if(msg.type == 0)
{
//格式化发送的消息内容
sprintf(format_message,SERVER_MESSAGE,clientfd,msg.content);
memcpy(msg.content,format_message,BUF_SIZE);
//遍历客户端列表依次发送消息,需要判断不要给来源客户端发
list<int>::iterator it;
for(it = clients_list.begin();it!=clients_list.end();it++)
{
if(*it != clientfd)
{
//把发送的结构体转换为字符串
bzero(send_buf,BUF_SIZE);
memcpy(send_buf,&msg,sizeof(msg));
if(send(*it,send_buf,sizeof(send_buf),0)<0)
return -1;
}
}
}
//私聊
if(msg.type == 1)
{
bool private_offline = true;
sprintf(format_message,SERVER_PRIVATE_MESSAGE,clientfd,msg.content);
memcpy(msg.content,format_message,BUF_SIZE);
//遍历客户端列表发送对应消息,需要判断不要给来源客户端发
list<int>::iterator it;
for(it = clients_list.begin();it!=clients_list.end();it++)
{
if(*it == msg.toID)
{
private_offline = false;
//把发送的结构体转换为字符串
bzero(send_buf,BUF_SIZE);
memcpy(send_buf,&msg,sizeof(msg));
if(send(*it,send_buf,sizeof(send_buf),0)<0)
return -1;
}
}
//如果私聊对象不在线
if(private_offline)
{
sprintf(format_message,SERVER_PRIVATE_ERROR_MESSAGE,msg.toID);
memcpy(msg.content,format_message,BUF_SIZE);
bzero(send_buf,BUF_SIZE);
memcpy(send_buf,&msg,sizeof(msg));
if(send(msg.fromID,send_buf,sizeof(send_buf),0)<0)
return -1;
}
}
}
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_wait error: ");
break;
}
cout<<"epoll_events_count = "<<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_addr;
socklen_t client_addr_len = sizeof(client_addr);
char client_IP[BUFSIZ];
int clientfd = accept(listener,(struct sockaddr*)&client_addr,&client_addr_len);
cout<<"client connection from: "<<inet_ntop(AF_INET,&client_addr.sin_addr.s_addr,client_IP,sizeof(client_IP))<<" : "<<ntohs(client_addr.sin_port)<<",clientfd = "<<clientfd<<endl;
addfd(epfd,clientfd,true);
//服务端用list保存用户连接
clients_list.push_back(clientfd);
cout<<"Add new clientfd = "<<clientfd<<" to poll"<<endl;
cout<<"Now there are "<<clients_list.size()<<"clients in 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();
}