zoukankan      html  css  js  c++  java
  • 计算机网络 学习笔记-传输层:TCP协议简介

    概述:

    • 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  

  • 相关阅读:
    第七周psp
    【探路者】第三周立会报告6(总第18次)
    版本控制报告
    【探路者】第三周立会报告5(总第17次)
    【探路者】第三周立会报告4(总第16次)
    【探路者】第三周立会报告3(总第15次)
    #【探路者】第三周立会报告2(总第14次)
    【探路者】第三周立会报告1(总第13次)
    PSP
    【探路者】第二周立会报告6(总第12次)
  • 原文地址:https://www.cnblogs.com/jacklu/p/4489028.html
Copyright © 2011-2022 走看看