应用程序连接服务器时,目的地套接字地址(端口号和IP地址)以参数形式传递给系统调用connect(tcp_v4_connect())。下面逐步介绍初始化该连接

  1. 检查内核路由表,查找给定目的地IP地址路由表。该路由包含传出设备信息,如果没有传出设备,则初始化APR特定信息,并缓冲以便后用。若没有找到则返回错误。

    /**
    * 特殊的路由查找函数,用于TCP。
    * 是对普通路由缓存查找函数的封装。
    */
    static inline int ip_route_connect(struct rtable **rp, u32 dst,
    u32 src, u32 tos, int oif, u8 protocol,
    u16 sport, u16 dport, struct sock *sk)
    {
    struct flowi fl = { .oif = oif,
    .nl_u = { .ip4_u = { .daddr = dst,
    .saddr = src,
    .tos = tos } },
    .proto = protocol,
    .uli_u = { .ports =
    { .sport = sport,
    .dport = dport } } }; int err;
    if (!dst || !src) {
    err = __ip_route_output_key(rp, &fl);
    if (err)
    return err;
    fl.fl4_dst = (*rp)->rt_dst;
    fl.fl4_src = (*rp)->rt_src;
    ip_rt_put(*rp);
    *rp = NULL;
    }
    return ip_route_output_flow(rp, &fl, sk, );
    }

    查找路由

  2. 为 SYN报文分配一个报文(sk_buff),构建tcp头,完成后将其发往IP层。
    * 构造并发送SYN段 */
    int tcp_connect(struct sock *sk)
    {
    struct tcp_sock *tp = tcp_sk(sk);
    struct sk_buff *buff; tcp_connect_init(sk);/* 初始化传输控制块中与连接相关的成员 */ /* 为SYN段分配报文并进行初始化 */
    buff = alloc_skb(MAX_TCP_HEADER + , sk->sk_allocation);
    if (unlikely(buff == NULL))
    return -ENOBUFS; /* Reserve space for headers. */
    skb_reserve(buff, MAX_TCP_HEADER); TCP_SKB_CB(buff)->flags = TCPCB_FLAG_SYN;
    TCP_ECN_send_syn(sk, tp, buff);
    TCP_SKB_CB(buff)->sacked = ;
    skb_shinfo(buff)->tso_segs = ;
    skb_shinfo(buff)->tso_size = ;
    buff->csum = ;
    TCP_SKB_CB(buff)->seq = tp->write_seq++;
    TCP_SKB_CB(buff)->end_seq = tp->write_seq;
    tp->snd_nxt = tp->write_seq;
    tp->pushed_seq = tp->write_seq;
    tcp_ca_init(tp); /* Send it off. */
    TCP_SKB_CB(buff)->when = tcp_time_stamp;
    tp->retrans_stamp = TCP_SKB_CB(buff)->when; /* 将报文添加到发送队列上 */
    __skb_queue_tail(&sk->sk_write_queue, buff);
    sk_charge_skb(sk, buff);
    tp->packets_out += tcp_skb_pcount(buff);
    /* 发送SYN段 */
    tcp_transmit_skb(sk, skb_clone(buff, GFP_KERNEL));
    TCP_INC_STATS(TCP_MIB_ACTIVEOPENS); /* Timer for repeating the SYN until an answer. */
    /* 启动重传定时器 */
    tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);
    return ;
    }

    构建并发送SYN段代码

  3. IP层首先检查传出报文的缓冲路由是否有效,若无效再次尝试获得有效路由。发生这种情况是因为路由从第一次发现目的路由时就已经改变,了能会产生路由失效。
  4. 若路由缓存有效,则构建报文的IP头。
  5. 检查防火墙策略,查看其是否允许该报文发出。如果允许发出,则在计算IP校验和并将其放在IP头的checksum域。发送到链路层。
    /**
    * TCP和SCTP发送包所用的函数。
    * 此函数只接收两个输入参数,所有处理包所需要的信息都可以通过skb直接或者间接的存取。
    * Skb: 要传输的包的缓冲区描述符。此数据结构有填入IP报头以及传输包所需要的所有参数(如下一跳网关)。记住,ip_queue_xmit用于处理本地产生的包。转发包没有相关的套接字。
    * Ipfragok: 主要由SCTP使用的标志,用来指出是否允许分段。
    */
    int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
  6. 如果前面全部通过,报文得到一个最终的有效传出设备。接着构建链路层头,只有当目的地IP有一个硬件地址时,才能构建链路层头。如果不知道目的地硬件地址,就需要发送APR请求。从APR确认中得到目的地IP硬件地址。
  7. 将该报文放入设备队列做最终传输。
  8. 从设备队列取出报文并检查是否可以从设备传输报文,若可以,则当前帧利用设备DMA来发送报文。否则重新将报文放入设备队列,使设备到CPU排队,并向CPU发出TxIRQ。CPU处理Tx softIRQ,取出报文并发送报文。
  9. 报文成功传输后产生Tx中断,成功发送的报文将从Tx中断释放。                     

  前面阐述啦首次连接设置的处理过程,在此过程缓存了一些重要信息,如路由、设备、APR等。下面将介绍TCP套接着写数据。

  • 查找与套接字描述符相对应的套接字,利用Inode和私有数据找到该套接字。
  • 向已连接的套接字写数据。TCP将数据复制到上一个报文(sk_buff没有满),或者创建一个新的报文(sk_buff)
  • 写完成后查询tcp状态机,检查是否可以立即发送数据。如果可以,接着就构建tcp头,将其发往ip层。否则,将报文放到tcp发送缓冲区结尾排队。
  • 若在结尾排队,检查是否可以发送首报文。若可以,则构建tcp头发往IP层。同时初始化TCP重传定时器。

  报文从套接字到达设备要经历三个阶段:

  1. 套接字发送队列sk->write_queue。
  2. 设备队列dev->q。
  3. 网络控制器的DMA Tx环缓冲区。

TCP/IP协议栈(三)——linux 向下的报文处理的更多相关文章

  1. TCP/IP协议栈在Linux内核中的运行时序分析

    网络程序设计调研报告 TCP/IP协议栈在Linux内核中的运行时序分析 姓名:柴浩宇 学号:SA20225105 班级:软设1班 2021年1月 调研要求 在深入理解Linux内核任务调度(中断处理 ...

  2. 浅谈TCP IP协议栈(三)路由器简介

    读完这个系列的第一篇浅谈TCP/IP协议栈(一)入门知识和第二篇浅谈TCP/IP协议栈(二)IP地址,在第一篇中,可能我对协议栈中这个栈的解释有问题,栈在数据结构中是一种先进后出的常见结构,而在整个T ...

  3. 理解TCP/IP协议栈之HTTP2.0

    1 前言 前面写了10多篇关于Redis底层实现.工程架构.实际应用的文章,感兴趣的读者可以进行阅读,如有问题欢迎交流: 1.Redis面试热点之底层实现篇-12.Redis面试热点之底层实现篇-23 ...

  4. linux OSI七层模型、TCP/IP协议栈及每层结构大揭秘

    学习Linux,就算是像小编我这样的小萌新,也知道OSI模型.什么?!你不知道!!! 好吧,这篇秘籍拿走,不谢~~~ 一.两个协议 (1)OSI 协议模型(7层)国际协议    PDU:协议数据单元对 ...

  5. Linux服务器丢包故障的解决思路及引申的TCP/IP协议栈理论

    我们使用Linux作为服务器操作系统时,为了达到高并发处理能力,充分利用机器性能,经常会进行一些内核参数的调整优化,但不合理的调整常常也会引起意想不到的其他问题,本文就一次Linux服务器丢包故障的处 ...

  6. [转载]Linux服务器丢包故障的解决思路及引申的TCP/IP协议栈理论

    Linux服务器丢包故障的解决思路及引申的TCP/IP协议栈理论 转载至:https://www.sdnlab.com/17530.html 我们使用Linux作为服务器操作系统时,为了达到高并发处理 ...

  7. UNIX/Linux网络编程基础:图解TCP/IP协议栈

    目录 1.主机到网络层协议:以太网协议 2.IP协议 3.网际控制报文协议(ICMP) 4.传输控制协议(TCP) 5.用户数据报文协议(UDP) 6.流控制传输协议(SCTP) 7.地址解析协议(A ...

  8. 用virtualbox+模拟串口+CDT调试linux内核 TCP/IP协议栈-起步

    经常有人问一台机器如何将hello经网络发送给另一台机器,我确实是不知道,只能看代码了. 说明:本人对内核的研究学习也是刚刚起步,有很多不了解的,所以文中可能会有一些"一本正经的胡扯&quo ...

  9. [转帖]Linux TCP/IP协议栈,数据发送接收流程,TCP协议特点

    Linux TCP/IP协议栈,数据发送接收流程,TCP协议特点 http://network.51cto.com/art/201909/603780.htm 可以毫不夸张的说现如今的互联网是基于TC ...

随机推荐

  1. 我的第一个python web开发框架(18)——前台页面与接口整合

    由于我们前后台系统没有分开,所以前台页面调用接口时,可以直接使用后台管理系统已经完成的接口,不过后台管理系统接口的访问加上了登录验证,所以需要将前台要用到的接口进行处理,让它们设置到白名单当中 我们打 ...

  2. 【剑指Offer学习】【面试题21:包括min 函数的栈】

    题目: 定义栈的数据结构,请在该类型中实现一个可以得到栈的最小素的min 函数.在该栈中.调用min.push 及pop的时间复杂度都是0(1) 解题思路: 把每次的最小元素(之前的最小元素和新压入战 ...

  3. UVA - 11396 Claw Decomposition(二分图染色)

    题目大意:给你一张无向图,每一个点的度数都是3. 你的任务是推断是否能把它分解成若干个爪(每条边仅仅能属于一个爪) 解题思路:二分图染色裸题.能够得出:爪的中心点和旁边的三个点的颜色是不一样的 #in ...

  4. STM32W108无线射频模块通用IO接口应用实例

    STM32W108无线射频模块通用IO接口应用实例 本实例编写STM32W108的GPIO測试程序,通过控制GPIO引脚,实现对LED灯的控制. 开发环境与硬件说明 硬件:STM32W108无线开发板 ...

  5. 五:Java之Vector类专题

    据说期末考试要考到Vector 这个类,出于复习须要在这里就要好好整理下这个类了. 一.基本概念 Vector 是可实现自己主动增长的对象数组. java.util.vector提供了向量类(vect ...

  6. webAPP踩坑记录

    最近公司突然给我们下了一个任务  一个星期要做出一个系统网站 外加手机app   2个同事负责 web开发  我负责手机app 的开发 今天终于初级版本做完了,记录一下手机app踩过的坑与优化之路 用 ...

  7. java多线程编程核心技术——全书总结

    这本书大致上是看完了,不过第七章结束的匆匆忙忙很不好. 不过好在还是看完了,勉强算吧. 回想这一年,挺感慨的,心里一直谋求着进步,却很难行动起来. 仔细想想确实啊,想一直进步肯定要牺牲自己的业余时间, ...

  8. REST设计规则

    1.简介 REST(Representational State Transfer), 表述性状态转移是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格. REST只是一 ...

  9. linux 磁盘管理三部曲——(2)管理分区,文件系统类型格式化

    上篇小编给大家讲解了磁盘结构和分区的介绍,这篇小编就给大家演示如何管理分区和文件系统类型格式化. 小编上篇已经提到如何使用磁盘,今天这两步,就是其中很重要的两步.(前几天写的有点急,有点乱,今天又整理 ...

  10. 如何在华为云软件开发云上搭建JavaWeb,Maven项目

    本文将使用华为云软件开发云向大家演示如何搭建JavaWeb,Maven项目. 一.相关信息 1.华为云软件开发云简介 华为云软件开发云(DevCloud)是集华为近30年研发实践,前沿研发理念,先进研 ...