当创建了TCP协议套接字后,客户端再调用connect()函数请求建立TCP链接。该函数通过系统调用触发tcp_v4_connect函数的执行,产生一个包含SYN标志和一个32位的序号的连接请求包,并发送给服务器端。
这是TCP三次握手的第一步。
我们知道,两个不同主机间的进程要进行通信,他们所发送的数据包所经过的路径为:
应用层→传输层→网络层→网络介质层
所以tcp_v4_connect()函数发出的SYN标志的请求包也要经过这些路径。
传输层负责的是不同应用程序之间的通信。即不同端口
网络层负责的使不同主机之间的通信,即不同的IP地址。在这期间数据包的传输通过路由来实现。路由发生在网络层。
时间戳:发送方在报文中放置一个时间戳值,接受方在确认时返回这个值以及接受时的时间戳值,以此来计算RTT值。
TCP超时与重传中最重要的部分就是对一个给定连接的往返时间( RTT)的测量。由于路由器和网络流量均会变化,因此我们认为这个时间可能经常会发生变化, TCP应该跟踪这些变化并相应地改变其超时时间。
MSS:表示TCP传往另一端的最大块数据长度,在连接建立时(SYN)双方各自通告自己的Mss,否则默认为536字节(加上20字节IP报头和TCP报头构成576字节的IP数据报)。长度为4字节
在一般的体制中,I P可以从T C P、U D P、I C M P和I G M P接收数据报(即在本地生成的数据
报)并进行发送,或者从一个网络接口接收数据报(待转发的数据报)并进行发送。IP层在内存中有一个路由表。当收到一份数据报并进行发送时,它都要对该表搜索一次。当数据报来自某个网络接口时, IP首先检查目的IP地址是否为本机的I P地址之一或者I P广播地址。如果确实是这样,数据报就被送到由I P首部协议字段所指定的协议模块进行处理。如果数据报的目的不是这些地址,那么( 1)如果I P层被设置为路由器的功能,那么就对数据报进行转发(也就是说,像下面对待发出的数据报一样处理);否则( 2)数据报被丢弃。
由上述分析这个函数应包含路由,端口,产生SYN分节,生成序号,发送包等部分。
754 int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
756         struct inet_opt *inet = inet_sk(sk);
//变量inet指向套接字struct sock中的inet选项
757         struct tcp_opt *tp = tcp_sk(sk);
//变量tp指向套接字struct sock中的TCP选项
758         struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
//将通用地址结构转换为IPv4的地址结构
759         struct rtable *rt;
//记录路由表项
760         u32 daddr, nexthop;
//daddr记录目的地址,nesthop记录下一条地址
761         int tmp;
762         int err;
763 
//判断地址长度是否合法,应该要大于或者等于其地址的长度
764         if (addr_len < sizeof(struct sockaddr_in))
765                 return -EINVAL;
//判断是否为inet协议族 
767         if (usin->sin_family != AF_INET)
768                 return -EAFNOSUPPORT;
//初始化目的地址和下一条地址
770         nexthop = daddr = usin->sin_addr.s_addr;
771         if (inet->opt && inet->opt->srr) {
772                 if (!daddr)
773                         return -EINVAL;
774                 nexthop = inet->opt->faddr;
775         }
//查找路由表项,并通过变量rt记录下来
777         tmp = ip_route_connect(&rt, nexthop, inet->saddr,
778                                RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
779                                IPPROTO_TCP,
780                                inet->sport, usin->sin_port, sk);
781         if (tmp < 0)
782                 return tmp;
783 
784         if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
785                 ip_rt_put(rt);
786                 return -ENETUNREACH;
787         }
788 
789         if (!inet->opt || !inet->opt->srr)
790                 daddr = rt->rt_dst;//如果源地址为0,则把rt_ src赋给源地址
791 
792         if (!inet->saddr)
793                 inet->saddr = rt->rt_src;
794         inet->rcv_saddr = inet->saddr;
//初始化TCP选项
796         if (tp->ts_recent_stamp && inet->daddr != daddr) {
797                 /* Reset inherited state */
798                 tp->ts_recent       = 0;//Time stamp to echo next
799                 tp->ts_recent_stamp = 0;//Time we stored ts_recent (for aging) 
800                 tp->write_seq       = 0;//序号初始化为0
801         }
802 
803         if (sysctl_tcp_tw_recycle &&
804             !tp->ts_recent_stamp && rt->rt_dst == daddr) {
805                 struct inet_peer *peer = rt_get_peer(rt);
806 
807                 /* VJ's idea. We save last timestamp seen from
808                  * the destination in peer table, when entering state TIME-WAIT
809                  * and initialize ts_recent from it, when trying new connection.
810                  */
811 
812                 if (peer && peer->tcp_ts_stamp + TCP_PAWS_MSL >= xtime.tv_sec) {
813                         tp->ts_recent_stamp = peer->tcp_ts_stamp;
814                         tp->ts_recent = peer->tcp_ts;
815                 }
816         }
817 
818         inet->dport = usin->sin_port;//目的端口地址
819         inet->daddr = daddr;//目的IP地址
820 
821         tp->ext_header_len = 0;
822         if (inet->opt)
823                 tp->ext_header_len = inet->opt->optlen;//inet的opt选项的长度
824 
825         tp->mss_clamp = 536;
826 
827         /* Socket identity is still unknown (sport may be zero).
828          * However we set state to SYN-SENT and not releasing socket
829          * lock select source port, enter ourselves into the hash tables and
830          * complete initialization after this.
831          */
//把套接字结构sk的状态置为TCP_SYN_SENT
832         tcp_set_state(sk, TCP_SYN_SENT);
//为套接字绑定一个端口,并记录在TCP的哈希表中
833         err = tcp_v4_hash_connect(sk);
834         if (err)
835                 goto failure;
836 
837         err = ip_route_newports(&rt, inet->sport, inet->dport, sk);
838         if (err)
839                 goto failure;
840 
841         /* OK, now commit destination to socket.  */
//设置套接字的路由出口信息
842         __sk_dst_set(sk, &rt->u.dst);
843         tcp_v4_setup_caps(sk, &rt->u.dst);
844         tp->ext2_header_len = rt->u.dst.header_len;
//生成一个序号
846         if (!tp->write_seq)
847                 tp->write_seq = secure_tcp_sequence_number(inet->saddr,
848                                                            inet->daddr,
849                                                            inet->sport,
850                                                            usin->sin_port);
851 
852         inet->id = tp->write_seq ^ jiffies;
//调用tcp_connect(sk)函数,为请求包设置SYN标志,并发出请求包
854         err = tcp_connect(sk);
855         rt = NULL;//rt指针指向内存0开始处
856         if (err)
857                 goto failure;
858 
859         return 0;
860 
861 failure:
//如果连接失败,则需把套接字状态设置为:TCP_CLOSE
862         /* This unhashes the socket and releases the local port, if necessary. */
863         tcp_set_state(sk, TCP_CLOSE);
864         ip_rt_put(rt);
865         sk->sk_route_caps = 0;//sk_route_caps,网络驱动特征标志
866         inet->dport = 0;
867         return err;
868

tcp_v4_connect函数分析相关推荐

  1. linux C函数之strdup函数分析【转】

    本文转载自:http://blog.csdn.net/tigerjibo/article/details/12784823 linux C函数之strdup函数分析 一.函数分析 1.函数原型: [c ...

  2. 【Android 逆向】Dalvik 函数抽取加壳 ( 类加载流程分析 | Class.cpp#findClassNoInit 函数 | DexFile.cpp#dexFindClass 函数分析 )

    文章目录 前言 一.Class.cpp#dvmDefineClass 函数分析 二.Class.cpp#findClassNoInit 函数分析 三.DexFile.cpp#dexFindClass ...

  3. 【Android 逆向】Dalvik 函数抽取加壳 ( 类加载流程分析 | DexPathList#findClass 函数分析 | DexFile#loadClassBinaryName 函数 )

    文章目录 前言 一.DexPathList.java#findClass 类加载函数源码分析 二.DexFile.java#loadClassBinaryName 函数源码分析 前言 上一篇博客 [A ...

  4. 【Android 逆向】整体加固脱壳 ( DexClassLoader 加载 dex 流程分析 | DexPathList 构造函数分析 | makeDexElements 函数分析 )

    文章目录 前言 一.DexPathList 构造函数分析 二.DexPathList.makeDexElements 函数分析 三.Element 类分析 前言 上一篇博客 [Android 逆向]整 ...

  5. 【Android 逆向】Android 逆向通用工具开发 ( adb forward 网络端口重定向命令 | PC 端逆向程序主函数分析 )

    文章目录 前言 一.adb forward 网络端口重定向命令 二.PC 端逆向程序主函数分析 前言 本篇博客重点分析 PC 端 hacktool 模块 ; 一.adb forward 网络端口重定向 ...

  6. 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 注入工具的 main 函数分析 )

    文章目录 一.注入流程 二.注入工具的 main 函数分析 一.注入流程 开始分析 [Android 逆向]Android 进程注入工具开发 ( 编译注入工具 | 编译结果文件说明 | 注入过程说明 ...

  7. 继承关系中的拷贝构造函数和赋值操作重载函数分析

    文章目录 1 继承关系中的拷贝构造函数和赋值操作重载函数分析 1 继承关系中的拷贝构造函数和赋值操作重载函数分析 在继承关系中,如果子类未实现拷贝构造函数,那么在子类进行拷贝构造操作时,会直接调用父类 ...

  8. Windows事件等待学习笔记(三)—— WaitForSingleObject函数分析

    Windows事件等待学习笔记(三)-- WaitForSingleObject函数分析 要点回顾 WaitForSingleObject NtWaitForSingleObject KeWaitFo ...

  9. fprintf/fscanf函数分析

    fprintf/fscanf函数分析 宗旨:技术的学习是有限的,分享的精神是无限的. fprintf/fscanf函数与printf/scanf区别:printf/scanf专门针对标准输入输出流,f ...

最新文章

  1. node.js(一)
  2. php内外边距,选择器与内外边距使用方法(margin,padding使用)-2019年9月4日
  3. 读取 XML 数据时,超出最大字符串内容长度配额 (8192)
  4. SSD(Single Shot MultiBox Detector):因为数据集中图像通道数不对导致的训练异常
  5. STM32之SPI从机例程
  6. struts2+spring+mybatis简单配置
  7. 新的开始,从CSDN
  8. 支付宝h5跳转小程序
  9. “风味人间”与计算机程序设计艺术《禅与计算机程序设计艺术》
  10. LeetCode面试热题十二
  11. 设计模式 “之“ 责任链模式
  12. mongodb安装及操作
  13. matlab画动物轮廓图,MATLAB一维插值的应用实例—画左右手的轮廓图
  14. 在cmd命令中写oracle语句
  15. PHP使用header实现文件下载功能
  16. datetimepick时间插件的使用
  17. 贝壳找房值百亿美元吗?
  18. SnapKit安装与使用
  19. pdffactory 打印字体_pdfFactory使用过程中的一些小技巧
  20. 仿支付宝账单的效果(listview分组 )

热门文章

  1. 解决Mac无法编辑 .bash_profile文件与使用sudo时permission denied报错
  2. Mac安装oracleVM VMware安装失败,解决方案
  3. 使用winscp在从linux向windows传输文件
  4. ctf 抓捕赵德汉_2017年网络空间安全技术大赛部分writeup
  5. 进入hbase shell速度很慢_HBase——大数据平台之分布式NoSQL数据库教程
  6. c 直接访问mysql_C语言访问MySQL数据库的方法
  7. mysql的join语句使用_MySQL开发技巧——如何正确使用Join语句
  8. This blog has been cancelled for a long time
  9. laravel contains 的用法
  10. [转]基于Storm的实时数据处理方案