zoukankan      html  css  js  c++  java
  • TCP/IP五层模型-传输层-TCP协议

    ​1.定义:TCP是一种面向连接、可靠的、基于字节流的传输控制协议。

    2.应用场景:TCP为可靠传输,适合对数据完整性要求高,对延时不敏感的场景,比如邮件。

    3.TCP报文:①TCP报文格式:

    ②TCP首部字段信息:

    源端口号:源端口和IP地址的作用是标识报文的返回地址。
    目的端口号:端口指明接收方计算机上的应用程序接口。
    (作用:TCP报头中的源端口号和目的端口号同IP数据报中的源IP与目的IP唯一确定一条TCP连接。)
    序号:序号是本报文段发送的数据组的第一个字节的序号,序号确保了TCP传输的有序性。
    确认号:确认号,即ACK,指明下一个期待收到的字节序号,表明该序号之前的所有数据已经正确无误的收到。确认号只有当ACK标志为1时才有效。
    数据偏移/首部长度:指出TCP报文段的起始处到TCP报文段的数据起始处的距离,占4bit。保留:为将来定义新的用途保留,现在一般置0。
    控制位:
    URG:紧急指针标志。当发送方URG=1时,表明紧急指针字段有效,它告诉系统此报文段中有紧急数据,应尽快传送,发送的数据不用进入缓冲区而直接交付给上一层。
    【注意】URG标志位:URG(紧急位)是表示紧急指针是否有效,当URG为1的时候就表示紧急指针是有效的。紧急指针通常情况下是无效的,当设置为有效的时候就表示数据要优先处理。紧急指针是一个正的偏移量,和序号字段中的值相加表示紧急数据最后一个字节的序号。TCP的紧急方式是发送端向另一端发送紧急数据的一种方式,紧急指针指向的是包内数据段的某个字节(数据从第一字节到指针所指字节就是紧急数据),紧急数据是不进入缓冲区的直接交给上层进程的(一般情况下TCP是要等到整个缓存都满了再向上交付的)。
    PSH:PSH标志是为了提示接收端的应用程序应该立即从TCP的接收缓冲区中拿走数据,为了接收后续的数据来腾出空间(如果应用程序不将接收到的数据拿走的话,它们就会一直都留在TCP的接收缓冲区中)。PSH(急迫位)当PSH为1的时候,客户端发给服务器的报文段立即被服务器TCP交付给应用程序来处理,而不用等整个缓存都填满再向上交付。一般情况下,TCP是等缓冲区写满再向上交付的,当PSH为1的时候数据还是要进入缓存区向上提交的,只不过不用等缓冲区满后才提交。这里所说的数据包括与此PUSH包一起传输的数据以及之前就为该进程传输过来的数据(滞留在缓存中的数据)。
    (URG与PSH的区别:发送方URG有效的时候,发送的数据不用进入缓冲区而直接交付给上一层;发送方PSH有效的时候,接收方收到后,发送的数据要进入缓冲区但不用等缓冲区满就交给上一层。URG是针对发送方发送紧急数据的,PSH是针对接收方,接收方尽快将数据向上层交付。
    ACK:确认序号标志,为1时表示确认号有效,为0表示确认号无效。)
    PSH:push标志,为1表示是带有push标志的数据,指示接收方在接收到该报文段以后,应尽快将这个报文段交给应用程序,发送的数据要进入缓冲区但不用等缓冲区满就交给上一层。
    RST:重置位。当RST=1时,表明在TCP连接中出现严重差错,必须释放当前连接,然后再重新建立传输连接。RST置1用来拒绝一个非法的报文段或拒绝打开一个连接。
    SYN:在建立连接时用来同步序号。当SYN=1而ACK=0时,表明这是一个连接请求报文段。对方若同意建立连接,则应在响应的报文段中使SYN=1和ACK=1。SYN置1表示连接请求或接收连接。
    FIN:finish标志,用于释放连接,为1时表示发送方已经没有数据发送了,即关闭本方数据流。
    窗口:滑动窗口大小,用来告知发送端接受端的缓存大小,以此控制发送端发送数据的速率,从而达到流量控制。
    校验和:检验首部和数据两部分,检验时需要在TCP报文段的前面加上12字节的伪首部。
    紧急指针:只有当 URG 标志置 1 时紧急指针才有效,TCP 的紧急方式是发送端向另一端发送紧急数据的一种方式。
    选项:TCP报文数据段中数据字段的最大长度,又称为MSS。MSS = MTU – TCP头部 – IP头部。MTU是指一种通信协议的某一层上面所能通过的最大数据包大小(以字节为单位),默认是1500字节。

    ③数据部分:TCP 报文段中的数据部分是可选的。在一个连接建立和一个连接终止时,双方交换的报文段仅有 TCP 首部。如果一方没有数据要发送,也使用没有任何数据的首部来确认收到的数据。

    4.TCP的功能/特点:①面向连接:三次握手:

    • 客户端请求建立连接,syn=1,seq=x,客户端进入syn_sent状态。

    • 服务器收到客户端发送的syn包,同意建立连接,ack=1,ack。number=x+1;服务器请求建立连接,syn=1,seq=y,服务器进入syn_rcvd状态。

    • 客户端收到服务器发送的syn+ack包,同意建立连接,ack=1,ack number=y+1,客户端和服务器进入established状态。

    四次挥手:

    • 客户端发送完成,请求断开连接, fin=1, seq=u。

    • 服务器同意断开连接, ack=1 ,ack number = u+1。

    • 服务器发送完成,请求断开连接,fin=1 , seq=i。

    • 客户端同意断开连接,ack=1, ack number = i+1。

    为什么TCP建立连接要三次握手?

    三次握手的目的是同步连接双方的序列号和确认号并交换 TCP 窗口大小信息。为什么两次握手不行?因为两次握手可能丢包而出现死锁,假设在两次握手场景中,C向S发送请求,S收到并发送确认请求给C,这时候S认为连接已经建立,并开始发送数据给C,但是那个确认请求丢包了,C不认为请求建立了,C当然会拒绝接受S发送来的数据,并且再去请求连接。这样,一个资源就死锁了。最后,握手当然可以四次五次一直握下去,但三次已经够了,就没有必要了。总结下来一句话,主要目的防止在网络发生延迟或者丢包的情况下浪费资源。

    为什么断开连接要四次挥手而不是三次?

    服务器收到客户端发送的fin包,就回客户端一个ack包。但是这个时候服务器可能还在发送数据,不能马上关闭数据连接通道。所以服务器给客户端回的ack和fin不是同时发送的,服务器把数据包发送完后,才会发送fin包给客户端。而在建立连接时,服务器把ack和syn这两个包合并成了一个包发送给客户端。

    ②可靠性:

    超时重传:PC用TCP协议发送一个报文段,会立即启动一个重传计时器,等待目的端口确认收到这个数据段,否则将超时重传。
    确认机制:每个报文都有序列号,发送完成后,收到对方回复的ack置位的确认包(ack的值为序列号+1)才认为成功发送,否则重传。
    滑动窗口:根据接受端缓存区大小,灵活调整发包速率,保证数据传输的稳定性。
    首部校验:TCP数据报文段中有首部和数据的校验和。目的是检测数据在传输过程中的任何变化,如果收到段的检验和有差错,如果出错的话,则接收端不会发送确认,从而触发发送方的确认重传。
    重复丢弃:IP数据报可能会出现重复,TCP的接收端必须丢弃重复的数据。
    有序性(Seq):TCP将每个字节的数据都进行了编号,这就是序列号。TCP报文段作为IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。如果必要,TCP将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层。(对失序数据进行重新排序,然后才交给应用层)。

    ③为什么说TCP是基于字节流?

    ④拓展:

    2MSL:TIMEWAIT状态也称为2MSL等待状态。每个具体TCP实现必须选择一个报文段最大生存时间MSL(Maximum Segment Lifetime)。它是任何报文段被丢弃前在网络内的最长时间。我们知道这个时间是有限的,因为TCP报文段以IP数据报在网络内传输,而IP数据报则有限制其生存时间的TTL字段。对一个具体实现所给定的MSL值,处理的原则是:当TCP执行一个主动关闭,并发回最后一个ACK,该连接必须在TIMEWAIT状态停留的时间为2倍的MSL。这样可让TCP再次发送最后的ACK以防这个ACK丢失(另一端超时并重发最后的FIN)。这种2MSL等待的另一个结果是这个TCP连接在2MSL等待期间,定义这个连接的插口(客户的IP地址和端口号,服务器的IP地址和端口号)不能再被使用。这个连接只能在2MSL结束后才能再被使用。

    设置TIMEWAIT的原因:

    大量 TIME_WAIT 产生的原因及解决办法:

    出现RST包的原因:

    • 客户端来连接时,服务器端口未打开

    • 在一个已关闭的SOCKET上收到数据

    • 请求超时

    • 提前关闭

    大量CLOSE_WAIT产生的原因及解决办法:

    半开、半闭连接:半开连接:从协议定义的角度来说,TCP的半开连接是指TCP连接的一端异常崩溃,或者在未通知对端的情况下关闭连接,这种情况下不可以正常收发数据,否则会产生RST。比如TCP连接的一端异常断电或是受到了syn攻击,就会导致TCP的半开连接。如果没有数据传输,对端就不会知道本端的异常而一直处于ESTABLISHED状态。

    半闭连接: TCP的半闭连接是指TCP连接只有一方发送了FIN,另一方没有发出FIN包,仍然可以在一个方向上正常发送数据。这种场景并不常见,一般来说Berkeley sockets API调用shutdown()接口时候就会进入半关闭状态(调用常规的close()一般是期待完整的双向关闭这个TCP连接),shutdown()接口相当指示程序,本端已经没有数据待发送,所以我发送一个FIN到对端,但是我仍然想要从对端接收数据,直到对端发送一个FIN指示关闭连接为止。

    syn flood攻击:定义:在三次握手过程中,Server发送SYN-ACK之后,收到Client的ACK之前的TCP连接称为半连接(half-open connect),此时Server处于SYN_RCVD状态,当收到ACK后,Server转入ESTABLISHED状态。SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server回复确认包,并等待Client的确认,由于源地址是不存在的,因此,Server需要不断重发直至超时,这些伪造的SYN包将长时间占用未连接队列,服务器将维护一个非常大的半连接列表,这样就会导致正常的SYN请求因为队列满而被丢弃,从而引起网络堵塞甚至系统瘫痪。SYN攻击时一种典型的DDOS攻击。攻击方式:

    • Direct Attack 攻击方使用固定的源地址发起攻击,这种方法对攻击方的消耗最小。

    • Spoofing Attack 攻击方使用变化的源地址发起攻击,这种方法需要攻击方不停地修改源地址,实际上消耗也不大。

    • Distributed Direct Attack 这种攻击主要是使用僵尸网络进行固定源地址的攻击。

    防御方法:

    5.用TCP传输数据的应用层协议:服务器同步数据的dns、ftp、smtp/pop3、http、telnet、ssh等。

  • 相关阅读:
    [转]WIBKIT技术资料
    WebKit学习要点
    提高IOS开发效率的常用网站、开源类库及工具
    【浏览器那些基础】Android平台有那些CPU类型
    深刻的理解
    Spring Boot 最流行的 16 条实践解读,值得收藏!
    MyBatis动态SQL(认真看看, 以后写SQL就爽多了)
    为什么很多 SpringBoot 开发者放弃了 Tomcat,选择了 Undertow?
    朋友,别告诉我你懂分布式事务!
    分布式锁用 Redis 还是 Zookeeper?
  • 原文地址:https://www.cnblogs.com/dawangk-3366/p/14286143.html
Copyright © 2011-2022 走看看