结构
网络结构体系
| 层次 | 面向对象 | 作用 |
|---|---|---|
| 应用层 | 提供访问网络服务的接口 | 为操作系统或网络应用程序提供访问网络服务的接口 |
| 传输层 | 端到端进程到进程的层次。 | 传输层负责将上层数据分段并提供端到端的、可靠的或不可靠的传输以及端到端的差错控制和流量控制问题 |
| 网络层 | 路由选择和存储转发 | 网络层负责对子网间的数据包进行路由选择。此外,网络层还可以实现拥塞控制、网际互连等功能 |
| 数据链路层 | 可以分为逻辑链路控制子层LLC和媒体访问控制子层MAC | 数据链路层为网络层提供可靠的数据传输 |
应用层
常见协议及端口号
| 协议 | 端口号 | 传输层协议 | 注释 |
|---|---|---|---|
| ftp | 21 | TCP | 文件传输协议 |
| telnet | 23 | TCP | Internet远程登陆服务 |
| smtp | 25 | TCP | Simple Mail Transfer Protocol,简单邮件传输协议 |
| DNS | 39 | UDP | Domain Name System,域名系统 |
| HTTP | 80 | TCP | 超文本传输协议(HTTP,HyperText Transfer Protocol) |
| POP3 | 110 | TCP | Post Office Protocol - Version 3, 邮局协议版本3 |
| https | 443 | TCP | Hyper Text Transfer Protocol over Secure Socket Layer, HTTP的安全版 |
| Snmp | 161 | UDP | 简单网络管理协议 |
| DHCP | 67 | UDP | Dynamic Host Configuration Protocol,动态主机配置协议,自动分配IP地址 |
| IMAP | 143 | TCP | 交互式邮件存取协议 |
https和http
http
HTTP协议的主要特点可概括如下:
1.支持客户/服务器模式。
2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
3.灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
4.无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
5.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
http报文格式
HTTP请求由三部分组成,分别是:请求行、消息报头、请求正文
请求行以一个方法符号开头,以空格分开,后面跟着请求的URI和协议的版本,格式如下:Method Request-URI HTTP-Version CRLF
HTTP响应也是由三个部分组成,分别是:状态行、消息报头、响应正文
状态行格式如下:HTTP-Version Status-Code Reason-Phrase CRLF
常见状态代码、状态描述、说明:
200 OK //客户端请求成功
206 Partial Content //客户发送了一个带有Range头的GET请求,服务器完成了它。通常使用在MIME机制上,其为多个部分的对象集合,来容纳多个不同类型的数据
301(永久移动) //请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。 您应使用此代码告诉 Googlebot 某个网页或网站已永久移动到新位置。
302(暂时移动) //服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。 此代码与响应 GET 或 HEAD 请求的 301 代码类似,会自动将请求者转到不同的位置,但您不应使用此代码来告诉 Googlebot 某个网页或网站已经移动,因为 Googlebot 会继续抓取原有位置并编入索引。
304 Not Modified 如果客户端发送了一个带条件的GET请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个状态码。304响应禁止包含消息体,因此始终以消息头后的第一个空行结尾。
该响应必须包含以下的头信息:
Date,除非这个服务器没有时钟。假如没有时钟的服务器也遵守这些规则,那么代理服务器以及客户端可以自行将Date字段添加到接收到的响应头中去(正如RFC 2068中规定的一样),缓存机制将会正常工作。
ETag和/或Content-Location,假如同样的请求本应返回200响应。
Expires, Cache-Control,和/或Vary,假如其值可能与之前相同变量的其他响应对应的值不同的话。
假如本响应请求使用了强缓存验证,那么本次响应不应该包含其他实体头;否则(例如,某个带条件的GET请求使用了弱缓存验证),本次响应禁止包含其他实体头;这避免了缓存了的实体内容和更新了的实体头信息之间的不一致。
假如某个304响应指明了当前某个实体没有缓存,那么缓存系统必须忽视这个响应,并且重复发送不包含限制条件的请求。
假如接收到一个要求更新某个缓存条目的304响应,那么缓存系统必须更新整个条目以反映所有在响应中被更新的字段的值。
400 Bad Request //客户端请求有语法错误,不能被服务器所理解
401 Unauthorized //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用
403 Forbidden //服务器收到请求,但是拒绝提供服务
404 Not Found //请求资源不存在,eg:输入了错误的URL
500 Internal Server Error //服务器发生不可预期的错误
502 Bad Gateway //作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。
503 Server Unavailable //服务器当前不能处理客户端的请求,一段时间后,可能恢复正常
主要的请求报头主要字段:
301与302区别
区别
1 定义
301:永久重定向,表示请求的资源已被分配新的URI,以后请求资源应使用现在所指的URI。
302:临时性重定向,表示请求的资源已被分配了新的URI,希望用户(本次)能使用新的URI访问。换句话说,已移动的资源对应的URI将来还有可能发生改变。
2 对于搜索引擎
| 301 | 302 |
|---|---|
| 搜索引擎在抓取新内容的同时也将旧的网址替换为重定向之后的新网址 | 搜索引擎会抓取新的内容而保留旧的网址 |
| 搜索引擎会把旧地址的PageRank带到新网址 | 旧地址的PageRank不会带到新网址 |
| 同时在搜索结果中会用新的网址替换旧网址 | 在搜索结果中不会去除旧的网址 |
3 浏览器缓存
301:浏览器会缓存重定向后的结果,再次访问时,会直接访问新地址。但不同的浏览器会有不同的缓存方式,Chrome 和 Firefox会一直缓存301跳转,除非手动删除或者为腾出空间被清除,但Safari和Opera在浏览器重启时就会清除301缓存。
由于301缓存问题,所以在使用301跳转时,一定要保证旧的网址不会再被访问了。举个真实例子,商品中心那边商品会上下架,当被下架时会跳转到错误页面,但当时这个跳转使用的是301跳转,所以当这个商品重新上架取消跳转时,由于浏览器缓存,会直接访问之前跳转后的地址,从而导致一直访问的是错误页面。
302:浏览器不会缓存重定向的结果
4 使用选择
301:如果你的网站不是暂时搬移,且关心网站的seo,那么建议使用301来跳转。例如:
为了重塑网站品牌(如www.xiaomi.com更换成www.mi.com,www.360buy.com更换成www.jd.com)决定将网站移动到一个新的域名
302:如果你只是暂时跳转到新网址,旧网址以后可能还会被使用,那么建议使用302跳转。例如:
网站维护,跳转至一个通知页面
商品脱销,跳转到一个特定页面(如同类商品的推荐页面),但有库存后会返回该商品页面。
get与post区别
幂等性:
对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
GET在浏览器回退时是无害的,而POST会再次提交请求。
其他:
POST所对应的URI并非创建的资源本身,而是资源的接收者。
比如:POST http://www.forum.com/articles的语义是在http://www.forum.com/articles下创建一篇帖子,HTTP响应中应包含帖子的创建状态以及帖子的URI。
两次相同的POST请求会在服务器端创建两份资源,它们具有不同的URI;所以,POST方法不具备幂等性。
而PUT所对应的URI是要创建或更新的资源本身。
比如:PUT http://www.forum/articles/4231的语义是创建或更新ID为4231的帖子。对同一URI进行多次PUT的副作用和一次PUT是相同的;
因此,PUT方法具有幂等性。
http://coolshell.cn/articles/4787.html
缓存:
GET请求会被浏览器主动cache,而POST不会,除非手动设置。
GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
编码:
GET请求只能进行url编码,而POST支持多种编码方式。
对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
长度限制:
GET请求在URL中传送的参数是有长度限制的,而POST没有。
GET参数通过URL传递,POST放在Request body中。
GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
http://www.tuicool.com/articles/Ufmy6j
head与get类似,只是head不返回报文主体,单单返回报文首部
options询问支持的方法,响应时返回服务器支持的方法(post,get,head…)
connect与代理服务器建立隧道进行tcp通信
https
HTTPS 可以认为是 HTTP + TLS。HTTP 协议大家耳熟能详了,目前大部分 WEB 应用和网站都是使用 HTTP 协议传输的。
TLS 是传输层加密协议,它的前身是 SSL 协议,最早由 netscape 公司于 1995 年发布,1999 年经过 IETF 讨论和规范后,改名为 TLS。如果没有特别说明,SSL 和 TLS 说的都是同一个协议。
HTTPS 区别于 HTTP,它多了加密(encryption),认证(verification),鉴定(identification)。它的安全源自非对称加密以及第三方的 CA 认证。
使用 HTTPS 协议主要是为了保护用户隐私,防止流量劫持。
HTTP 本身是明文传输的,没有经过任何安全处理。例如用户在百度搜索了一个关键字,比如“苹果手机”,中间者完全能够查看到这个信息,并且有可能打电话过来骚扰用户。也有一些用户投诉使用百度时,发现首页或者结果页面浮了一个很长很大的广告,这也肯定是中间者往页面插的广告内容。如果劫持技术比较低劣的话,用户甚至无法访问百度。
总体来说,HTTPS 协议提供了三个强大的功能来对抗上述的劫持行为:
1, 内容加密。浏览器到百度服务器的内容都是以加密形式传输,中间者无法直接查看原始内容。
2, 身份认证。保证用户访问的是百度服务,即使被 DNS 劫持到了第三方站点,也会提醒用户没有访问百度服务,有可能被劫持
3, 数据完整性。防止内容被第三方冒充或者篡改。

第一步,客户端给出协议版本号、一个客户端生成的随机数(Client random),以及客户端支持的加密方法。
第二步,服务器确认双方使用的加密方法,并给出数字证书、以及一个服务器生成的随机数(Server random)。
第三步,客户端确认数字证书有效,然后生成一个新的随机数(Premaster secret),并使用数字证书中的公钥,加密这个随机数,发给服务器。
第四步,服务器使用自己的私钥,获取客户端发来的随机数(即Premaster secret)。
第五步,客户端和服务器根据约定的加密方法,使用前面的三个随机数,生成”对话密钥”(session key),用来加密接下来的整个对话过程。
握手阶段有三点需要注意。
(1)生成对话密钥一共需要三个随机数。
(2)握手之后的对话使用”对话密钥”加密(对称加密),服务器的公钥和私钥只用于加密和解密”对话密钥”(非对称加密),无其他作用。
(3)服务器公钥放在服务器的数字证书之中。

HTTPS 的访问过程,相比 HTTP 要复杂很多,在部分场景下,使用 HTTPS 访问有可能增加 7 个 RTT。
HTTPS 首次请求需要的网络耗时解释如下:
1, 三次握手建立 TCP 连接。耗时一个 RTT。
2, 使用 HTTP 发起 GET 请求,服务端返回 302 跳转到 https://www.baidu.com。需要一个 RTT 以及 302 跳转延时。
a) 大部分情况下用户不会手动输入 https://www.baidu.com 来访问 HTTPS,服务端只能返回 302 强制浏览器跳转到 https。
b) 浏览器处理 302 跳转也需要耗时。
3, 三次握手重新建立 TCP 连接。耗时一个 RTT。
a) 302 跳转到 HTTPS 服务器之后,由于端口和服务器不同,需要重新完成三次握手,建立 TCP 连接。
4, TLS 完全握手阶段一。耗时至少一个 RTT。
a) 这个阶段主要是完成加密套件的协商和证书的身份认证。
b) 服务端和浏览器会协商出相同的密钥交换算法、对称加密算法、内容一致性校验算法、证书签名算法、椭圆曲线(非 ECC 算法不需要)等。
c) 浏览器获取到证书后需要校验证书的有效性,比如是否过期,是否撤销。
5, 解析 CA 站点的 DNS。耗时一个 RTT。
a) 浏览器获取到证书后,有可能需要发起 OCSP 或者 CRL 请求,查询证书状态。
b) 浏览器首先获取证书里的 CA 域名。
c) 如果没有命中缓存,浏览器需要解析 CA 域名的 DNS。
6, 三次握手建立 CA 站点的 TCP 连接。耗时一个 RTT。
a) DNS 解析到 IP 后,需要完成三次握手建立 TCP 连接。
7, 发起 OCSP 请求,获取响应。耗时一个 RTT。
8, 完全握手阶段二,耗时一个 RTT 及计算时间。
a) 完全握手阶段二主要是密钥协商。
9, 完全握手结束后,浏览器和服务器之间进行应用层(也就是 HTTP)数据传输。
http://www.ruanyifeng.com/blog/2014/09/illustration-ssl.html
http://op.baidu.com/2015/04/https-s01a02/
加密算法
====对称加密
===========DES、AES
====非对称加密
===========RSA
====散列加密
===========MD5、SHA1、SHA2
http://zoucz.com/blog/2016/12/29/understand-crypto-1/
邮件协议
SMTP
SMTP 的全称是“Simple Mail Transfer Protocol”,即简单邮件传输协议。它是一组用于从源地址到目的地址传输邮件的规范,通过它来控制邮件的中转方式。SMTP 协议属于 TCP/IP 协议簇,它帮助每台计算机在发送或中转信件时找到下一个目的地。SMTP 服务器就是遵循 SMTP 协议的发送邮件服务器。
SMTP 认证,简单地说就是要求必须在提供了账户名和密码之后才可以登录 SMTP 服务器,这就使得那些垃圾邮件的散播者无可乘之机。 增加 SMTP 认证的目的是为了使用户避免受到垃圾邮件的侵扰。
POP3
POP3是Post Office Protocol 3的简称,即邮局协议的第3个版本,它规定怎样将个人计算机连接到Internet的邮件服务器和下载电子邮件的电子协议。它是因特网电子邮件的第一个离线协议标准,POP3允许用户从服务器上把邮件存储到本地主机(即自己的计算机)上,同时删除保存在邮件服务器上的邮件,而POP3服务器则是遵循POP3协议的接收邮件服务器,用来接收电子邮件的。
IMAP
IMAP全称是Internet Mail Access Protocol,即交互式邮件存取协议,它是跟POP3类似邮件访问标准协议之一。不同的是,开启了IMAP后,您在电子邮件客户端收取的邮件仍然保留在服务器上,同时在客户端上的操作都会反馈到服务器上,如:删除邮件,标记已读等,服务器上的邮件也会做相应的动作。所以无论从浏览器登录邮箱或者客户端软件登录邮箱,看到的邮件以及状态都是一致的。
总之,IMAP 整体上为用户带来更为便捷和可靠的体验。POP3 更易丢失邮件或多次下载相同的邮件,但 IMAP 通过邮件客户端与webmail 之间的双向同步功能很好地避免了这些问题。
在浏览器中输入 www.baidu.com 后执行的全部过程
现在假设如果我们在客户端(客户端)浏览器中输入 http://www.baidu.com ,而baidu.com为要访问的服务器(服务器),下面详细分析客户端为了访问服务器而执行的一系列关于协议的操作:
1)客户端浏览器通过DNS解析到www.baidu.com的IP地址220.181.27.48,通过这个IP地址找到客户端到服务器的路径。客户端浏览器发起一个HTTP会话到220.161.27.48,然后通过TCP进行封装数据包,输入到网络层。
2)在客户端的传输层,把HTTP会话请求分成报文段,添加源和目的端口,如服务器使用80端口监听客户端的请求,客户端由系统随机选择一个端口如5000,与服务器进行交换,服务器把相应的请求返回给客户端的5000端口。然后使用IP层的IP地址查找目的端。
3)客户端的网络层不用关系应用层或者传输层的东西,主要做的是通过查找路由表确定如何到达服务器,期间可能经过多个路由器,这些都是由路由器来完成的工作,不作过多的描述,无非就是通过查找路由表决定通过那个路径到达服务器。
4)客户端的链路层,包通过链路层发送到路由器,通过邻居协议查找给定IP地址的MAC地址,然后发送ARP请求查找目的地址,如果得到回应后就可以使用ARP的请求应答交换的IP数据包现在就可以传输了,然后发送IP数据包到达服务器的地址。
https://www.nowcoder.com/discuss/3853?pos=264&type=1&order=0
http://fex.baidu.com/blog/2014/05/what-happen/
http://www.jianshu.com/p/c1dfc6caa520
DNS解析过程
1、浏览器会检查缓存中有没有这个域名对应的解析过的IP地址,如果缓存中有,这个解析过程就结束。浏览器缓存域名也是有限制的,不仅浏览器缓存大小有限制,而且缓存的时间也有限制,通常情况下为几分钟到几小时不等,域名被缓存的时间限制可以通过TTL属性来设置。这个缓存时间太长和太短都不太好,如果时间太长,一旦域名被解析到的IP有变化,会导致被客户端缓存的域名无法解析到变化后的IP地址,以致该域名不能正常解析,这段时间内有一部分用户无法访问网站。如果设置时间太短,会导致用户每次访问网站都要重新解析一次域名。
2、如果用户浏览器缓存中没有数据,浏览器会查找操作系统缓存中是否有这个域名对应的DNS解析结果。其实操作系统也有一个域名解析的过程,在Windows中可以通过C:\Windows\System32\drivers\etc\hosts文件来设置,在Linux中可以通过/etc/hosts文件来设置,用户可以将任何域名解析到任何能够访问的IP地址。例如,我们在测试时可以将一个域名解析到一台测试服务器上,这样不用修改任何代码就能测试到单独服务器上的代码的业务逻辑是否正确。正是因为有这种本地DNS解析的规程,所以有黑客就可能通过修改用户的域名来把特定的域名解析到他指定的IP地址上,导致这些域名被劫持。
3、前两个过程无法解析时,就要用到我们网络配置中的”DNS服务器地址”了。操作系统会把这个域名发送给这个LDNS,也就是本地区的域名服务器。这个DNS通常都提供给用户本地互联网接入的一个DNS解析服务,例如用户是在学校接入互联网,那么用户的DNS服务器肯定在学校;如果用户是在小区接入互联网,那么用户的DNS就是再提供接入互联网的应用提供商,即电信或联通,也就是通常说的SPA,那么这个DNS通常也会在用户所在城市的某个角落,不会很远。Windows环境下通过命令行输入ipconfig,Linux环境下通过cat /etc/resolv.conf就可以查询配置的DNS服务器了。这个专门的域名解析服务器性能都会很好,它们一般都会缓存域名解析结果,当然缓存时间是受到域名的失效时间控制的。大约80%的域名解析到这里就结束了,所以LDNS主要承担了域名的解析工作。
4、如果LDNS仍然没有命中,就直接到Root Server域名服务器请求解析
5、根域名服务器返回给本地域名服务器一个所查询的主域名服务器(gTLD Server = Generic top-level domains servers)地址。gTLD是国际顶级域名服务器,如.com、.cn、.org等,全球只有13台左右
6、本地域名服务器LDNS再向上一步返回的gTLD服务器发送请求
7、接受请求的gTLD服务器查找并返回此域名对应的Name Server域名服务器的地址,这个Name Server通常就是用户注册的域名服务器,例如用户在某个域名服务提供商申请的域名,那么这个域名解析任务就由这个域名提供商的服务器来完成
8、Name Server域名服务器会查询存储的域名和IP的映射关系表,在正常情况下都根据域名得到目标IP地址,连同一个TTL值返回给DNS Server域名服务器
9、返回该域名对应的IP和TTL值,LDNS会缓存这个域名和IP的对应关系,缓存时间由TTL值控制
10、把解析的结果返回给用户,用户根据TTL值缓存在本地系统缓存中,域名解析过程结束
在实际的DNS解析过程中,可能还不止这10步,如Name Server可能有很多级,或者有一个GTM来负载均衡控制,这都有可能会影响域名解析过程。
http://www.cnblogs.com/xrq730/p/4931418.html
传输层
- TCP的包是没有IP地址的,那是IP层上的事。但是有源端口和目标端口。
- 一个TCP连接需要四个元组来表示是同一个连接(src_ip, src_port, dst_ip, dst_port)准确说是五元组,还有一个是协议。但因为这里只是说TCP协议,所以,这里我只说四元组。
注意上图中的四个非常重要的东西: - Sequence Number是包的序号,用来解决网络包乱序(reordering)问题。
- Acknowledgement Number就是ACK——用于确认收到,用来解决不丢包的问题。
- Window又叫Advertised-Window,也就是著名的滑动窗口(Sliding Window),用于解决流控的。
- TCP Flag ,也就是包的类型,主要是用于操控TCP的状态机的。
由于一个主机可以有多个进程,因此还有复用和分用的功能。
分用是把运输层segment中的信息发送给正确的socket的服务
复用是把所有socket中的数据集中并加头信息封装,然后发送到网络层的服务
注意clint和server端状态的变化
Clinet:SYNC_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT
Server:LISTEN->SYNC_RCVD->ESTABLISHED->CLOSE_WAIT-> LASK_ACK->CLOSED
三次握手建立连接
服务器必须接受外来的连接,这通过socket,bind,listen实现被动打开的过程
然后客户端使用connect实现主动打开,发送SYN J到服务器,然年进入阻塞状态
服务器监听到请求,使用accept接受请求,发送SYN K, ACK J+1,然后进入阻塞
客户端收到后,connect返回,发送ACK K+1进行确认,这时connect返回
至此三次握手完毕,已经建立连接
然后传输数据,并确认回复
四次挥手释放连接
客户端扣个应用调用close进行主动关闭,发送FIN M
服务器收到后执行被动关闭,对这个FIN进行确认ACK M+1。同时作为文件结束符传送给应用程序,表示应用程序再也接收不到额外的数据,因为发了FIN就表示客户端不再发送数据了
一段时间后,应用调用close关闭套接口,同时发送了FIN M
客户端进行确认(主动关闭的一端)
进程终止时所有的tcp都会发出FIN
执行主动关闭的那一端进入到time_wait阶段
必要性
为什么要三次挥手?
防止已失效的请求报文段突然又传送到了服务端而造成连接的误判。
在只有两次“握手”的情形下,假设Client想跟Server建立连接,但是却因为中途连接请求的数据报丢失了,故Client端不得不重新发送一遍;这个时候Server端仅收到一个连接请求,因此可以正常的建立连接。但是,有时候Client端重新发送请求不是因为数据报丢失了,而是有可能数据传输过程因为网络并发量很大在某结点被阻塞了,这种情形下Server端将先后收到2次请求,并持续等待两个Client请求向他发送数据…问题就在这里,Cient端实际上只有一次请求,而Server端却有2个响应,极端的情况可能由于Client端多次重新发送请求数据而导致Server端最后建立了N多个响应在等待,因而造成极大的资源浪费!所以,“三次握手”很有必要!
为什么要四次挥手?
这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的连接请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。
但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可能未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。
为什么要有time_wait阶段?
可靠的实现TCP全双工链接的终止。
这是因为虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到ESTABLISH状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文。允许老的重复的分节在网络中消逝。
TCP中是可靠的服务,当数据包丢失会重传,当有数据包迷路的情况下,如果不等待2MSL时,当客户端以同样地方式重新和服务建立连接后,上一次迷路的数据包这时可能会到达服务,这时会造成旧包被重新读取
http://wetest.qq.com/lab/view/81.html
SYN Flood攻击
关于建连接时SYN超时。
试想一下,如果server端接到了clien发的SYN后回了SYN-ACK后client掉线了,server端没有收到client回来的ACK,那么,这个连接处于一个中间状态,即没成功,也没失败。
于是,server端如果在一定时间内没有收到的TCP会重发SYN-ACK。
在Linux下,默认重试次数为5次,重试的间隔时间从1s开始每次都翻售,5次的重试时间间隔为1s, 2s, 4s, 8s, 16s,总共31s,第5次发出后还要等32s都知道第5次也超时了,所以,总共需要 1s + 2s + 4s+ 8s+ 16s + 32s = 2^6 -1 = 63s,TCP才会把断开这个连接。
关于SYN Flood攻击。
一些恶意的人就为此制造了SYN Flood攻击——给服务器发了一个SYN后,就下线了,于是服务器需要默认等63s才会断开连接,这样,攻击者就可以把服务器的syn连接的队列耗尽,让正常的连接请求不能处理。
于是,Linux下给了一个叫tcp_syncookies的参数来应对这个事——当SYN队列满了后,TCP会通过源地址端口、目标地址端口和时间戳打造出一个特别的Sequence Number发回去(又叫cookie),如果是攻击者则不会有响应,如果是正常连接,则会把这个 SYN Cookie发回来,然后服务端可以通过cookie建连接(即使你不在SYN队列中)。
请注意,请先千万别用tcp_syncookies来处理正常的大负载的连接的情况。
因为,synccookies是妥协版的TCP协议,并不严谨。
对于正常的请求,你应该调整三个TCP参数可供你选择,第一个是:tcp_synack_retries 可以用他来减少重试次数;第二个是:tcp_max_syn_backlog,可以增大SYN连接数;第三个是:tcp_abort_on_overflow 处理不过来干脆就直接拒绝连接了。
http://coolshell.cn/articles/11564.html
TCP重传机制
TCP要保证所有的数据包都可以到达,所以,必需要有重传机制。
注意,接收端给发送端的Ack确认只会确认最后一个连续的包,比如,发送端发了1,2,3,4,5一共五份数据,接收端收到了1,2,于是回ack 3,然后收到了4(注意此时3没收到),此时的TCP会怎么办?
我们要知道,SeqNum和Ack是以字节数为单位,所以ack的时候,不能跳着确认,只能确认最大的连续收到的包,不然,发送端就以为之前的都收到了。
超时重传机制
一种是不回ack,死等3,当发送方发现收不到3的ack超时后,会重传3。一旦接收方收到3后,会ack 回 4——意味着3和4都收到了。
但是,这种方式会有比较严重的问题,那就是因为要死等3,所以会导致4和5即便已经收到了,而发送方也完全不知道发生了什么事,因为没有收到Ack,所以,发送方可能会悲观地认为也丢了,所以有可能也会导致4和5的重传。
对此有两种选择:
一种是仅重传timeout的包。也就是第3份数据。
另一种是重传timeout后所有的数据,也就是第3,4,5这三份数据。
这两种方式有好也有不好。第一种会节省带宽,但是慢,第二种会快一点,但是会浪费带宽,也可能会有无用功。但总体来说都不好。因为都在等timeout,timeout可能会很长(在下篇会说TCP是怎么动态地计算出timeout的)
快速重传机制
于是,TCP引入了一种叫Fast Retransmit 的算法,不以时间驱动,而以数据驱动重传。也就是说,如果,包没有连续到达,就ack最后那个可能被丢了的包,如果发送方连续收到3次相同的ack,就重传。Fast Retransmit的好处是不 用等timeout了再重传。
比如:如果发送方发出了1,2,3,4,5份数据,第一份先到送了,于是就ack回2,结果2因为某些原因没收到,3到达了,于是还是ack回2,后面的4和5都到了,但是还是ack回2,因为2还是没有收到,于是发送端收到了三个ack=2的确认,知道了2还没有到,于是就马上重转2。然后,接收端收到了2,此时因为3,4,5都收到了,于是ack回6。
Fast Retransmit只解决了一个问题,就是timeout的问题,它依然面临一个艰难的选择,就是,是重传之前的一个还是重传所有的问题。对于上面的示例来说,是重传#2呢还是重传#2,#3,#4,#5呢?因为发送端并不清楚这连续的3个ack(2)是谁传回来的?也许发送端发了20份数据,是#6,#10,#20传来的呢。这样,发送端很有可能要重传从2到20的这堆数据(这就是某些TCP的实际的实现)。可见,这是一把双刃剑。
TCP的RTT算法
从前面的TCP重传机制我们知道Timeout的设置对于重传非常重要。
设长了,重发就慢,丢了老半天才重发,没有效率,性能差;
设短了,会导致可能并没有丢就重发。于是重发的就快,会增加网络拥塞,导致更多的超时,更多的超时导致更多的重发。
而且,这个超时时间在不同的网络的情况下,根本没有办法设置一个死的值。只能动态地设置。
为了动态地设置,TCP引入了RTT——Round Trip Time,也就是一个数据包从发出去到回来的时间。
这样发送端就大约知道需要多少的时间,从而可以方便地设置Timeout——RTO(Retransmission TimeOut),以让我们的重传机制更高效。
http://coolshell.cn/articles/11609.html
流量控制
TCP必需要解决:可靠传输以及包乱序(reordering)的问题
对于流量控制,有两个方面可以优化:一是TCP利用滑动窗口实现流量控制的机制;二是如何考虑流量控制中的传输效率。
滑动窗口
TCP必需要解决的可靠传输以及包乱序(reordering)的问题,所以,TCP必需要知道网络实际的数据处理带宽或是数据处理速度,这样才不会引起网络拥塞,导致丢包。
所以,TCP引入了一些技术和设计来做网络流控,Sliding Window是其中一个技术。
TCP头里有一个字段叫Window,又叫Advertised-Window,这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。
于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。
滑动窗口协议是传输层进行流控的一种措施,接收方通过通告发送方自己的窗口大小,从而控制发送方的发送速度,从而达到防止发送方发送速度过快而导致自己被淹没的目的。
接收端在给发送端回ACK中会汇报自己的AdvertisedWindow = MaxRcvBuffer – LastByteRcvd – 1;
而发送方会根据这个窗口来控制发送数据的大小,以保证接收方可以处理。
上图中分成了四个部分,分别是:(其中那个黑模型就是滑动窗口)
- 已收到ack确认的数据。
- 发还没收到ack的。
- 在窗口中还没有发出的(接收方还有空间)
- 窗口以外的数据(接收方没空间)
下面是个滑动后的示意图(收到36的ack,并发出了46-51的字节):
滑动窗口
Silly Window Syndrome
Silly Window Syndrome翻译成中文就是“糊涂窗口综合症”。正如你上面看到的一样,如果我们的接收方太忙了,来不及取走Receive Windows里的数据,那么,就会导致发送方越来越小。到最后,如果接收方腾出几个字节并告诉发送方现在有几个字节的window,而我们的发送方会义无反顾地发送这几个字节。
要知道,我们的TCP+IP头有40个字节,为了几个字节,要达上这么大的开销,这太不经济了。
如果你的网络包可以塞满MTU,那么你可以用满整个带宽,如果不能,那么你就会浪费带宽。(大于MTU的包有两种结局,一种是直接被丢了,另一种是会被重新分块打包发送) 你可以想像成一个MTU就相当于一个飞机的最多可以装的人,如果这飞机里满载的话,带宽最高,如果一个飞机只运一个人的话,无疑成本增加了,也而相当二。
所以,Silly Windows Syndrome这个现像就像是你本来可以坐200人的飞机里只做了一两个人。 要解决这个问题也不难,就是避免对小的window size做出响应,直到有足够大的window size再响应,这个思路可以同时实现在sender和receiver两端。
拥塞控制Congestion Handling
拥塞控制主要是四个算法:A. 慢启动,B. 拥塞避免,C. 拥塞发生,D. 快速恢复。
慢热启动算法 – Slow Start
A. 慢启动的算法如下(cwnd全称Congestion Window):
1)连接建好的开始先初始化cwnd = 1,表明可以传一个MSS大小的数据。
2)每当收到一个ACK,cwnd++; 呈线性上升
3)每当过了一个RTT,cwnd = cwnd*2; 呈指数让升
4)还有一个ssthresh(slow start threshold),是一个上限,当cwnd >= ssthresh时,就会进入“拥塞避免算法”(后面会说这个算法)
B. 拥塞避免算法 – Congestion Avoidance
前面说过,还有一个ssthresh(slow start threshold),是一个上限,当cwnd >= ssthresh时,就会进入“拥塞避免算法”。一般来说ssthresh的值是65535,单位是字节,当cwnd达到这个值时后,算法如下:
1)收到一个ACK时,cwnd = cwnd + 1/cwnd
2)当每过一个RTT时,cwnd = cwnd + 1
这样就可以避免增长过快导致网络拥塞,慢慢的增加调整到网络的最佳值。很明显,是一个线性上升的算法。
C. 拥塞状态时的算法
前面我们说过,当丢包的时候,会有两种情况:
1)等到RTO超时,重传数据包。TCP认为这种情况太糟糕,反应也很强烈。
sshthresh = cwnd /2
cwnd 重置为 1
进入慢启动过程
2)Fast Retransmit算法,也就是在收到3个duplicate ACK时就开启重传,而不用等到RTO超时。
TCP Tahoe的实现和RTO超时一样。
TCP Reno的实现是:
cwnd = cwnd /2
sshthresh = cwnd
进入快速恢复算法——Fast Recovery
上面我们可以看到RTO超时后,sshthresh会变成cwnd的一半,这意味着,如果cwnd<=sshthresh时出现的丢包,那么TCP的sshthresh就会减了一半,然后等cwnd又很快地以指数级增涨爬到这个地方时,就会成慢慢的线性增涨。我们可以看到,TCP是怎么通过这种强烈地震荡快速而小心得找到网站流量的平衡点的。
D. 快速恢复算法 – Fast Recovery
TCP Reno
快速重传和快速恢复算法一般同时使用。快速恢复算法是认为,你还有3个Duplicated Acks说明网络也不那么糟糕,所以没有必要像RTO超时那么强烈。
注意,正如前面所说,进入Fast Recovery之前,cwnd 和 sshthresh已被更新:
cwnd = cwnd /2
sshthresh = cwnd
然后,真正的Fast Recovery算法如下:
cwnd = sshthresh + 3 * MSS (3的意思是确认有3个数据包被收到了)
重传Duplicated ACKs指定的数据包
如果再收到 duplicated Acks,那么cwnd = cwnd +1
如果收到了新的Ack,那么,cwnd = sshthresh ,然后就进入了拥塞避免的算法了。
如果你仔细思考一下上面的这个算法,你就会知道,上面这个算法也有问题,那就是——它依赖于3个重复的Acks。注意,3个重复的Acks并不代表只丢了一个数据包,很有可能是丢了好多包。但这个算法只会重传一个,而剩下的那些包只能等到RTO超时,于是,进入了恶梦模式——超时一个窗口就减半一下,多个超时会超成TCP的传输速度呈级数下降,而且也不会触发Fast Recovery算法了。
http://coolshell.cn/articles/11609.html
TCP和UDP区别
UDP用户数据报协议,是面向无连接的通讯协议,UDP数据包括目的端口号和源端口号信息,由于通讯不需要连接,所以可以实现广播发送。UDP通讯时不需要接收方确认,属于不可靠的传输,可能会出现丢包现象,实际应用中要求程序员编程验证。
UDP与TCP位于同一层,但它不管数据包的顺序、错误或重发。因此,UDP不被应用于那些使用虚电路的面向连接的服务,UDP主要用于那些面向查询—应答的服务,例如NFS。相对于FTP或Telnet,这些服务需要交换的信息量较小。
UDP是无连接协议,,因为客户端与服务器端不存在长期的关系,比如客户端创建一个套接字发送给服务器,然后还可以用该套接字发送另一个数据给另一个服务,同样UDP服务器也可以用同一个套接字从若干不同的客户接受多个数据报。
使用UDP协议包括:TFTP(简单文件传输协议)、SNMP(简单网络管理协议)、DNS(域名解析协议)、NFS、BOOTP。
TCP 与 UDP 的区别:TCP是面向连接的,可靠的字节流服务;UDP是面向无连接的,不可靠的数据报服务。
http://blog.csdn.net/ce123_zhouwei/article/details/8976006
注意:tcp是有状态协议,而ip、http都是无状态的
网络层
在TCP/IP 体系结构中,直接为 ICMP 提供服务的协议是ip协议
ip地址
1)网络地址
IP地址由网络号(包括子网号)和主机号组成,网络地址的主机号为全0,网络地址代表着整个网络。
2)广播地址
广播地址通常称为直接广播地址,是为了区分受限广播地址。
广播地址与网络地址的主机号正好相反,广播地址中,主机号为全1。当向某个网络的广播地址发送消息时,该网络内的所有主机都能收到该广播消息。
3)组播地址
D类地址就是组播地址。
A类地址以0开头,第一个字节作为网络号,地址范围为:0.0.0.0~127.255.255.255;
B类地址以10开头,前两个字节作为网络号,地址范围是:128.0.0.0~191.255.255.255;
C类地址以110开头,前三个字节作为网络号,地址范围是:192.0.0.0~223.255.255.255。
D类地址以1110开头,地址范围是224.0.0.0~239.255.255.255,D类地址作为组播地址(一对多的通信);
E类地址以1111开头,地址范围是240.0.0.0~255.255.255.255,E类地址为保留地址,供以后使用。
注:只有A,B,C有网络号和主机号之分,D类地址和E类地址没有划分网络号和主机号。
4)255.255.255.255
该IP地址指的是受限的广播地址。受限广播地址与一般广播地址(直接广播地址)的区别在于,受限广播地址只能用于本地网络,路由器不会转发以受限广播地址为目的地址的分组;一般广播地址既可在本地广播,也可跨网段广播。例如:主机192.168.1.1/30上的直接广播数据包后,另外一个网段192.168.1.5/30也能收到该数据报;若发送受限广播数据报,则不能收到。
注:一般的广播地址(直接广播地址)能够通过某些路由器(当然不是所有的路由器),而受限的广播地址不能通过路由器。
5)0.0.0.0
常用于寻找自己的IP地址,例如在我们的RARP,BOOTP和DHCP协议中,若某个未知IP地址的无盘机想要知道自己的IP地址,它就以255.255.255.255为目的地址,向本地范围(具体而言是被各个路由器屏蔽的范围内)的服务器发送IP请求分组。
6)回环地址
127.0.0.0/8被用作回环地址,回环地址表示本机的地址,常用于对本机的测试,用的最多的是127.0.0.1。
7)A、B、C类私有地址
私有地址(private address)也叫专用地址,它们不会在全球使用,只具有本地意义。
A类私有地址:10.0.0.0/8,范围是:10.0.0.0~10.255.255.255
B类私有地址:172.16.0.0/12,范围是:172.16.0.0~172.31.255.255
C类私有地址:192.168.0.0/16,范围是:192.168.0.0~192.168.255.255
路由选择
常见的路由选择协议有:RIP协议、OSPF协议。
RIP协议 :它选择路由的度量标准(metric)是跳数,最大跳数是15跳,如果大于15跳,它就会丢弃数据包。
OSPF协议 :Open Shortest Path First开放式最短路径优先,底层是迪杰斯特拉算法,是链路状态路由选择协议,它选择路由的度量标准是带宽,延迟。
NAT协议
NAT网络地址转换(Network Address Translation)属接入广域网(WAN)技术,是一种将私有(保留)地址转化为合法IP地址的转换技术,它被广泛应用于各种类型Internet接入方式和各种类型的网络中。原因很简单,NAT不仅完美地解决了lP地址不足的问题,而且还能够有效地避免来自网络外部的攻击,隐藏并保护网络内部的计算机。
ARP-地址解析协议
ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议。
1:首先,每个主机都会在自己的ARP缓冲区中建立一个ARP列表,以表示IP地址和MAC地址之间的对应关系。
2:当源主机要发送数据时,首先检查ARP列表中是否有对应IP地址的目的主机的MAC地址,如果有,则直接发送数据,如果没有,就向本网段的所有主机发送ARP数据包,该数据包包括的内容有:源主机 IP地址,源主机MAC地址,目的主机的IP 地址。
3:当本网络的所有主机收到该ARP数据包时,首先检查数据包中的IP地址是否是自己的IP地址,如果不是,则忽略该数据包,如果是,则首先从数据包中取出源主机的IP和MAC地址写入到ARP列表中,如果已经存在,则覆盖,然后将自己的MAC地址写入ARP响应包中,告诉源主机自己是它想要找的MAC地址。
4:源主机收到ARP响应包后。将目的主机的IP和MAC地址写入ARP列表,并利用此信息发送数据。如果源主机一直没有收到ARP响应数据包,表示ARP查询失败。
广播发送ARP请求,单播发送ARP响应。
数据链路层
长度问题
MTU:最大传输单元,以太网的MTU为1500Bytes
以太帧中数据长度为46-1500字节
太网帧的最小长度为64字节(6目的mac+6源mac+2类型+46数据+4校验),最大长度为1518字节(6+6+2+1500+4)
ip报文和tcp报文的头部是20B
TCP最小数据长度为1460Bytes
TCP数据包大小 1500(MTU) - IP头(20B)- TCP头(20B) = 1460B 这也是最大的MSS
UDP数据包 1500 - IP头(20B) - UDP头(8B) = 1472B)IP数据包的最大长度是64K字节(65535),TCP最大负载65535-40B
TCP报文段的最大负载为65495字节,因为每个数据段必须适合IP的载荷能力,不能超过65535字节,IP头20B,TCP包头20B,
故最大负载为65535- 20-20=65495Bip分片
虽然IP报文的范围在64KB到65535,但受到二层MTU的限制。
IP MTU=MSS+20bytes(IP包头)+20bytes(TCP包头)。
tcp里有个字段MSS说的是TCP最大能携带的数据大小(不包括报头大小)。这个会在SYN协商时确定。
一般TCP实际载荷为1500-20(IP报头)-20(TCP报头)=1460字节
如果TCP数据不大于1460就不需要进行分段处理。
协议
IEEE802.3 以“以太网”为技术原形,本质特点是采用CSMA/CD 的介质访问控制技术。
“以太网”与IEEE 802.3略有区别。但在忽略网络协议细节时, 人们习惯将IEEE 802.3称为”以太网”。
EEE 802.11—无线局域网。
mac地址
MAC地址的长度为48位(6个字节),其中前24位代表网络硬件制造商的编号,它由IEEE(Istitute of Electrical and Electronics Engineers,电气与电子工程师协会)分配,而后24代表该制造商所制造的某个网络产品(如网卡)的系列号。每个网络制造商必须确保它所制造的每个以太网设备都具有相同的前三字节以及不同的后三个字节。这样就可保证世界上每个以太网设备都具有唯一的MAC地址。
其他知识点
大端法和小端法
其实 big endian 是指低地址存放最高有效字节( MSB ),而 little endian 则是低地址存放最低有效字节( LSB )。大弟高,小弟低
所有网络协议也都是采用 big endian 的方式来传输数据的。所以有时我们也会把 big endian 方式称之为网络字节序。当两台采用不同字节序的主机通信时,在发送数据之前都必须经过字节序的转换成为网络字节序后再进行传输。
Little Endian
QoS
QoS(Quality of Service),中文名为”服务质量”。
它是指网络提供更高优先服务的一种能力,包括专用带宽、抖动控制和延迟(用于实时和交互式流量情形)、丢包率的改进以及不同WAN、LAN 和 MAN 技术下的指定网络流量等,同时确保为每种流量提供的优先权不会阻碍其它流量的进程
只要涉及到带宽分配和对业务服务质量有要求的地方,就会有QoS设计。
QoS技术多应用于广域网络和语音、视频等媒体业务系统。