C++ socket网络编程——即时通信系统( 三 )


struct Msg
{
int type;
int fromID;
int toID;
char content[BUF_SIZE];
 
};
#endif // CHATROOM_COMMON_H
服务端类 Server.h Server.cpp
服务端需要的接口:
1)init()初始化
2)Start()启动服务
3)Close()关闭服务
4)广播消息给所有客户端函数 SendBroadcastMessage()
服务端的主循环中每次都会检查并处理EPOLL中的就绪事件,而就绪事件列表主要是两种类型:新连接或新消息 。服务器会依次从就绪事件列表里提取事件进行处理,如果是新连接则accept()然后addfd(),如果是新消息则SendBroadcastMessage()实现聊天功能 。
Server.h

#ifndef CHATROOM_SERVER_H
#define CHATROOM_SERVER_H
 
#include <string>
 
#include "Common.h"
 
using namespace std;
 
// 服务端类,用来处理客户端请求
class Server {
 
public:
// 无参数构造函数
Server();
 
// 初始化服务器端设置
void Init();
 
// 关闭服务
void Close();
 
// 启动服务端
void Start();
 
private:
// 广播消息给所有客户端
int SendBroadcastMessage(int clientfd);
 
// 服务器端serverAddr信息
struct sockaddr_in serverAddr;
 
//创建监听的socket
int listener;
 
// epoll_create创建后的返回值
int epfd;
 
// 客户端列表
list<int> clients_list;
};
//Server.cpp
#include <iostream>
 
【C++ socket网络编程——即时通信系统】#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是一个句柄
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 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
<< " closed.n now there are "
<< clients_list.size()


推荐阅读