概述:

  • TCP传输前先要建立连接
  • TCP在传输层
  • 点对点,一条TCP只能连接两个端点
  • 可靠传输、无差错、不丢失、不重复、按顺序
  • 全双工
  • 字节流

TCP报文段

TCP报文段的报头前20字节是固定的,后面4n字节是根据需要而添加的。

20字节的固定部分:

  • 源端口和目的端口:分别写入源端口号和目的端口号
  • 序号:0-(2^32-1),本报文段数据的第一个字节的序号,用来解决乱序问题
  • 确认序号:期望收到对方下一个报文段的第一个数据字节的序号,用来解决丢包问题
  • 数据偏移:TCP报头长度,包括固定的20字节和选项字段
  • 保留:均为0
  • 控制位:说明报文的性质,操控TCP的状态机

  • 窗口:指发送者自己的接收窗口大小,流量控制
  • 校验和:
  • 紧急指针:当URG=1时才有效,指出本报文段紧急数据的字节数
  • 选项:

连接的建立与释放

三次握手:

(1)client发出请求连接报文段,SYN=1,Seq=x。client进入SYN-SENT状态。

(2)server收到请求报文后,向client发送确认报文段。确认报文段的首部中SYN =1,ack = x + 1,同时为自己选择一个初始序列号Seq = y.server进入SYN-RCVD(同步收到)状态。

(3)client收到server的确认报文后,还有给server发送一个确认报文。 确认号ack = y + 1,而自己的Seq = x + 1。这个报文段已经可以携带数据,如果不携带数据则不消耗序号,下一个报文段序号仍为Seq = x + 1。

为什么要三次握手呢?

假设握手只有两次,如果某次数据报由于网络延迟,从client到server时,已经断开连接了,而此时server会认为是client想建立一个新的连接,于是发给client一个确认报文(第二次握手)就建立了新的连接了,显然这是错误的。如果是三次握手,client接到这个确认报文时,不予理睬,两者没有完成第三次握手,所以不会建立错误的连接了。

网上有一个比较形象的说法:

第一次对话:

老婆让甲出去打酱油,半路碰到一个朋友乙,甲问了一句:哥们你吃饭了么?
结果乙带着耳机听歌呢,根本没听到,没反应。甲心里想:跟你说话也没个音,不跟你说了,沟通失败。说明乙接受不到甲传过来的信息的情况下沟通肯定是失败的。
如果乙听到了甲说的话,那么第一次对话成功,接下来进行第二次对话。

第二次对话:

乙听到了甲说的话,但是他是老外,中文不好,不知道甲说的啥意思也不知道怎样回答,于是随便回答了一句学过的中文 :我去厕所了。甲一听立刻笑喷了,“去厕所吃饭”?道不同不相为谋,离你远点吧,沟通失败。说明乙无法做出正确应答的情况下沟通失败。
如果乙听到了甲的话,做出了正确的应答,并且还进行了反问:我吃饭了,你呢?那么第二次握手成功。
通过前两次对话证明了乙能够听懂甲说的话,并且能做出正确的应答。接下来进行第三次对话。

第三次对话:

甲刚和乙打了个招呼,突然老婆喊他,“你个死鬼,打个酱油咋这么半天,看我回家咋收拾你”,甲是个妻管严,听完吓得二话不说就跑回家了,把乙自己晾那了。乙心想:这什么人啊,得,我也回家吧,沟通失败。说明甲无法做出应答的情况下沟通失败。
如果甲也做出了正确的应答:我也吃了。那么第三次对话成功,两人已经建立起了顺畅的沟通渠道,接下来开始持续的聊天。
通过第二次和第三次的对话证明了甲能够听懂乙说的话,并且能做出正确的应答。
可见,两个人进行有效的语言沟通,这三次对话的过程是必须的。

 

四次挥手

(1)此时TCP两端都还处于ESTABLISHED状态,client不再发送数据,并发送一个FIN报文段,seq = 1,进入FIN-WAIT-1状态。

(2)server收到后回复,ack = u + 1,seq = v(v等于服务器传输数据最后一字节的序号加1),然后进入CLOSE-WAIT状态,server如果继续发送数据,client依然接收。

(3)client收到确认报文后,进入FIN-WAIT-2状态。server不再发送数据后,发出FIN,ack = u  + 1,进入LASK-ACK状态。

(4)client收到后回复,seq = u + 1, ack = w + 1(w 等于服务器后来继续发送的最后一个字节的序号加1,与v并不一定相等!),然后进入TIME-WAIT状态

(5)此时连接还没有释放,需要等待(4分钟)两端才会CLOSED。设置时间等待是因为有可能最后一个确认报文丢失而需要重传。

为什么要四次挥手呢?

因为当client发送FIN是,表示client没有要传的数据了,不代表server没有数据要传给client,所以server还需要发送FIN来表示它也没数据传输了。由于TCP是全双工的,所以并不存在谁先FIN的问题。

SYN超时问题:server如果在一定时间内没有收到client的确认报文,会重发。在Linux下,默认重试次数为5次,5次重试的时间分别为1、2、4、8、16、32s。第五次都没有收到,就会断开这个连接。

SYN Flood攻击问题:如果给服务器发送一个SYN后,就下线了,于是服务器就需要等63秒才会断开连接,这样攻击者就可以把服务器的SYN连接队列耗尽。Linux下有一个叫tcp_syncookies的参数来应对这个事。当SYN队列满了以后,TCP会通过源地址端口、目标地址端口和时间戳打造一个特别的Seq Number发回去(又叫cookie),如果是攻击者则不会有相应,如果是正常连接,则会把这个SYN Cookie发回来,然后服务端可以通过cookie建立连接。千万不要用tcp_syncookies来处理正常的大负载的连接的情况。对于正常的请求,应该调整TCP参数,第一个是:tcp_synack_retries可以用他来减少重试次数;第二个是:tcp_max_syn_backlog,可以增大SYN连接数;第三个是:tcp_abort_on_overflow处理不过来感觉直接拒绝连接!

TCP可靠传输的实现

  • TCP报文段的长度可变,根据收发双发缓存、网络状态而调整。
  • TCP收到另一端数据时,会回发确认
  • TCP能够超时重传
  • 数据校验
  • 报文段中有序号,以保证顺序正确
  • TCP提供流量控制

发送者再发送一个报文段后,暂时保存该文段的副本,收到确认后才删除;

确认报文段也需要序号,才能明白是发出去的那个数据得到了确认;

超时计时器比传输往返时间略长,但具体值不确定,根据网络情况而定(使用RTT算法)。

连续ARQ协议

实际中为了提高效率,采用流水线传输:发送方可以连续发送多个报文段(连续发送的数据长度叫做窗口)。接收方也不必对收到的每个报文都做回复,而是采用累积确认方式;

流量控制和拥塞控制

由于接收方缓存限制,发送窗口不能大于接受方接受窗口。
 

参考资料:《TCP那些事(上)》http://coolshell.cn/articles/11564.html

实验楼 TCP/IP网络协议基础 https://www.shiyanlou.com/courses/98

计算机网络 学习笔记-传输层:TCP协议简介的更多相关文章

  1. (传输层)TCP协议

    目录 首部格式数据单位特定注意自动重传请求ARQ具体实现发送缓存接收缓存滑动窗口确认丢失和确认迟到超时重传时间选择报文段的发送时机运输连接发送TCP请求客户端拥塞处理相关概念避免拥塞具体实现TCP 的 ...

  2. 传输层TCP协议

    目录 首部格式数据单位特定注意自动重传请求ARQ具体实现发送缓存接收缓存滑动窗口确认丢失和确认迟到超时重传时间选择报文段的发送时机运输连接发送TCP请求客户端拥塞处理相关概念避免拥塞具体实现TCP 的 ...

  3. OSI模型第四层传输层--TCP协议

    1.传输层2个协议tcp和udp 2.tcp的可靠性(挂号信). 面向链接的:类似寄挂号信,对方收到了并且能够确认.所以也是可靠的传输. 最大报文传输:两端可以协商传输报文大小.(协商一个报文的大小) ...

  4. 传输层tcp协议以及scoket套字节方法

    一.传输层 1.传输层的由来: 网络层的IP帮我们区分子网 以太网的Mac帮我们找到主机 所以通过IP和Mac找到了一台特定的主机 如何找到该特定主机的应用程序呢? 答案是通过端口,端口即应用程序与网 ...

  5. [计网笔记] 传输层---TCP 传输层思维导图

    传输层思维导图 TCP笔记 为什么是三次握手和四次挥手 https://blog.csdn.net/baixiaoshi/article/details/67712853 [问题1]为什么连接的时候是 ...

  6. TCP/IP五层模型-传输层-TCP协议

    ​1.定义:TCP是一种面向连接.可靠的.基于字节流的传输控制协议. 2.应用场景:TCP为可靠传输,适合对数据完整性要求高,对延时不敏感的场景,比如邮件. 3.TCP报文:①TCP报文格式: ②TC ...

  7. Java学习笔记之基于TCP协议的socket

    可以一直输入,而不是一问一答: 开两个线程,一个负责收,一个负责发. 1.先运行: package com.zr.javase0825; import java.io.BufferedReader; ...

  8. [TCP/IP] 传输层-TCP和UDP的使用场景

    传输层-TCP和UDP应用场景 TCP(传输控制协议) 需要将要传输的文件分段传输,建立会话,可靠传输,流量控制 UDP(用户报文协议) 一个数据包就能完成数据通信,不需要建立会话,不分段,不用流量控 ...

  9. [转帖]传输层安全协议TLS 1.3 RFC 8446使互联网更快、更安全

    传输层安全协议TLS 1.3 RFC 8446使互联网更快.更安全 2018-08-12 11:38:19作者:LINUX人稿源:开源社区 https://ywnz.com/linuxyffq/261 ...

随机推荐

  1. MQTT实现长连接,IM最简单实例

    1,引入MqttSDK. 2, 头文件 #import "MQTTSession.h" //定义主题#define kTopic @"lichanghong"/ ...

  2. java 代码的细节优化

    前言 代码优化,一个很重要的课题.可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个问题我是这么考虑 的,就像大海里面的鲸鱼一样,它吃一条小虾米有用吗?没用 ...

  3. 《JavaScript模式》第6章 代码复用模式

    @by Ruth92(转载请注明出处) 第6章:代码复用模式 GoF 在其著作中提出的有关创建对象的建议原则: -- 优先使用对象组合,而不是类继承. 传统模式:使用类继承: 现代模式:"类 ...

  4. 自定义EditText实现可以一键删除输入的内容

    public class MyEditText extends EditText { private Drawable dRight; private Rect rRounds; public MyE ...

  5. 设置Android studio内容的主题

    下载主题Jar包 http://color-themes.com/?view=theme&id=563a1a6e80b4acf11273ae76 导入主题: File->Import s ...

  6. mysql加单引号和不加单引号的性能比较

    刚刚我们说过了,生活中难免会有一些不如意,比如,我们用一个字符串类型的字段来作为主键,表面上,这太不如意了,然而,事实也证明这是有用的.问题也就出来了,当在查询语句中对该字段值加上单引号和不加查询耗时 ...

  7. IncDec Sequence

    题目链接 http://www.lydsy.com/JudgeOnline/problem.php?id=3043[题目描述]给定一个长度为 n 的数列{a1,a2...an},每次可以选择一个区间[ ...

  8. 函数指针的一个demo

    #include <stdio.h> typedef void (*fun_cb)(int a, int b); static fun_cb exe_fun_cb; void fun_cb ...

  9. mysql事务,START TRANSACTION, COMMIT和ROLLBACK,SET AUTOCOMMIT语法

    http://yulei568.blog.163.com/blog/static/135886720071012444422/ MyISAM不支持 START TRANSACTION | BEGIN ...

  10. finally语句总是不会被执行?

    答案是否(1)try语句没有被执行到,如在try语句之前return就返回了,这样finally语句就不会执行.这也说明了finally语句被执行的必要而非充分条件是:相应的try语句一定被执行到.( ...