欢迎光临
我们一直在努力

Nanomsg中usock模块状态机详解:客户端与服务端视角

1、背景

Nanomsg 的 usock 模块通过有限状态机(FSM)优雅地管理异步 socket 的生命周期。无论是主动连接的客户端 socket,还是被动接受连接的服务端 socket,它们的状态转换路径既有共性也有差异。本文将分别从客户端和服务端的角度,详细绘制状态转移图并解释每个状态的含义及转换条件。

2、客户端Socket状态机

客户端 socket 指通过 nn_usock_connect 主动向远端发起连接的 socket。其典型生命周期如下:
请添加图片描述

2.1、状态转移详解

状态含义转换条件
IDLE 初始状态,无底层 socket 描述符 nn_usock_init 后进入
STARTING 已创建操作系统 socket(socket() 成功),但尚未绑定或连接。可在此设置 socket 选项 nn_usock_start 触发 NN_FSM_START 动作
CONNECTING 正在尝试连接远端。可能是同步 connect 返回 EINPROGRESS,也可能是已提交异步任务 nn_usock_connect 发送 ACTION_CONNECT
ACTIVE 连接建立成功,可以发送和接收数据 同步成功或异步连接成功后由 CONNECTING 转入
REMOVING_FD 正在从 worker 的 poller 中移除 fd 并关闭 socket ACTIVE 状态下发生错误或收到停止请求
DONE socket 已关闭,仅作为过渡状态,等待最终停止 REMOVING_FD 完成,或 STARTING/CONNECTING 中出错

2.2、客户端关键转移

1、STARTING 转到 CONNECTING
调用 nn_usock_connect 后,状态机收到 ACTION_CONNECT,立即调用非阻塞 connect

  • 若 connect 返回 0,直接发送 ACTION_DONE 转到 ACTIVE
  • 若返回 EINPROGRESS,保持在 CONNECTING 并提交 task_connecting 给 worker,等待 fd 可写事件
  • 若返回其他错误,发送 ACTION_ERROR 转到 DONE
    2、CONNECTING 转到 ACTIVE(异步)
    Worker 检测到 fd 可写,触发 NN_WORKER_FD_OUT 事件。状态机调用 getsockopt(SO_ERROR) 检查连接结果。
  • 若 SO_ERROR == 0,连接成功,转到 ACTIVE,并通过 task_connected 将 fd 加入 poller(但不设置读写事件),最后上报 NN_USOCK_CONNECTED 给父状态机
  • 若 SO_ERROR != 0,连接失败,转到 DONE 并上报 NN_USOCK_ERROR
    3、ACTIVE 下的错误处理
    在 ACTIVE 状态下,如果 send 或 recv 遇到 ECONNRESET 等致命错误,状态机会收到 ACTION_ERROR,先转到 REMOVING_FD 并提交 task_stop 异步清理资源,最终进入 DONE

3、服务端 Socket 状态机

服务端 socket 分为两类:监听 socket(调用 listen)和被接受 socket(由 accept 产生),下面分别介绍。

3.1、监听 Socket

监听 socket 负责接受新连接,其状态转换如下:请添加图片描述

3.1.1、状态转移详解

状态含义转换条件
IDLE 初始状态
STARTING socket 已创建,尚未监听
LISTENING 已调用 listen,可以接受连接,但当前没有正在进行的 accept 操作 nn_usock_listen 发送 ACTION_LISTEN
ACCEPTING 上层已调用 nn_usock_accept,正在等待新连接(同步尝试失败后进入异步等待) ISTENING 收到 ACTION_ACCEPT
ACCEPTING_ERROR 因系统资源不足(如文件描述符用尽)导致无法接受新连接,等待上层重试 ACCEPTING 中 accept 返回 ENFILE/EMFILE 等
CANCELLING 上层取消等待(例如停止 socket),正在清理 ACCEPTING 收到 ACTION_CANCEL(由 nn_usock_stop 触发)

3.1.2、监听 socket 关键转移说明

1、STARTING 到 LISTENING:调用 nn_usock_listen,执行 listen() 系统调用,之后状态机收到 ACTION_LISTEN 进入监听状态
2、LISTENING 到 ACCEPTING:上层调用 nn_usock_accept,发送 ACTION_ACCEPT。状态机先尝试同步 accept:

  • 成功获得新 fd 后初始化被接受 socket,发送 ACTION_DONE 回到 LISTENING(一次 accept 完成)
  • 失败且错误码为 EAGAIN/EWOULDBLOCK 后,开始 配对 self->asock,提交 task_accept 给 worker,worker 将监听 fd 加入 poller 并关注读事件
  • 失败且错误码为资源不足后,开始转入 ACCEPTING_ERROR,上报 NN_USOCK_ACCEPT_ERROR 事件给父状态机
    3、ACCEPTING 异步完成:当新连接到达,worker 触发 NN_WORKER_FD_IN,状态机再次调用 accept:
  • 成功后初始化被接受 socket,解除配对,回到 LISTENING,并分别通知被接受 socket(ACTION_DONE)和上层(NN_USOCK_ACCEPTED)
  • 失败且为资源不足后转入 ACCEPTING_ERROR
  • ECONNABORTED 则忽略并继续等待
    4、ACCEPTING_ERROR 恢复:上层收到错误事件后,可以重新调用 nn_usock_accept(发送 ACTION_ACCEPT)回到 ACCEPTING 状态,重新尝试接受

3.2、被接收Socket

当监听 socket 成功 accept 一个新连接时,会创建一个新的 nn_usock 对象(通常由上层协议分配)。这个被接受的 socket 有自己的状态机路径:
请添加图片描述

3.2.1、状态详解

状态含义
IDLE 初始状态
BEING_ACCEPTED 已标记为等待被接受(asock 指向监听 socket),但尚未真正被 accept 系统调用返回
ACCEPTED 已经被 accept 成功,底层 fd 已存在,但尚未加入 worker 的 poller,可在此设置 socket 选项
ACTIVE 已激活,可以发送和接收数据

3.2.2、被接受 socket 关键转移说明

1、IDLE → BEING_ACCEPTED:在 nn_usock_accept 中,如果 self 处于空闲,会调用 nn_fsm_start 并发送 ACTION_BEING_ACCEPTED,使其进入此状态,同时 self->asock 指向监听 socket
2、 BEING_ACCEPTED → ACCEPTED:当监听 socket 成功执行 accept 后,会调用 nn_usock_init_from_fd 初始化 self 的 fd,然后发送 ACTION_DONE 给 self,转入 ACCEPTED 状态,并向上层上报 NN_USOCK_ACCEPTED 事件
3 、ACCEPTED → ACTIVE:上层(如协议层)在完成必要选项设置后,调用 nn_usock_activate,状态机收到 ACTION_ACTIVATE,将 fd 加入 worker 的 poller,转入 ACTIVE。此后即可进行收发
4、 ACCEPTED 或 ACTIVE 停止:可通过 nn_usock_stop 正常关闭

4、3种socket状态机对比

维度客户端 socket服务端监听 socket被接受 socket
初始创建 nn_usock_start nn_usock_start 由 accept 隐式创建(上层分配)
从 STARTING 转移 nn_usock_connect 到CONNECTING nn_usock_listen 到 LISTENING 无,直接从 IDLE 到 BEING_ACCEPTED
活跃前必经状态 CONNECTING LISTENING → ACCEPTING(等待连接) BEING_ACCEPTED 到ACCEPTED
进入 ACTIVE 的条件 连接成功 不进入 ACTIVE(监听 socket 不用于数据传输) 调用 nn_usock_activate
特殊状态 ACCEPTING_ERROR、CANCELLING
典型事件上报 NN_USOCK_CONNECTED、NN_USOCK_SENT、NN_USOCK_RECEIVED NN_USOCK_ACCEPTED(来自被接受 socket)、NN_USOCK_ACCEPT_ERROR NN_USOCK_ACCEPTED、NN_USOCK_SENT、NN_USOCK_RECEIVED

5、总结

usock 模块通过精细的状态机设计,将异步 socket 的复杂行为分解为清晰的状态和转换。客户端 socket 专注于连接建立和 I/O;服务端监听 socket 专注于接受连接,并容忍临时资源枯竭;被接受 socket 则复用客户端 socket 的 ACTIVE 状态处理数据传输。

赞(0)
未经允许不得转载:171主机测评 » Nanomsg中usock模块状态机详解:客户端与服务端视角
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址