Session——会话管理有什么

Session 回答的问题是:「每个连接自己的状态放哪?」 它被逼出来的原因是「每个连接的状态散落在 EventLoop 回调里」。这一篇讲它有什么——职责、内部结构、边界、异常、形态,重点是「协议状态属于 Session,不属于 Protocol」。


一、它解决什么问题

每个客户端连接都需要维护自己的状态:

1
2
3
缓冲区       已收到但还没处理完的字节
协议状态 握手 / 正常 / 关闭
活跃时间 多久没动了(心跳判断)

在没有 Session 的阶段,这些状态散落在 EventLoop 回调里——靠全局数组、靠 fd 索引到处查。连接一多,状态管理就乱。

Session 被逼出来的原因:把「每个连接的状态」集中到一个结构里,从事件分发中抽离。


二、它有什么(内部结构)

1
2
3
4
5
6
7
struct Session {
int fd; // 连接 fd
Buffer recv_buf; // 接收缓冲区
Buffer send_buf; // 发送缓冲区
ProtocolState state; // 协议状态(握手/正常/关闭)
time_t last_active; // 最后活跃时间
};
1
2
3
数据:fd + 接收/发送缓冲 + 协议状态 + 活跃时间
算法:状态机(协议状态流转)+ 心跳判断
接口:on_connect / on_message / on_disconnect / tick(心跳)

Session 的核心是「状态」

1
2
3
4
每个客户端一个 Session
生命周期从连接建立到连接断开
连接建立 → 创建 Session
连接断开 → 销毁 Session

三、协议状态属于 Session,不属于 Protocol

这是上一轮澄清过的一个关键点,这里再强调:

1
2
3
4
5
6
7
Protocol(数据结构):
→ struct Message 的定义,是「死的」
→ 消息长什么样:length + command + payload

协议状态(活的):
→ 握手、正常、关闭,是「活的」
→ 属于某个具体的会话
1
2
3
Session.state = HANDSHAKING   ← 这个会话正在握手
Session.state = NORMAL ← 这个会话正常通信中
Session.state = CLOSING ← 这个会话正在关闭

协议格式是死的定义,协议状态是活的、属于某个 Session。 所以「协议状态」不该挂在 Protocol(数据结构)上,而该挂在 Session 上。


四、它的边界:管「状态」,不管「事件」和「生死」

1
2
3
✅ 管:每个连接的缓冲、协议状态、活跃时间
❌ 不管:什么时候有数据(EventLoop 的事)
❌ 不管:连接怎么建立/关闭(Connection 的事)
1
2
3
EventLoop 说「fd 3 可读」     ← 什么时候
Connection 管「fd 3 还活着」 ← 生死
Session 管「fd 3 收到多少字节、协议走到哪一步」 ← 状态

三层分工清晰:

1
2
3
EventLoop   什么时候有事
Connection 连接的生死
Session 连接的状态

五、它的形态:有状态组件,类封装

1
2
有状态:缓冲、协议状态、活跃时间,每个会话一份
有生命周期:连接建立时创建,断开时销毁

所以用类封装,每个连接一个 Session 对象,和 Connection 一一配对。

1
2
3
4
Session* s = new Session(client_fd);
s->on_connect();
s->on_data(bytes, len);
s->on_disconnect();

六、它的异常

1
2
3
4
5
6
7
8
9
10
11
会话过期:
长时间没有活跃(超过心跳阈值)
→ 处理:清理会话、关闭连接、通知上层

协议版本不匹配:
握手时对方版本不一致
→ 处理:握手失败、关闭连接、返回错误

协议状态机异常:
状态流转非法(如 NORMAL 状态收到握手请求)
→ 处理:记录、重置或关闭会话

Session 的异常都是「会话状态」层面的——它处理「状态怎么出问题了」,不处理「连接怎么断了」(Connection)或「字节格式对不对」(解析层)。


七、它和其他组件的关系

1
2
3
4
Session ← 被 EventLoop 驱动(连接建立 → 创建;断开 → 销毁)
Session ← 挂载在 Connection 上(一连接一会话)
Session → 用 Buffer(recv_buf / send_buf 就是它的字段)
Session → 持有 ProtocolState(协议状态字段)
1
2
3
4
5
6
EventLoop ──驱动──→ Connection ──挂载──→ Session

┌─────────────┼─────────────┐
↓ ↓ ↓
recv_buf send_buf state
(Buffer) (Buffer) (ProtocolState)

八、小结

1
2
3
4
5
6
7
8
9
10
Session 有什么:
职责:每个连接的缓冲、协议状态、活跃时间
结构:fd + recv_buf + send_buf + ProtocolState + last_active
边界:管「状态」,不管「事件」(EventLoop)和「生死」(Connection)
形态:有状态组件,类封装,一连接一会话
异常:会话过期 / 协议版本不匹配 / 状态机异常

关键:协议状态属于 Session,不属于 Protocol(数据结构)。

一句话:Session 是「每个连接此刻是什么状态」的容器。