Linux网络协议栈之TCP 状态机处理函数

本文把Linux-2.6.11.12源码中文注释版中的注释收集出来,整理在下面。如有侵权,请告知。

TCP状态有如下11种:
enum {
  TCP_ESTABLISHED = 1,  //"Established"
  TCP_SYN_SENT,         //"Syn Sent"
  TCP_SYN_RECV,         //"Syn Recv"
  TCP_FIN_WAIT1,        //"Fin Wait 1"
  TCP_FIN_WAIT2,        //"Fin Wait 2"
  TCP_TIME_WAIT,        //"Time Wait"
  TCP_CLOSE,            //"Close"
  TCP_CLOSE_WAIT,       //"Close Wait"
  TCP_LAST_ACK,         //"Last ACK"
  TCP_LISTEN,           //"Listen"
  TCP_CLOSING,        //"Closing"
  TCP_MAX_STATES /* Leave at the end! */
};

状态机函数有三个:

tcp_timewait_state_process(),tcp_rcv_synsent_state_process(),tcp_rcv_state_process(),主要工作如下:

tcp_timewait_state_process()
{
  /* 用于处理在FIN_WAIT2和TIME_WAIT状态下接收到的段 */
  /* 如果存在选项并且需要做序号回绕处理 */
    /* 解析选项 */
/* 如果有时间戳,进行PAWS判断 tcp_parse_options*/
/* 如果timewait子状态是TCP_FIN_WAIT2 */
  /* 如果PAWS检测未通过 或者 TCP序号不完全在接收窗口内,需要向对方发送ACK */
/* 如果接收到RST段,释放控制块并返回TCP_RW_SUCCESS */
  goto kill:
/* 如果接收到SYN段,释放控制块并返回TCP_RW_RST */
  goto kill_with_rst:
/* 如果在FIN_WAIT_2状态下,接收到非FIN段,或接收到的段序号与预期不符 kill*/
/* 接收到有效的FIN段,进入TIME_WAIT状态 */
/* 如果时间戳有效 */
  /* 根据往返时间启动MSL定时器 */
/* 否则使用固定的60s作为MSL定时器 */
/* 返回TCP_TW_ACK,表示收到有效段,需要给对方发送ACK */
/* TIME_WAIT状态处理 */
/* 如果是预期段 */
/* 如果段没有被丢弃,则进入TIME_WAIT等待阶段 */
  /* 启动FIN_WAIT_2或TIME_WAIT定时器 */
/* 如果在TIME_WAIT状态下接收到SYN段,且SYN段中没有RST和ACK标志,序号有效 */
  /* 可接受该连接请求,重新计算初始序号后返回SYN由上层处理连接请求 */
/* 如果非RST段,只要没有回绕都需要向对方回送ACK */
}
tcp_rcv_synsent_state_process()
{
  /* 在SYN_SENT状态下处理接收到的段,但是不处理带外数据 */
  /* 解析TCP选项并保存到传输控制块中 */
  /* 如果是ACK段,处理ACK标志 */
  /* 如果收到ACK+RST段,需要tcp_reset设置错误码,并关闭套接口 */
  /* 在SYN_SENT状态下接收到的段必须存在SYN标志,否则说明接收到的段无效,丢弃该段 */
  /* 从首部标志中获取显示拥塞通知的特性 */
  /* 如果支持ECN,则设置标志 */
  /* 设置与窗口相关的成员变量 */
  /* 根据是否支持时间戳选项来设置传输控制块的相关字段 */
  /* 初始化PMTU、MSS等成员变量 */
  /* 如果启用了连接保活,则启用连接保活定时器 */
  /* 首部预测 */
  /* 如果套口不处于SOCK_DEAD状态,则唤醒等待该套接口的进程 */
  /* 连接建立完成,根据情况进入延时确认模式 */
  /* 如果不需要延时确认,立即发送ACK段 */
  /* 如果收到RST段,则丢弃传输控制块 */
  /* PAWS检测失效,也丢弃传输控制块 */
  /* 在SYN_SENT状态下收到了SYN段并且没有ACK,说明是两端同时打开 */
     /* 设置状态为TCP_SYN_RECV */
/* 设置时间戳相关的字段 */
/* 初始化窗口相关的成员变量 */
/* 从首部标志中获取显式拥塞通知的特性。 */
/* 初始化MSS相关的成员变量 */
/* 向对端发送SYN+ACK段,并丢弃接收到的SYN段 */
}
tcp_rcv_state_process()
{
  /* 除了ESTABLISHED和TIME_WAIT状态外,其他状态下的TCP段处理都由本函数实现 */
  /*如果有ACK标志*/
  switch(sk->sk_state) {
case TCP_SYN_RECV:
/* 正常的第三次握手,设置连接状态为TCP_ESTABLISHED */
/* 状态已经正常,唤醒那些等待的线程 */
/* 初始化传输控制块,如果存在时间戳选项,同时平滑RTT为0,则需计算重传超时时间 */
/* 建立路由,初始化拥塞控制模块 */
/* 更新最近一次发送数据包的时间 */
/* 计算有关TCP首部预测的标志 */
case TCP_FIN_WAIT1:
   /* 处理FIN_WAIT1状态下接收到的ACK */
/* 通过ACK段的确认,所有发送段对方都已经收到,则迁移到FIN_WAIT2状态 */
/* 从对方收到ACK段,因此可以确认此路由缓存有效 */
/* 如果不在DEAD状态并且状态发生了变化,通过等待的线程 */
/* 否则在DEAD状态,则需要关闭传输控制块,或者在FIN_WAIT2状态等待 */
  /* 无需要在FIN_WAIT2状态等待 或者 接收的段有数据并且接收的段都已经完毕 */
     /* 无需等待,直接关闭套接口 */
/* 在FIN_WAIT2等待 */
case TCP_CLOSING:
   /* 这个状态是处理同时关闭 */
/* 如果所有的段都已经收到 */
  /* 迁移到wait状态 */
case TCP_LAST_ACK:
   /* 如果所有段都已经收到 */
  /* 更新路由缓存并关闭套接口 */
  switch (sk->sk_state)
case TCP_CLOSE_WAIT:
case TCP_CLOSING:
case TCP_LAST_ACK:
        /* 这三种状态,如果接收到已经确认过的段,则直接丢弃 */
    case TCP_FIN_WAIT1:
case TCP_FIN_WAIT2:
        /* 如果接收方向已经关闭 */
  /* 如果接收到新数据 */
      /* 给对方发送复位消息 */
case TCP_ESTABLISHED:
   /* 对已经接收到的段进行排队,应该是在处理快速TCP,在发送ACK的同时发送了数据段 */
  /* 如果tcp_data需要发送数据和ACK则在这里处理 */
  /* 如果段没有加入队列,或者前面的流程需要释放报文,则释放它 */
}

你可能感兴趣的:(Linux网络协议栈之TCP 状态机处理函数)