TCP

OSI

TCP 在OSI的第4层,传送的为Segment
IP 在OSI的第3层,传送的是Packet
ARP,RARP 在OSI的二层,数据链路层,传送的是Frame

OSI七层:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层

交换机工作在数据链路层,路由器工作在网络层

TCP/IP 四层 : 网络接口层、网络层、传输层、应用层

三次握手建立连接:

第一次握手:客户端发送syn包(seq=x)到服务器,并进入SYN_SEND状态,等待服务器确认,服务器端经过socket,bind,linsten 此时处于linsten状态;阻塞等待客户端连接
(此时客户端进行socket,进行connet,发起请求,阻塞等待服务器响应)

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(seq=y),即SYN+ACK包,此时服务器由linsten状态进入SYN_RECV状态;

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),只发送ACK包,此包发送完毕,
客户端和服务器进入ESTABLISHED状态,完成三次握手。

握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。

四次握手断开连接:

第一次挥手:主动关闭方发送一个FIN,用来关闭主动方到被动关闭方的数据传送,也就是主动关闭方告诉被动关闭方:我已经不会再给你发数据了(当然,在fin包之前发送出去的数据,如果没有收到对应的ack确认报文,主动关闭方依然会重发这些数据),但此时主动关闭方还可以接受数据,
主动方进入FIN_WAIT_1状态。此时服务器进入CLOSE_WAIT状态

第二次挥手:被动关闭方收到FIN包后,发送一个ACK给对方,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),此时主动方处于FIN_WAIT_2状态。

第三次挥手:被动关闭方发送一个FIN,用来关闭被动关闭方到主动关闭方的数据传送,也就是告诉主动关闭方,我的数据也发送完了,不会再给你发数据了。
(在二、三挥手之间,被动关闭方仍然可以发送数据给主动关闭方,但是主动方不能发送数据给被动方)

第四次挥手:主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1,主动方进入TIME_WAIT状态,至此,完成四次挥手。

四次挥手

关闭连接时,当收到对方的 FIN 报文通知时,它仅仅表示对方没有数据发送给你了,但是你还可以给对方发送数据。TCP允许单向关闭,也有这么种可能,
你还有一些数据在传给对方的途中,所以你不能立马关闭连接,也即你可能还需要把在传输途中的数据给对方之后,
又或者,你还有一些数据需要传输给对方后,(再关闭连接)再发送FIN 报文给对方来表示你同意现在可以关闭连接了,所以它这里的 ACK 报文和 FIN 报文多数情况下都是分开发送的

为什么 TIME_WAIT 状态还需要等 2MS L后才能返回到 CLOSED 状态?
这是因为虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,
按理可以直接回到 CLOSED 状态(就好比从 SYN_SEND 状态到 ESTABLISH 状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的 ACK 报文会一定被对方收到,因此对方处于 LAST_ACK 状态下的 SOCKET 可能会因为超时未收到 ACK 报文,而重发 FIN 报文,所以这个 TIME_WAIT 状态的作用就是用来重发可能丢失的 ACK 报文

  • 超时重传

在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。

  • 快速重新发送

超时重新发送的机制:发送方送出一个TCP片段,然后开始等待并计时,如果RTO时间之后还没有收到ACK回复,发送方则重新发送。TCP协议有可能在计时完成之前启动重新发送,也就是利用快速重新发送。快速发送机制如果被启动,将打断计时器的等待,直接重新发送TCP片段。

当接收方收到乱序片段的时候,需要重复发送ACK。比如接收到乱序片段9的时候,接收方需要回复ACK。回复号为8 (7+1)。此后接收方如果继续收到乱序片段(序号不是8的片段)将再次重复发送ACK=8。当发送方收到3个ACK=8的回复时,发送方推断片段8丢失。即使此时片段8的计时器还没有超时,发送方会打断计时,直接重新发送片段8

比较超时重传和快速重传,可以发现超时重传是发送端在傻等超时,然后触发重传;而快速重传则是接收端主动告诉发送端数据没收到,发送断连续收到标号相同的ACK包,然后触发发送端重传。

TCP UDP

  • IP协议和UDP协议采用的是数据包方式传送,后发出的数据包可能早到,所以不能保证到达次序。而TCP可以确保数据到达的次序和文本流顺序一致。所以UDP只有
    等到所有数据到达后,再进行排序,然后再组装。而TCP可以一边接收,一边写入。

  • 文本流很长的话,TCP以片段(segment)发送。每个片段也分为头部和数据部分,头部会有该片段的序号,这样接收方就知道该片段在流中的顺序
    和下一个要接受的片段。

  • ACK是一位(bit)。只有ACK位设定的时候,回复号(Acknowledgement number)才有效。ACK回复号说明了接收方期待接收的下一个片段,
    所以ACK回复号为最后接收到的片段序号加1。一个片段可以只包含ACK回复,一个纯粹的ACK回复片段不传送文本流,所以不消耗序列号
    如果有下一个是正常的要发送的数据片段,它的序号将与纯粹ACK回复片段的序号相同。

  • 在TCP连接中,我们通过将ACK回复“附着”在其他数据片段的方式,减少了ACK回复所消耗的流量。但TCP协议并不是对每个片段都发送ACK回复。TCP协议实际采用的是累计ACK回复。接收方往往利用一个ACK回复来知会连续多个片段的成功接收。

  • 在TCP重新发送中,TCP处理片段丢失的方法:ACK超时和重复ACK

  • 如何确认一个TCP报文是重传报文
    在实际的数据交互过程中,重传报文一般具有以下两个特征:一是TCP交互序列号突然下降,二是其在TCP报头中的序列号、数据长度、应用数据等参数跟前面某TCP报文一致。

  • TCP 是流socket, UDP 是数据报socket

滑窗

利用滑窗,我们一定程度上实现了对乱序数据的缓存;滑窗被同时应用于接收方和发送方

我们假设一个可以容纳三个片段的滑窗,并假设片段从左向右排列。对于发送方来说,滑窗的左侧为已发送并已ACK过的片段序列,滑窗右侧是尚未发送的片段序列。滑窗中的片段(比如片段5,6,7)被发送出去,并等待相应的ACK。如果收到片段5的ACK,滑窗将向右移动。这样,新的片段从右侧进入滑窗内,被发送出去,并进入等待状态。在接收到片段5的ACK之前,滑窗不会移动,即使已经收到了片段6和7的ACK。这样,就保证了滑窗左侧的序列是已经发送的、接收到ACK的、符合顺序的片段序列。

对于接收方来说,滑窗的左侧是已经正确收到并ACK回复过的片段(比如片段1,2,3,4),也就是正确接收到的文本流。滑窗中是期望接收的片段(比如片段5, 6, 7) 同样,如果片段6,7先到达,那么滑窗不会移动。如果片段5先到达,那么滑窗会向右移动,以等待接收新的片段。如果出现滑窗之外的片段,比如片段9,那么滑窗将拒绝接收。

流量控制可控制滑动窗口的大小,来控制发送速率,可以使发送和接受能力相匹配。

滑动窗用来做流量控制。流量控制只关注发送端和接受端自身的状况,而没有考虑整个网络的通信情况。堵塞控制,则是基于整个网络来考虑的。一旦发送方认为TCP片段丢失,则认为网络中出现堵塞;TCP协议通过控制滑窗(sliding window)大小来控制发送速率,从而实现堵塞控制。

在TCP滑窗管理中,我们已经见到了一个窗口限制,就是advertised window size,以实现TCP流量控制。TCP还会维护一个congestion window size,以根据网络状况来调整滑窗大小。真实滑窗大小取这两个滑窗限制的最小值,从而同时满足两个限制 (流量控制和堵塞控制)。

长短连接

短连接就是一次TCP请求得到结果后,连接马上结束.而长连接并不马上断开,而一直保持着,直到长连接TIMEOUT.长连接可以避免不断的进行TCP三次握手和四次挥手.
长连接(keepalive)是需要靠双方不断的发送探测包来维持的,keepalive期间服务端和客户端的TCP连接状态是ESTABLISHED. 目前http 1.1版本里默认都是keepalive(1.0版本默认是不keepalive的)

HTTP/1.0 缺点 : 无连接,每一次请求都要重新建立TCP连接,所以每一次HTTP请求都要花费2倍RTT时间(一次TCP请求,一次HTTP请求)

HTTP/1.1 : 使用持续连接,即保持TCP连接一段时间.

TCP的三次握手过程?为什么会采用三次握手,若采用二次握手可以吗?

参考答案

答:建立连接的过程是利用客户服务器模式,假设主机A为客户端,主机B为服务器端。
(1)TCP的三次握手过程:主机A向B发送连接请求;主机B对收到的主机A的报文段进行确认;主机A再次对主机B的确认进行确认。
(2)采用三次握手是为了防止失效的连接请求报文段突然又传送到主机B,因而产生错误。失效的连接请求报文段是指:主机A发出的连接请求没有收到主机B的确认,于是经过一段时间后,主机A又重新向主机B发送连接请求,且建立成功,顺序完成数据传输。考虑这样一种特殊情况,主机A第一次发送的连接请求并没有丢失,而是因为网络节点导致延迟达到主机B,主机B以为是主机A又发起的新连接,于是主机B同意连接,并向主机A发回确认,等待传输数据。而此时主机A根本没有数据可传,因为是之前丢失的请求,主机B就一直在等待主机A发送数据,导致主机B的资源浪费。
(3)采用两次握手不行,原因就是上面说的实效的连接请求的特殊情况。

C发送请求,S应答并分配资源
若S的应答没有到达C端,C认为连接未建立,而S认为建立了
S会在一段时间内保留分配的资源
如果大量C这样请求,S会崩溃

  • 能否采用三次挥手?可以
    当服务端收到第一个FIN,并且自己也不需要发送数据了,则合并ACK,FIN为一个段报文,然后客户端再回应ACK,总共为三次

IP

  • A类
    A类网络位占8为,主机位占24位,其中第一位为0 表示A类地址,所以网络位分布为 0 0000000(0) --- 0 1111111 (127)
    其中0和127保留,所以网络为总共有126个。主机位为后24位,全部为0和1的保留,总共有2^24-2个

  • B类 以10开始
    B类网络位占16个字节,主机位16位,网络位分布为 10 000000 00000000(128.0) -- 10 111111 11111111(191.255),
    前两位固定,所以网络位总共有 214-2=16382个。主机位为后16位,去掉全0和全1的,总共有216-2= 65534个

  • C类 以110开始
    C类网络位占24个字节,网络位分布为 110 00000 00000000 00000000 (192.0.0.) -- 110 11111 11111111 11111111 (223.255.255)
    前3位固定,所以网络为总共有 2^21 -2 个。主机位为后8位,去掉全0和全1的,总共有 2^8-2=254个

  • 192.168.128.10/24 后面的24表示网络位

  • 子网掩码 网络位全位1 主机位全为0

HHTTPS

HTTPS协议在HTTP协议的基础上,在HTTP和TCP中间加入了一层SSL/TLS加密层

HTTP协议

  1. HTTP请求 包含三个内容 1. 请求行 2.HTTP请求头 3. 内容
  • 请求行
由三部分组成
请求方法  请求网址 HTTP版本 
  • HTTP请求头
cache头域  

客户端If-Mdified-Since     将浏览器的缓存页面的最后修改时间发送到服务器,服务器会把这个时间和服务器本地时间对比。如果时间一致,就返回304,客户端直接使用本地缓存,如果不一致就会返回200和新的内容。客户端收到新的内容,就会丢弃旧文件,缓存新文件。If-Mdified-Since 和服务器端cache于的Last-Modified对比

客户端If-None-Match  和服务器端ETag一起工作。在response中添加ETag信息,当用户再次请求该资源时,将在Request中加入If-None-Match信息(ETag的值),如果服务器验证该资源的ETag没有变,将返回一个304,告诉客户端使用本地缓存文件,否则将返回200和新的资源和ETag.

client头域

Accept   --浏览器端可以接受的类型, */* 代表浏览器可以处理任意类型
Accept-Encoding  --浏览器申明自己的编码方法(不是字符编码)和压缩方法
User-Agent
Accept-Charset  --浏览器接受的字符集,这是字符编码

Miscellaneous头域

Referer  --告诉服务器我是从哪个链接过来的
  • 内容
请求头和内容之间有个空行

内容只在POST请求中存在,GET请求不包含实体
  1. HTTP响应 包含三个内容 1.状态行 2. HTTP响应头 3. 返回内容
  • 状态行
三部分组成

HTTP版本  响应状态码  状态码描述

信息类(100-199)

响应成功(200-299)

重定向类(300-399)

302  Found-- 重定向  新的url会在response中的Location中返回,浏览器会使用新的url发出请求

304 Not Modified --使用缓存

客户端错误类(400-499)

400 Bad Request  客户端请求与语法错误,不能被服务器所理解

401 Unauthroized 请求未认证

403 Forbidden    服务器收到请求,但是拒绝提供服务

服务器错误类(500-599)

500  服务器内部错误 
502 Bad Gateway(网关故障)   代理使用的服务器遇到了上游的无效响应
503  服务器当前不能处理客户端的请求,一段时间后可能恢复正常 
  • HTTP响应头
响应头和响应体之间也有个空行

Cache头域

Expires  --浏览器会在指定过期时间内使用本地缓存

Entity头域
ETag --配合客户端if-None-Match使用

Last-Modified  --配合客户端if-Modified-Since使用

Content-Encoding   --服务器使用了什么压缩方法



Web服务器通过2种方式来判断浏览器缓存是否是最新的。
第一种, 浏览器把缓存文件的最后修改时间通过 header ”If-Modified-Since“来告诉Web服务器。
第二种, 浏览器把缓存文件的ETag, 通过header "If-None-Match", 来告诉Web服务器。

ETag是Web服务端产生的,然后发给浏览器客户端。浏览器客户端是不用关心Etag是如何产生的。
为什么使用ETag呢? 主要是为了解决Last-Modified 无法解决的一些问  题。
1. 某些服务器不能精确得到文件的最后修改时间, 这样就无法通过最后修改时间来判断文件是否更新了。
2. 某些文件的修改非常频繁,在秒以下的时间内进行修改. Last-Modified只能精确到秒。
3. 一些文件的最后修改时间改变了,但是内容并未改变。 我们不希望客户端认为这个文件修改了。

cookie 和 session

  • cookie 不可跨域名

  • 服务器向客户端浏览器发送一个名为JSESSIONID的Cookie,它的值为该Session的id(也就是HttpSession.getId()的返回值)。Session依据该Cookie来识别是否为同一用户。

  • URL地址重写是对客户端不支持Cookie的解决方案。URL地址重写的原理是将该用户Session的id信息重写到URL地址中。服务器能够解析重写后的URL获取Session的id。这样即使客户端不支持Cookie,也可以使用Session来记录用户状态

你可能感兴趣的:(TCP)