套接字
套接字是一个同一台主机内应用层和网络层之间的接口。由于套接字是在网络上建立网络应用程序的可编程接口,所以也把套接字称为应用程序和网络之间的应用编程接口。
一个UDP套接字是由目的IP地址和目的端口号标识的二元组。两个UDP报文段,只要目的IP地址和目的端口号一样,不论源IP地址和端口号是否一样,都被定向到相同的目的进程。
一个TCP套接字是由源IP地址,源端口号,目的IP地址,目的端口号构成的四元组。所有的这四元组都被用来进行多路分解。
常见应用层协议
DNS
FTP
HTTP
SMTP
HTTP
HTTP请求报文段
HTTP包含一行请求行和多行首部行。
请求行有三个字段:方法字段,URL字段,HTTP协议版本字段。
方法字段有GET,POST,HEAD,PUT和DELETE。
- Host,目标主机。
- Connection,浏览器告诉服务器不希望使用持久连接。
- User-agent,浏览器。
- Accept-language
HTTP响应报文段
一个状态行和6个首部行,然后是报文实体。
状态行:
协议版本,状态码和相应状态信息。
6个首部行:
- Connection,不适用持久链接。
- Date,服务器产生发送报文的时间。
- Server,服务器类型。
- Last-Modified,对象创建或者修改的最后日期。
- Content-Length,发送内容的长度。
- Content Type,发送内容的类型。
HTTP状态码[3,4, 5]
1xx信息
2xx成功
200 OK 请求成功
201 Created 当服务器按照客户端的的请求创建了一个新的资源时,发送此响应代码。
204 No Content。服务端拒绝对PUT,POST或者DELETE请求返回任何状态信息。返回空文件替换缓存。而304是使用上次的缓存。
3xx 重定向,客户端需要做一些额外的工作才能得到所需要的资源,他们通过用于GET请求。
301 Moved Permanently 服务器知道客户端请求的资源,但是不喜欢客户端使用当前URL。
302 Found。临时性重定向。不是永久性移动,而是临时性移动。比如说用户把uri保存为书签,出现301时,书签会被更新,出现302时不会。。
303 See Other。请求已经被处理,但是服务器返回的不是文档,是一个URI。和302功能一样,但是303明确表示客户端应该使用GET方法获取资源。
304 Not modified。客户端有数据主题,不需要重复发送。
307 Temporary Redict。临时性重定向,和302有着相同的意思。但是不会将POST修改成GET。
301,302,303响应状态码返回时,几乎所有的浏览器都会把POST改成GET,删除请求体,再次发送请求。尽管301,302是禁止将POST改成GET的,但是大家都会这么做。
4xx表示客户端错误
400 Bad Request,服务器收到了请求,但是不知道什么意思。
401 请求要求用户的身份认证,而客户端认证失败。
403 客户端的请求正确,但是服务端拒绝此请求,暗示了请求的资源确实存在。
404 Not Found,服务器无法把客户端请求的URI转换为一个资源。
405 客户端中请求的方法被禁止
5xx表示服务器错误
500 Internal Server Error对于大多数web框架,如果在执行请求处理代码时遇到了异常,就发送此代码。
502 bad gateway
503 Service Unavaiable,服务器当前不能处理处理客户端的请求,可能一会就好了。
505 HTTP Version Not Support
GET和POST区别
- GET是安全的,POST是不安全的。
- GET是幂等的,POST是不幂等的。
- GET是可缓存的,POST通常是不可缓存的。
GET一般是请求服务器的指定资源,是安全,幂等,可缓存的。而post一般是根据请求的payload对指定的资源机械能给你处理,POST是不安全的,不幂等的,不可缓存的。
其他:
- GET会把请求的数据会放在URL后面,而POST把请求的数据放在body中。注意,GET的body也可以存放request body,这是针对于接口来说的。
- GET请求提交的url数据最多是1024字节是浏览器或者服务器限制的,而post则没有限制。
- GET和POST都不安全,HTTP本身是明文协议,无论是url,header还是body,都是在网络中明文传播的。只不过url中的数据是可以在浏览器中直接看到的,而header和body中的数据更麻烦一些,需要使用抓包软件查看。
- 但是GET的效率要比post高。
HTTPS和HTTP[2]
HTTP协议是明文协议,TCP和UDP也没有加密。于是就有了SSL,利用非对称密码体系对发送的数据进行加密。
HTTPS是在TCP连接之后由客户端发起的。其实使用到了对称加密技术和非对称加密技术。
- 客户端发送一个Client Hello给服务器,包含一个随机数,以及客户端支持的加密条件和SSL版本。
- 服务端回应一个Server Hello给客户端,服务器选定一组加密套件,然后和第二个随机数,以及服务器的证书(包含服务器的公钥和名字)一块发送给客户端。服务器是由CA机构发送到,一个大家都信任的机构。
- 客户端验证服务端的证书的真实性。(使用CA的数字证书,服务端的证书含有CA对服务器信息的签名,然后客户端使用CA证书中的公钥对服务端的数字证书进行验证签名,验证签名即使用相同的摘要算法对服务器的信息进行摘要,然后和CA证书的签名对比。)
验证成功之后,生成第三个随机数,使用服务端的公钥对这个随机数加密生成PreMaster Key,然后发送给服务端。 - 服务端用自己的私钥解密生成PreMaster Key。这个时候,两边都拥有三个随机数,使用相同的算法生成一个秘钥。之后的通信都使用这个秘钥进行。
输入www.baidu.com发生的一切
- 用户输入网址。
- DNS解析。一般情况下,本机是会知道DNS服务器的IP地址的。递归查询和迭代查询获得目的主机的IP地址。一般是在同一个局域网内,通过ARP请求,查询对应的DNS服务器的MAC地址,然后把请求包发给它。[8]
- TCP连接。三次握手。
- 发送请求。
- 接收HTTP相应报文
- 浏览器渲染。
Cookie
Cookie用户和服务器的交互。因为HTTP是无状态的,简化了服务器的设计。当想要识别用户的时候,可能限制用户的访问或者想把用户和内容关联起来。HTTP使用了cookie:
cookie有四个部分:
- HTTP响应报文中有一个cookie首部行。
- HTTP请求报文中有一个cookie首部行。
- 用户端系统有保留一个cookie文件。
- Web站点后台有一个cookie数据库。
Web缓存
Web缓存器也叫代理服务器,它有自己的磁盘存储空间,并在自己的磁盘存储空间中保存最近请求过的对象拷贝。
然后可以配置浏览器,将用户的所有HTTP请求首先指向Web缓存器,一旦配置了浏览器,每个浏览器对象的请求首先被定向到Web缓存器。
- 浏览器建立一个到Web缓存器的TCP连接,并发送一个HTTP请求。
- Web缓存器检查缓存是命中。
- 命中的话,Web缓存器向发送一个条件GET,查询Last-modified。
- 没有命中的话,Web缓存器请求该对象,并将其缓存。
- Web缓存器向客户机浏览器发送报文。
TCP和UDP的选择
DNS通常采用UDP,因为TCP需要建立连接,会引入建立TCP连接的时延,这样子会慢得多。如果没有收到响应,就会向另一台DNS服务器发送查询,或者通知调用的程序它不能获得响应。[9]
而HTTP使用TCP而不是UDP,因为web网页需要的是可靠性。
UDP
UDP相对于TCP的优势:
- 应用层能更好的控制要发送的数据和发送时间。
- 无需连接建立。
- 无连接状态。
- 分组首部开销小。TCP报文段有20字节的首部开销,而UDP只有8字节的开销。
UDP报文段结构
UDP报文段的首部共8个字节,64位,每个字段8位,共4个字段,:
- 16位源端口号
- 16位目的端口号
- 16位长度字段,长度字段包含了首部在内的UDP报文段的长度(以字节为单位)。
- 16位检验和
UDP校验和
- UDP校验和提供了差错检测功能,但是不能进行差错恢复。为什么UDP校验和work?
- 为什么要进行差错校验?链路中可能出错,内存中也可能出错。UDP必须在端到端基础上在运输层提供差错校验。
- 出错后如何处理。一些实现是丢弃受损的报文段,一些是将受损的报文段交给应用程序并告警。
可靠数据传输原理
停止等待协议
为了解决分组可能出错的情况,引入自动重传请求。自动重传请求协议需要另外三种协议:差错检验,接收方反馈和重传。
当一个分组到达时可能出错,接收方进行进行差错校验,如果出错,发送一个NAK给发送方。如果没有失败,发送一个ACK给接收方。
直到发送方确定接收方已经收到当前分组之后(收到一个ACK),才会继续发送新数据,这就是停止等待协议。如果收到一个NAK,就会重传当前分组。(接收方反馈)
但是ACK和NAK也可能出错或者丢失,通过引入重传解决这个问题。
到底什么时候重传呢?等待一个RTT太久了,可以使用一个定时器设置一个时间,超过这个时间就重传。
这样子在接收方引入了冗余分组的问题。冗余分组的问题在于不知道接收方发送的ACK或者NAK是否被发送方接收,或者是分组没有丢失,等到了一段时间又到了。接收方不知道接收到的分组到底是哪一个,是重发的分组还是新的分组。可以通过引入分组序号解决这个问题。在停止等待协议中,一个比特的分组序号就够了。所以也叫比特交替协议。
流水线可靠数据传输协议
停止等待协议的效率太低了。流水线可靠数据传输协议不是一次只发一个分组,而是一次发送多个分组,就好像一条流水线一样。这就产生了几个问题:
- 必须增加序号范围,原来只要一个比特就够了,现在需要多个。
- 协议的发送方和接收方也必须能够缓存多个分组。
- 流水线中如果分组丢失了,有两种方式进行差错恢复,回退N步(GBN)和选择重传(SR)。
回退N步
GBN的发送方要处理是三个工作,准备N个分组,处理接收方返回的ACK,以及超时重传。
GBN的接收方要处理的工作,只有接收到的分组的序号和上一次相同,会返回给发送方一个ACK,GBN采用累计确认(对序号n的分组的确认表明接收方已经正确接收到n以及n之前的分组了)。所有其他情况,都会丢弃分组。比如失序分组,接收方应该接收序号为n的分组,但是收到了序号为n+1的分组,就会丢弃,而不是缓存。
GBN维护一个大小为N的窗口。对于发送方,维护一个大小为N的窗口,如果这N个分组的ACK都没有收到,就不会发送新的数据,等待接收方返回ACK。发送方还有超时设置,(发送方发送的分组丢了,或者接收方返回的ACK丢了),都会重传。
选择重传
GBN有时候会效率太低,因为一个分组丢失,可能导致重传整个N个分组。选择重传可以用来解决这种问题。
TCP
TCP累计确认和GBN,选择重传之间的关系
GBN是滑动窗口协议,虽然也提供累计确认,但是它不会缓存失序报文,会把它们全部丢弃。假设序号为n的报文段丢失了,然后需要发送方重传n之后的所有报文。而TCP的发送方至多只会重传一个报文段,如果TCP接收方接收到了
选择重传对失序报文进行缓存,但是没有提供累计确认。
可靠数据传输
TCP发送方有三个与发送和重传有关的主要事件:
- 数据处理。TCP从发送缓存重拿数据,加上TCP首部,传递给IP层。然后传递给网络,TCP接收方的接收缓存获取数据。
- 超时。
通过重传引发超时的报文响应超时时间。如果多次超时的话,就倍增超时时间间隔。
冗余ACK触发快速重传(为什么发送方收到三个冗余ACK就立即快重传)。冗余ACK是对按序接收到的最后一个字节数据进行重复确认。 - ACK处理。如果收到的ACK是窗口的最小未确认序号,那么修改窗口的最小未确认序号。
三次握手
- A向B发送一个SYN报文段,并且包含自己的初始序列号。
- B向A发送一个SYNACK报文段,并且包含自己的初始序列号。同时分配连接缓存,变量等。
- A向B发送一个ACK报文段,不是SYN报文段。
为什么要随机初始化一个报文段序号
减少上次TCP连接中的报文段被当做两台主机之间新的TCP连接中的报文段。
为什么是三次握手而不是两次或者四次
其实是四次挥手,只不过第二次和第三次可以合并起来了。三次挥手的目的是确立TCP双方都能获得对方的初始序号。
为什么不是两次?如果A向B发送一个请求,B回应一个请求。而B的回应丢了,A就无法和B进行通信。如果设计成A重传,那么可能会建立很多个连接。如果设计成B重传,为什么要B重传?不是两次握手吗?他怎么知道要重传。这些都是如果设计成两次握手需要考虑的问题。
对于三次握手来说,如果
- A发给B的丢了,A超时重传。
- B发给A的丢了,B超时重传。B分配缓存,变量等。
- A又发给B的丢了,这时候B已经认为建立了连接。
如果双方都没有数据,那么会触发第二步的超时重传。
如果A要发送数据,那么A会直接把数据发给B,就肯定建立连接了。
如果B要发送数据,也会触发第二步的超时重传。
四次挥手
- A发给B FIN报文段。A执行主动关闭。
- B发给A ACK。B进行WAIT-TIME。等待B终止连接,这个时候B可以给A发送数据,但是A不能给B发送数据。B执行被动关闭,B处于CLOSE_WAIT状态。
- B发给A FIN报文段。A收到报文段之后处于TIME_WAIT状态。
- A发给B ACK。这个时候A要等待30s或者1分钟,两分钟。因为需要确认B那边收到了ACK,否则的话,B就无法关闭。
流量控制
TCP通过让发送方维护一个16位的接收窗口(是接收方的)的变量来提供流量控制。不正式的说,接收窗口用于告诉发送方,接收方还有多少可用的缓存空间。TCP是全双工的,两端都维护一个接收窗口。
接收方将自己的缓冲区大小填入TCP首部的窗口长度字段。这个字段是多少:缓冲区的大小 - (缓冲区中的最后一个字节编号 - 从缓冲区中读出的最后一个字节)。
如果接收方窗口大小为0怎么办?这时发送方不给接收方发报文,而接收方也不发,只有在有数据或者ACK要发的时候,接收方才会给发送方发报文。随着接收方应用程序从缓冲区取走数据,发送方也不能继续发数据。这个时候怎么办?规定:当接收方的接收窗口大小为0时,发送方会不断发送含有一个数据字节的报文段。
为什么要有流量控制,为了防止快速的发送设备发出的数据过多,导致慢速的接收设备处理不过来,而发生大量数据的丢失。
拥塞控制
分组重传是网络拥塞的征兆,却不能解决网络拥塞问题。
什么时候知道出现了拥塞:
- 超时
- 收到3个冗余ACK。
为什么要有拥塞控制:
慢启动。
快恢复。收到三个ACK以后的方式叫做快恢复。
快重传。
开始时,指数方式增加,收到超时ACK时开始线性增乘性减。
但是如果发生超时,执行慢开始,即将拥塞窗口变为1MSS,然后指数速度增加,直到遇到超时事件的一半窗口值,开始线性增加。通过设置一个阈值来实现。
TIMEWAIT过多[6]
修改内核设置:
- 开启内核中TCP重用。
- 开启内核中TCP中快速回收。
- 修改TIMEOUT
CLOST_WAIT太多[7]
比如说一个爬虫服务器,爬取其他服务器上的内容,如果没有相应的内容,对方会断开连接,这时候爬虫服务器上的程序是被动断开,如果没有执行close引发第三次挥手,就会有很多CLOSE_WAIT。
long fat network
高带宽和长时延网络情况,被称为长肥网络。带宽和时延的乘积表示网络通道的容量,也就是能够在网络中缓冲的数据量,显然增加带宽和时延都增加在网络中缓冲的数据量。但是随着它们乘积的不断变大,TCP的局限就开始显露出来。常规的窗口大小是16位的,能接收和发送的最大大小为65535,而BDP远大于这个值。TCP就不得不发送一会数据就等待ACK,极端情况下有点像停止等待协议。
缺点
- 窗口小,序号少,无法充分利用带宽。窗口扩展项。
- 时延长。快重传。
- 序号用的很快。PAWS算法。
- RTT比较难测量。引入时间戳。
TCP和UDP的区别
- TCP面向连接,UDP无连接。
- TCP提供可靠数据传输,UDP提供不可靠数据传输。
- TCP的逻辑通信信道是全双工的可靠信道,而UDP是不可靠信道。
- TCP面向字节流,把数据看成一个无结构但是有序的字节流。UDP面向报文段。
- TCP有流量控制,拥塞控制,UDP无。
- TCP很慢,而UDP很快。
- TCP首部20个字节,UDP是8个字节。
Dos攻击
Dos(拒绝服务)攻击是一种宽泛类型的攻击,可以分为三类:
- 弱点攻击
- 带宽洪泛。攻击者向目的主机发送大量的分组,导致目标的介入链路变得非常拥塞,使得合法的分组无法到达服务器。
- 连接洪泛。创建大量的全开或者半开TCP连接。
DDos攻击,分布式拒绝服务攻击。
SYN洪泛攻击
攻击者发送大量的SYN报文段,而不完成TCP握手的第三步,服务器不断地为这些半开连接服务器分配资源,导致服务器资源被迅速消耗。
怎么预防?SYN cookies,当服务器收到一个TCP连接时,不生成一个TCP半开连接,只生成一个初始序列号(精心计算的序列号,被称为cookie),然后发送这种序列号的SYNACK报文段。
如果客户机是合法的,客户机返回一个ACK,服务器收到ACK。然后利用这个ACK计算一个,这个ACK是否对应客户机发送的SYN报文段,如果是,生成一个全开的连接。
DNS攻击
DDos带宽洪泛攻击。攻击者向多个DNS根服务器发送大量的分组,使得大多数合法的DNS请求得不到回答。比如发送大量的ICMP报文。
怎么预防?分组过滤器,过滤ICMP报文。还有就是本地DNS服务器缓存了顶级域名服务器的地址。使得请求绕过了DNS根服务器。
传输层协议
TCP协议。
UDP协议。
运输层协议是在端系统而不是网络路由器中实现的。
端口号。
socket?
网络层协议
IP协议,IP协议为主机之间提供了逻辑通信,它的服务模型是尽力而为交互服务。
ICMP协议。互联网控制消息协议。最典型的应用是差错报告。ICMP报文有一个类型字段和一个编码字段,并且包含由该ICMP报文首次生成的IP数据报的首部和前8字节内容,以便于发送方能够确定引发该差错的数据报。
ping程序发送一个ICMP类型为8编码为0的报文到指定主机(表示回显请求),看到该回显请求的目的主机发送一个类型0编码为0的报文回显回答。
traceroute原理。traceroute利用ICMP报文实现,源主机中的该程序向目的主机发送一系列普通的IP数据报,每一个数据报都携带了一个具有不可达UDP端口号的UDP报文段,第i个报文段的TTL(time to live,确保数据报不会永远在网络中循环,每过一个路由器,字段值减一)是i。同时,源主机为每个数据报启动定时器,当第i个数据报到达第i个路由器时,TTL为0。根据IP协议的规则,路由器会向源主机发送一个ICMP告警报文(类型为11,编码为0)。该告警报文含有路由器的名字和IP地址,该ICMP报文到达源主机时,源主机从定时器得到RTT,从ICMP报文得到路由器名字和IP地址。那么什么时候停止发送数据报?当其中一个报文到达目的主机的时候,由于数据报包含了一个不可达的端口,所以目的主机会发送类型为3,编码为3的目的端口不可达的ICMP报文。
IGMP协议。网际组管理协议。用于多播。
ARP协议,地址解析协议。是算在链路层还是网络层?把IPv4地址转换成硬件地址。
RARP协议,反向地址解析协议。把硬件地址映射成IPv4地址。
路由器属于网络层设备,它只检查网络层字段。
IP地址。
MTU(最大传输单元),以太网的MTU是1500字节。IPV4要求最小MTU是68字节(20字节首部长度和40字节选项,以及8字节的偏移)。IPV6要求的最小MTU是1280字节。两个主机路径上的最小MTU称为路径MTU。路径MTU可以不对称。
当IP数据报的大小超过链路MTU时,执行分片。
最小重组缓冲区是IPV4(6)的任何实现都必须保证支持的最小数据报大小,IPV4是576字节,IPV6是1500字节。超过这个大小,就不一定能被接收方识别。所以,使用UDP的网络应用的报文段一般都不超过这个大小。
MSS(最大报文段)是用来通过对方,自己这面能够接收的最大TCP报文段大小,也就是最小重组缓冲区的实际值。MSS的大小通常设置为MTU减去IP和TCP首部的长度。
如果
数据链路层
成帧,透明传输,差错检测。
MAC地址。
交换机,网桥。
MAC地址。
物理层
集线器,中继器。
TCP“粘包”问题
粘包问题实际上不是TCP的,它是开发者在设计应用数据传输时的数据结构没有设计好好,可能两个不同的应用层数据在同一个TCP报文段中发给了接收方。
怎么解决,需要在传输层的数据流中给出边界,然后对传输层的数据流进行解析得到相应的数据。不应该依赖于socket的缓冲区作为数据报的边界。
参考文献
1.《计算机网络自顶向下》
2.https://segmentfault.com/a/1190000016855991
3.https://www.cnblogs.com/xflonga/p/9368993.html
4.https://www.cnblogs.com/aliwa/p/8495014.html
5.https://blog.csdn.net/qq_39816673/article/details/89611936
6.https://www.cnblogs.com/dadonggg/p/8778318.html
7.http://www.httpclient.cn/archives/106.html
8.https://www.cnblogs.com/lolau/p/8137541.html
9.为什么DNS使用UDP而不是TCP? - 车小胖的回答 - 知乎
https://www.zhihu.com/question/310145373/answer/583869215