书接上回
聊天服务器,这个类主要是用于处理网络连接和消息。
public:
ChatServer(EventLoop *loop, // 事件循环
const InetAddress &listenAddr, // IP+Port
const string &nameArg) // 服务器的名字
: _server(loop, listenAddr, nameArg), _loop(loop)
{
// 给服务器注册用户连接的创建和断开回调
_server.setConnectionCallback(std::bind(&ChatServer::onConnection, this, _1));
// 给服务器注册用户读写事件回调
_server.setMessageCallback(std::bind(&ChatServer::onMessage, this, _1, _2, _3));
// 设置服务器端的线程数量 1个I/O线程 3个worker线程
_server.setThreadNum(4);
}
// 开启事件循环
void start() {
_server.start();
}
上面是整个代码的核心,之后对其中两个最重要的回调函数:
一个是用户连接的创建和断开回调
一个用户读写事件回调。
用户的连接创建和断开
// 专门处理用户的连接创建和断开 epoll listenfd accept
void onConnection(const TcpConnectionPtr &conn)
{
if (conn->connected())
{
cout << conn->peerAddress().toIpPort() << " -> "
<< conn->localAddress().toIpPort() << " state:online" << endl;
}
else {
cout << conn->peerAddress().toIpPort() << " -> "
<< conn->localAddress().toIpPort() << " state:offline" << endl;
conn->shutdown(); // close(fd)
}
}
该函数检查传入的 conn
对象是否处于连接状态(connected()
方法返回 true
表示连接状态)。
如果连接,它将输出远端地址和端口号(peerAddress().toIpPort()
),本地地址和端口号(localAddress().toIpPort()
),以及状态 "state:online"
如果断开,它将输出相同的地址和端口号,但状态为 "state:offline"
它的输出:格式为:远端地址和端口 -> 本地地址和端口 状态:online/offline
peerAddress()
和 localAddress()
分别返回连接的远端和本地的网络地址信息
toIpPort()
方法将地址信息转换为字符串格式,包括IP地址和端口号
处理用户读写事件
// 专门处理用户的读写事件
void onMessage(const TcpConnectionPtr &conn, // 连接
Buffer *buffer, // 缓冲区
Timestamp time) // 接收到数据的时间信息
{
string buf = buffer->retrieveAllAsString();
cout<<"recv data:" << buf << " time:" << time.toString() << endl;
conn->send(buf);
}
TcpServer _server;// #1
EventLoop *_loop;// #2 epoll
两个成员
TcpServer _server;// #1
EventLoop *_loop;// #2 epoll
_server
是一个 TcpServer
类型的成员变量,用于管理TCP服务器的连接和通信
_loop
是一个 EventLoop
类型的成员变量,用于处理事件循环。EventLoop
是muduo网络库中用于处理I/O事件的核心组件
而用到的一些细节:
retrieveAllAsString()
方法从 buffer
中提取所有数据,并将其转换为字符串
toString()
方法将 Timestamp
对象转换为字符串格式的时间信息
send()
方法将数据发送回给客户端
main函数
int main()
{
EventLoop loop; // epoll
InetAddress addr("127.0.0.1", 6000);
ChatServer server(&loop, addr, "ChatServer");
server.start(); // listenfd epoll_ctl_epoll
loop.loop(); // epoll_wait以阻塞方式等待新用户连接,已连接用户的读写事件等
return 0;
}
首先创建 EventLoop
对象:EventLoop loop;
:创建一个 EventLoop
对象,用于处理事件循环。
创建 InetAddress
对象:InetAddress addr("127.0.0.1", 6000);
:创建一个 InetAddress
对象,指定服务器监听的本地IP地址为 127.0.0.1
(即本机地址),端口号为 6000
。
创建 ChatServer
对象:ChatServer server(&loop, addr, "ChatServer");
:创建一个 ChatServer
对象,传入 EventLoop
对象、InetAddress
对象和服务器名称 "ChatServer"
。
启动服务器:server.start();
:调用 ChatServer
对象的 start
方法,启动服务器,开始监听指定的IP地址和端口,准备接受新用户的连接。
启动事件循环:loop.loop();
:调用 EventLoop
对象的 loop
方法,启动事件循环。服务器将进入阻塞状态,等待新的用户连接和处理已连接用户的读写事件。
返回值:return 0;
:程序正常结束,返回 0
表示成功。
最后是一开始的所有注释
综上 我们muduo网络库的代码就全部编写完成