之前在《深入理解并行编程》的群里,有个小米的兄弟问了一个问题,服务器A发包给服务器B,Seq是1,但是在未能收到服务器B的报文回复的情况下,发送了
rst,但是rst报文中,对应的seq是1461,一堆人都在猜测,为什么seq跳变了,由于当时只看到一半的图片,所以我让他发送完整报文出来之后,我

发现其实rst的seq不是1的原因,并不是因为跳变,而是正常的,因为发送给B的报文,长度为1460,但是这个报文没有得到回复,所以在超时之后,应用程序关闭了这条连接,

导致内核协议栈发送了一个rst报文,而rst报文选取seq的时候,并不是选取的确定已经发送的seq,而是当前连接已经用掉的seq,也就是当前seq,哪怕这个报文没有收到回复,也会使用。

具体看代码:

/* We get here when a process closes a file descriptor (either due to
* an explicit close() or as a byproduct of exit()'ing) and there
* was unread data in the receive queue. This behavior is recommended
* by RFC 2525, section 2.17. -DaveM
*/
void tcp_send_active_reset(struct sock *sk, gfp_t priority)
{
struct sk_buff *skb; /* NOTE: No TCP options attached and we never retransmit this. */
skb = alloc_skb(MAX_TCP_HEADER, priority);
if (!skb) {
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTFAILED);
return;
} /* Reserve space for headers and prepare control bits. */
skb_reserve(skb, MAX_TCP_HEADER);
tcp_init_nondata_skb(skb, tcp_acceptable_seq(sk),
TCPHDR_ACK | TCPHDR_RST);//注意传入的标志是rst,不是fin,可以具体参考tcp_send_fin 是怎么传参数的
	/* Send it off. */
if (tcp_transmit_skb(sk, skb, 0, priority))
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTFAILED); TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTRSTS);
}

  其中关注下报文的init过程:

/* Constructs common control bits of non-data skb. If SYN/FIN is present,
* auto increment end seqno.
*/
static void tcp_init_nondata_skb(struct sk_buff *skb, u32 seq, u8 flags)
{
struct skb_shared_info *shinfo = skb_shinfo(skb); skb->ip_summed = CHECKSUM_PARTIAL;
skb->csum = 0; TCP_SKB_CB(skb)->tcp_flags = flags;
TCP_SKB_CB(skb)->sacked = 0; shinfo->gso_segs = 1;
shinfo->gso_size = 0;
shinfo->gso_type = 0; TCP_SKB_CB(skb)->seq = seq;
if (flags & (TCPHDR_SYN | TCPHDR_FIN))//我们本文的标志是 TCPHDR_ACK | TCPHDR_RST ,
            seq++;//此处+1 ,但进不来
TCP_SKB_CB(skb)->end_seq = seq;//所以本文应该是传入seq是多少就发送多少 }

  那么传入的seq是多少呢?

/* SND.NXT, if window was not shrunk.
* If window has been shrunk, what should we make? It is not clear at all.
* Using SND.UNA we will fail to open window, SND.NXT is out of window. :-(
* Anything in between SND.UNA...SND.UNA+SND.WND also can be already
* invalid. OK, let's make this for now:
*/
static inline __u32 tcp_acceptable_seq(const struct sock *sk)
{
const struct tcp_sock *tp = tcp_sk(sk); if (!before(tcp_wnd_end(tp), tp->snd_nxt))
return tp->snd_nxt;
else
return tcp_wnd_end(tp);
}

  注释写得比较清楚,如果窗口没有shrunk,也就是tp->snd_nxt 没有out of window 的话,则取得就是tp->snd_nxt,而这个值,就是报文长度+1了,也就是1461.

如果不是rst的方式结束,而是fin的方式结束,那么这个seq则应该为多少呢?
我们来关注下 tcp_send_fin 函数,看看它怎么使用seq的,

void tcp_send_fin(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *skb = tcp_write_queue_tail(sk);
int mss_now; /* Optimization, tack on the FIN if we have a queue of
* unsent frames. But be careful about outgoing SACKS
* and IP options.
*/
mss_now = tcp_current_mss(sk); if (tcp_send_head(sk) != NULL) {//说明还有空间,tcp_send_head返回值为sk->sk_send_head,
TCP_SKB_CB(skb)->tcp_flags |= TCPHDR_FIN;
TCP_SKB_CB(skb)->end_seq++;
tp->write_seq++;
} else {
/* Socket is locked, keep trying until memory is available. */
for (;;) {
skb = alloc_skb_fclone(MAX_TCP_HEADER,
sk->sk_allocation);//申请一个skb
if (skb)
break;
yield();
} /* Reserve space for headers and prepare control bits. */
skb_reserve(skb, MAX_TCP_HEADER);
/* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */
tcp_init_nondata_skb(skb, tp->write_seq,
TCPHDR_ACK | TCPHDR_FIN);//fin包占用一个seq
tcp_queue_skb(sk, skb);
}
__tcp_push_pending_frames(sk, mss_now, TCP_NAGLE_OFF);
}

  不管有没有空间,其实发送出去的序列号就是当前报文的下一个,因为fin也占用一个seq,所以这个seq也是上次发完的seq+报文长度+1.

linux 协议栈tcp的rst报文中,seq的选取问题的更多相关文章

  1. 评价linux协议栈tcp实现中的prequeue

    https://blog.csdn.net/dog250/article/details/5464513 https://wiki.aalto.fi/download/attachments/7078 ...

  2. Linux内核TCP MSS机制详细分析

    前言 上周Linux内核修复了4个CVE漏洞[1],其中的CVE-2019-11477感觉是一个很厉害的Dos漏洞,不过因为有其他事打断,所以进展的速度比较慢,这期间网上已经有相关的分析文章了.[2] ...

  3. linux下TCP/IP及内核参数优化调优(转)

    Linux下TCP/IP及内核参数优化有多种方式,参数配置得当可以大大提高系统的性能,也可以根据特定场景进行专门的优化,如TIME_WAIT过高,DDOS攻击等等. 如下配置是写在sysctl.con ...

  4. Linux内核 TCP/IP、Socket参数调优

    Linux内核 TCP/IP.Socket参数调优 2014-06-06  Harrison....   阅 9611  转 165 转藏到我的图书馆   微信分享:   Doc1: /proc/sy ...

  5. Linux下tcp协议socket的recv函数返回时机分析(粘包)

    http://www.vckbase.com/index.php/wv/10http://blog.csdn.net/zlzlei/article/details/7689409 文章一: 当前在网络 ...

  6. [置顶] Linux协议栈代码阅读笔记(一)

    Linux协议栈代码阅读笔记(一) (基于linux-2.6.21.7) (一)用户态通过诸如下面的C库函数访问协议栈服务 int socket(int domain, int type, int p ...

  7. Linux上TCP的几个内核参数调优

    Linux作为一个强大的操作系统,提供了一系列内核参数供我们进行调优.光TCP的调优参数就有50多个.在和线上问题斗智斗勇的过程中,笔者积累了一些在内网环境应该进行调优的参数.在此分享出来,希望对大家 ...

  8. TCP三次握手与Linux的TCP内核参数优化

    感谢各位技术大佬的资料分享,这里我把我理解的内容做一个整理 一:TCP的三次握手 1.TCP简述 TCP是一个面向连接的协议,在连接双方发送数据之前,首先需要建立一条连接.TCP建立连接可以简单称为: ...

  9. Linux下TCP网络编程与基于Windows下C#socket编程间通信

    一.linux下TCP网络编程基础,需要了解相关函数 Socket():用于套接字初始化. Bind():将 socket 与本机上的一个端口绑定,就可以在该端口监听服务请求. Listen():使s ...

随机推荐

  1. 微信小程序,个人开发者创业新平台

    在移动互联网世界,微信无小事,微信的事,是整个创业圈的事.经过一年多的酝酿,2017年1月9日,微信小程序发布了.发布伊始,无疑是对整个业界注入一剂兴奋剂,整个微信的生态圈的企业和个人开发者,都跃跃欲 ...

  2. 对mysql事务提交、回滚的错误理解

    一.起因 begin或者START TRANSACTION开始一个事务 rollback事务回滚 commit 事务确认 人们对事务的解释如下:事务由作为一个单独单元的一个或多个SQL语句组成,如果其 ...

  3. Codeforces Round #493 (Div. 1)

    A. /* 发现每次反转或者消除都会减少一段0 当0只有一段时只能消除 这样判断一下就行 */ #include<cstdio> #include<algorithm> #in ...

  4. mocha、should、supertest释义

    解释参考地址: https://itbilu.com/nodejs/npm/VyrFOe51-.html Mocha模块 Mocha是一个简单.可扩展的用于Node.js和JavaScript的单元测 ...

  5. mogoDB工具选择及连接<一>

    最近在某微服务项目中需要用到mogoDB 原因是:开源免费.适合互联网公司.大数据量情况下性能比mysql好 咨询过为啥不用oracle,原因你懂得 --费用 好,言归正传: 1.选择工具,使用工具是 ...

  6. [Unity基础]镜头管理类

    一个游戏中可能会有各种类型的镜头,例如有时候是第一人称,有时是第三人称,有时又会给个特写等等,因此可以定义一个镜头类型枚举,在不同的场合进行切换,管理起来很方便. CameraManager.cs u ...

  7. c#生成cad缩略图或者图片

    struct BITMAPFILEHEADER{public short bfType;public int bfSize;public short bfReserved1;public short ...

  8. 【转】Exchange Server 的防火墙开放端口

    关于exchange所用到的端口参阅下面的文档, 适用于exchange2010sp2. http://technet.microsoft.com/en-us/library/bb331973.asp ...

  9. 重识linux-linux主机上的用户信息传递

    1 查询用户 w,who,last,lastlog 1)在线用户查询  w ,who 2)账号最近的登录时间  last lastlog 2 用户对谈 write,mesg,wall 1)write ...

  10. 24.纯 CSS 创作出平滑的层叠海浪特效

    原文地址:https://segmentfault.com/a/1190000014895634 感想:这里的波浪只是侧面的,利用几个平面一部分弧旋转得到. HTML代码: <div class ...