在muduo库中,使用了很多有限状态机来管理事件的处理流程,如
1 | //TcpConnection |
通过状态机管理对象或流程的执行状态,流程清晰易于管理。
分析管理的对象或流程,将整个生命周期中所有稳定且互斥的阶段识别出来,这些阶段就是一个一个状态。然后找到所有可能导致状态改变的外部输入或内部条件。
下面几个示例,方便理解与使用
TcpConnection:管理连接的完整生命周期
kConnecting:连接已建立,正在进行初始化(如调用connectEstablished)。kConnected:连接完全就绪,可以进行数据收发。kDisconnecting:已调用shutdown(),正在等待数据发送完毕或对端关闭。kDisconnected:连接已完全关闭。
事件与状态转移:
- 事件:
connectEstablished()被调用- 转移:
kConnecting->kConnected - 动作:启用读事件,调用用户的
ConnectionCallback。
- 转移:
- 事件:用户调用
shutdown()- 转移:
kConnected->kDisconnecting - 动作:关闭写端,但仍可接收数据。
- 转移:
- 事件:
read()返回0 或发生错误,触发handleClose()- 转移:
kConnected或kDisconnecting->kDisconnected - 动作:关闭 socket,调用用户的
ConnectionCallback和内部的CloseCallback
- 转移:
Connector:连接管理
kDisconnected:初始状态或连接失败后的状态。kConnecting:已发起非阻塞connect,正在等待结果。kConnected:连接成功建立。
事件与状态转移:
- 事件:调用
start()发起连接- 转移:
kDisconnected->kConnecting
- 转移:
- 事件:socket 可写,
handleWrite()检查SO_ERROR成功- 转移:
kConnecting->kConnected
- 转移:
- 事件:连接失败,
retry()被调用- 转移:
kConnecting->kDisconnected
- 转移:
HttpContext:TCP流式协议解析
kExpectRequestLine:正在解析请求行kExpectHeaders:正在解析请求头kExpectBody:正在解析请求体kGotAll:解析完成
事件与状态转移:
- 事件:在缓冲区中找到并成功解析了请求行
- 转移:
kExpectRequestLine->kExpectHeaders
- 转移:
- 事件:在缓冲区中解析完所有头部,并遇到了一个空行
- 转移:
kExpectHeaders->kGotAll
- 转移:
文件下载器
1 | enum status{ |
- 事件:
user_starts_download()- 转移:
kIdle->kConnecting
- 转移:
- 事件:
connection_succeeded()- 转移:
kConnecting->kDownloading
- 转移:
- 事件:
data_chunk_received()- 转移:
kDownloading->kDownloading(保持状态,但更新进度)
- 转移:
- 事件:
user_pauses()- 转移:
kDownloading->kPaused
- 转移:
- 事件:
download_finished()- 转移:
kDownloading->kCompleted
- 转移:
- 事件:
network_error()- 转移:
kDownloading或kConnecting->kError
- 转移: