关于tcp-ip:Initial-connection超时接口无法正常请求Status-canceled

问题形容最近上了一版需要,其中有一个接口因为后端的计算量超级微小,导致接口工夫要达到七八秒能力返回对应后果。 上了生产环境当前,申请总是失败。 测试环境是好好的...查看控制台申请发送的报文相干信息如下: 笔者看一下报文,发现申请的状态从开始的pending期待到最初的canceled勾销。 点开申请的Timing面板查看,发现申请卡在Connection Star的Initial connection中央不往下走了。 Initial connection是建设TCP连贯的意思,笔者不禁考虑,为啥好好的申请,TCP连贯连不上了啊,也是一脸懵。 于是,笔者去百度如何解决Initial connection过慢失败问题,发现网上的帖子七嘴八舌,如:可能是一个域名下挂着两个ip、如:可能是域名解析DNS问题之类的等... 与此同时,后端共事也在看如何优化本人的接口,让接口返回疾速一些... 前后端就这样各自钻研了一下午。 解决方案其实一开始方向就错了,不应该看Initial connection超时就认为是什么环境域名导致TCP连贯不上(公司测试环境是ip生产环境是域名),导致TCP连贯不上的起因有很多。 其中有一点就是前端限度了超时工夫,导致了TCP没工夫去进行连贯、去进行三次握手四次挥手,所以最终的解决方案是: 前端放开超时工夫axios中的timeout超时工夫限度 既然这个申请会达到七八秒,那么这个就将超时工夫设置为16秒,这样的话,工夫足够用了。 import axios from "axios";const http = axios.create({ timeout: 16000 // 给予接口足够的工夫})这样设置当前,发现,问题解决 第一张图是失败的超时勾销的申请,再附上一张胜利的不超时的申请

January 8, 2023 · 1 min · jiezi

关于tcp-ip:什么是TorTor浏览器更新有什么用

前言:Tor我的项目团队近日发表,公布Tor浏览器11.5版本。Tor被美国国家安全局(NSA)誉为“互联网匿名零碎之王“。Tor ( The Onion Router)零碎就是洋葱路由技术的具体实现。 Tor我的项目团队公布Tor浏览器11.5版本,而此次更新1.帮忙用户主动绕过互联网审查2.HTTPS 默认开启3.对网络设置菜单进行了重大改良。说起TOR浏览器都略有耳闻,那么Tor是什么样的技术原理?到底要如何利用?一、什么是Tor现在互联网曾经是咱们最罕用的交流平台,所有痕迹在互联网上都有迹可循。为了拆穿上网时的个人信息与身份,爱护个人隐私和平安,各种网络匿名冲浪技术应运而生,而洋葱路由(Onion Routing)技术和Tor ( The OnionRouter)零碎则在它们当中怀才不遇,并被美国国家安全局(NSA)誉为“互联网匿名零碎之王”。 要晓得,电脑可能上网是以互联网编号调配机构(IANA,Internet Assigned Numbers Authority)调配的IP地址为前提,互联网的IP数据包由包头和数据载荷组成。数据载荷可经加密以防被第三方窥视,但包头蕴含发送方和接管方的IP地址、数据载荷长度、发送工夫等信息,如果网站手动攻打用户的上网地点、拜访网站、身份背景以及通联关系可能会被盗取。洋葱路由( Onion Routing)技术综合使用了随机多跳路由、多层封包、多重加密等技术手段,能够实现牢靠的在线匿名。1996年Reed,M.G.P.F. Syverson,和D. M. Goldschlag提出的匿名通信算法,基本原理等同于Chaum,D. L.的 Mix 匿名通信算法,随后由美国海军提出的和孵化的,它的初衷是爱护政府通信以及为情报界和军队的网络流动提供匿名掩护和身份爱护。洋葱头路由的目标是为基于TCP的利用提供低提早的匿名通信服务,如web拜访,即时通信等。洋葱头路由算法基于通道(Circuit)实现数据报文的路由和传输。算法在网络中通过若干个节点建设通道,通过通道传输后续的用户数据。 Tor ( The Onion Router)零碎就是洋葱路由技术的具体实现。Tor Project公司开发的Tor软件—Tor Project、一些大学和机构提供的一组外围Tor路由器与寰球志愿者提供的数以千计的Tor路由器,独特组成了一个收费、开源的互联网匿名零碎—Tor。Tor目前以参与者意愿提供中继节点的形式宽泛地部署在Internet 中,是Internet中最胜利的公共匿名通信服务。Tor的设计引入完满的前向秘密(perfectforwarsecrecy、拥塞管制(congestiopcontro)、口亟服务(directory service)、完整性校验(gintesrity checking)。可配置的进口策略(configurable exit policies)和端到端完整性校验等机制,解决了第一代洋葱头路由匿名通信零碎设计的种种问题。Tor有两种实体,别离是Tor用户(Tor user)和Tor节点(Tor node)。Tor节点提供中继服务,是Tor 网络的主体。Tor用户在零碎中运行本地代理Onion Proxy (OP)程序,该程序抉择中继节点,通过中继节点建设通道,接管利用TCP数据流,并将该数据流通过已建设通道传输。每个Tor 节点都具备一组身份秘钥(identitykey)和-一组洋葱头秘钥(onion key)。身份秘钥用来签订Tor 节点的路由描述符。路由描述符是一个汇合,包含该节点的洋葱头秘钥、地址、带宽、进口机制等,注册在目录服务中。洋葱头秘钥用来建设传输通道以及协商传输的会话秘钥。 二、Tor利用的双面性任何技术都是双面性的,Tor提供了爱护用户隐衷的匿名通信服务。通过Tor网络传输的用户通信,既有合理合法的用户行为,也有滥用的行为。因为Tor网络的机制是进口节点代表用户拜访最终的目标服务,因而当呈现滥用行为时,目标服务看到的是进口节点发动的歹意行为,其间接后果往往是目标服务阻止进口节点拜访,从而使所有通过该进口节点拜访同样目标服务的通信都被阻止。Tor网络中局部传输流量的内容为不平安的利用协定,如Telnet、POP3 等。因而局部歹意Tor节点,当其作为传输通道的进口节点时,则运行相应的记录程序,对传输的敏感数据进行记录。如记录的Telnet或 POP3协定中明码传输的用户名和口令,并用作商业的用处,发售给相干的公司和机构。当初国内一些科技公司开发了检测IP代理的软件,用来检测Tor连贯,避免欺诈、增强流量过滤、防止虚伪账号注册等问题。 三、对于Tor浏览器11.5版本本次Tor的更新是对于三大方面:1.主动绕过互联网审查(Auto block bypassing) 2.HTTPS 默认开启(HTTPS on by default)版本11.5 中的另一个重要新性能是将“HTTPS 模式”设为默认浏览模式,以便通过隧道进行连贯。这确保了用户和托管网站的服务器之间的所有数据交换都将被加密,以进攻中间人 (MitM) 攻打并爱护用户免受歹意进口中继的 SSL剥离。3. 网络设置菜单更改为“连贯设置“(Better settings)Tor 浏览器 11.5 的第三个重大改良是对网络设置菜单进行了重大改良,当初称为“连贯设置”,它应该更容易找到和了解特定设置。最值得注意的是,桥接配置和连贯选项曾经过从新设计,以实现疾速轻松的审查和治理。在保留的桥上应用表情符号,新界面首次提供了配置的可视化,便于辨认正确的桥并在须要时方面快捷的抉择它。  现在TORDE 的用户数曾经超过十万,如军事、情报机构、记者等以及超过75个国家的6011个继电器提供在线匿名和隐衷爱护。           

July 27, 2022 · 1 min · jiezi

关于tcp-ip:关于TCPIP协议漏洞的安全措施

摘要:上篇咱们介绍了TCP/IP协定中常见的破绽类型包含ARP病毒攻打、基于RIP的攻打、DNS坑骗、TCP连贯坑骗。面对TCP/IP协定中存在的破绽咱们要采取什么样的安全措施去预防和解决呢?首先从架构角度来说:IPSec与TLS最罕用的两种平安架构,能够利IPSec、TLS平安架构在不同的协定层来爱护数据传输的安全性。一、IPSecIPSec 是一组用来在网络层进步数据包传输平安的协定族统称,它通过在原有的IP报文中退出一些特定的检测头来达到平安确认的目标。IPSec有两种工作模式,别离是传输模式和隧道模式,前者实用于端到端(End to End),即两台主机之间的 IPSec 通信,后者实用于站点到站点(Site to Site),即两个网关之间的 IPSec 通信,IPSec 由 AH 协定、ESP协定和一些简单的平安验证算法组成,这些根本的算法为IPSec中的协定服务。咱们次要介绍AH和ESP两个协定:(1)AH协定提供的平安服务AH 的工作模式是在每一个数据包中的 IP 报头后增加一个 AH 头,这个 AH 头有本人独特的字段用于提供平安服务,AH 能够保证数据的完整性不被篡改,但不能避免数据被偷盗。AH 应用的 IP 协定号是 51,当IP报文的协定号局部为51 时,代表IP头前面是一个 AH 报头。AH提供的平安服务次要有数据源认证,退出一个单方协商好的密文,来对对方身份以及数据的有效性进行验证;第二个是数据完整性校验,因为AH协定须要避免数据被非法篡改,因而该协定会通过引入一个单向Hash函数来创立一个散列值或者摘要信息,将该散列值与文本联合向接管方传输,同时接受方用同样的单向Hash函数对承受内容进行解密,验证后果是否统一,以此来爱护数据的完整性。第三个是防报文重放攻打,所谓重放攻打就是攻击者尽管不晓得加密过的数据包外面到底是什么,然而能够通过截取这个数据包再发给接受方从而使接管方无奈判断哪个才是正确的发送者,而AH协定会校验序列号字段中的数值是否反复过,若反复,则间接抛弃。(2)ESP 协定提供的平安服务ESP与 AH不同的是 ESP会先把数据段加密,而后再寄存到IP报文中,从而达到避免窃听的目标。ESP 除了在 IP 报头的前面会加上一个 ESP报头以外,还会在报文最初加上一个 ESP 报尾,该报尾用来提供加密服务。这样攻击者即便获取了该数据包,在没解开 ESP 加密的状况下也无奈获知其中的信息。ESP 提供的平安服务和 AH 有所重合,ESP应用序列号字段来避免重放攻打,ESP 通常应用HMAC-MD5 或 HMAC-SHA-1算法对加密后的载荷进行 Hash 计算来实现认证和保障数据完整性的性能。但因为ESP会把数据加密之后再传输,因而会提供保密性服务,在传输机密性数据的时候 ESP 有很大劣势。此外,在 NAT 模式下,因为AH会对IP地址也做Hash运算,因而在地址转换之后 AH 的 Hash 值会被毁坏,而ESP的IP协定号是50,在进行NAT转换时没有相应的 TCP或UDP端口号的概念。为了使 ESP 可能满足 NAT环境下的地址转换,这时就须要引进一个新的办法,即在ESP报文和 IP 报头之间退出一个新的UDP报头。二、TLS协定TLS 协定工作在传输层,因为TCP和UDP都有可被利用的破绽,因而它是为了解决传输层链路平安问题而呈现的。TLS 分为两种协定,别离是 TLS 记录协定和 TLS 握手协定。TLS 记录协定依据 TLS 握手协定协商的参数,对下层所交付的数据进行各种操作,从而使数据通过密文的模式传输,而接管方则通过解密的形式来承受数据。通过这种形式就能够大大增强数据传输的安全性。另一种协定是 TLS 握手协定,他让客户端和服务端进行协商,确定一组用于数据传输加密的密钥串,互相认证对方,这样当攻击者没有通过密钥认证时,就无奈与另一端进行数据通信。首先,客户端向服务端发送 ClientHello 音讯,其中含有一个客户端生成的随机数,咱们假如为R1和可供选择的版本号清单等信息。第二步,依据客户端发来的Client Hello,服务端回复 Server Hello 音讯,其中会依据客户端发来的清单数据确定两端通信将会应用的版本号,明码套件,压缩形式等等协定须要的重要信息,并产生一个服务端随机数 R2,当服务器认证时,服务器会发给客户端本人的证书。第三步,当要求客户端认证时,客户端会先发送本人的证书,同时依据之前客户端和服务器端产生的随机数专用一种算法计算出密钥。最初互相发送了 Finished 音讯后就代表握手完结,能够开始传输数据。同时也能够依据每种破绽不同的特点进行有针对性的进攻,然而一些进攻办法并不全面。一、ARP病毒攻打的常见进攻办法目前有很多针对ARP病毒攻打的进攻办法,咱们来看一下常见的进攻办法。(1)进步零碎安全性定期更新操作系统补丁,及时降级杀毒软件病毒库,并开启杀毒软件的实时监控性能,避免零碎被非法入侵或感化ARP病毒,然而这种进攻办法只能避免本机感化ARP病毒,并不能无效进攻ARP坑骗。(2)部署ARP防火墙ARP防火墙在肯定水平上能够用来帮忙缓解ARP攻打,帮助爱护局域网内主机平安。ARP防火墙除了下文行将介绍的绑定MAC地址性能外,最次要的进攻办法就是主动防御。主动防御是指ARP防火墙依照肯定频率强制对外发送正确的ARP数据包,这ARP防火墙在肯定水平上能够用来帮忙缓解ARP攻打,帮助爱护局域网内主机平安。ARP防火墙除了绑定MAC地址性能外,最次要的进攻办法就是主动防御。主动防御是指ARP防火墙依照肯定频率强制对外发送正确的ARP数据包,这显然会对网络造成额定的累赘。如果发送频率过高时,会在局域网内造成ARP风暴。而且攻击者只有进步攻击速度,使其大于ARP防火墙的主动防御速度,主动防御就会生效。(3)在交换机或主机端绑定MAC地址在交换机端绑定每台主机的IP/MAC对应关系,为每台主机增加一条动态ARP缓存条目。当交换机收到来自主机的数据包时,将数据包的IP地址和MAC地址与ARP缓存条目进行比对,如果雷同则放行数据包,否则该数据包将被抛弃。同理,在主机端也能够绑定网关的IP/MAC对应关系,为网关增加一条动态ARP缓存条目。这种进攻办法尽管能够抵挡肯定水平的ARP攻打,但会就义 Internet的移动性和主动配置性,减少了网络管理员的累赘,不适用于主机变动颊繁的局域网。二、基于RIP的攻打的常见预防办法(1) 将路由器的某些接口配置为被动接口。配置为被动接后,该接口进行向该接口所在的网络播送路由更新音讯。然而,容许持续在该接口接管路由更新播送音讯。(2) 配置ACL访问控制列表。只容许相应源IP地址的路由更新报文进入。(3) 在RIPV2中应用验证机制。RIPV1天生就有不平安因素。因为它没有应用认证机制并应用不牢靠的UDP协定进行传输。RIPv2的分组格局中蕴含了一个选项能够设置16个字符的明文明码字符串(示意可很容的被嗅探到)或者MD5签字。尽管RIP信息包能够很容易的伪造,但在RIPv2中你应用了MD5签字将会使坑骗的操作难度大大提高。(4)采纳路由器之间数据链路层PPP的验证。采纳PPP的PAP验证或Chap验证实现数据链路层的平安线路连贯。三、DNS坑骗常见预防办法(1)进行IP地址和MAC地址的绑定① 预防ARP坑骗攻打。因为DNS攻打的坑骗行为要以ARP坑骗作为开始,所以如果能无效防备或防止ARP坑骗,也就使得DNS坑骗攻打无从下手。例如能够通过将GatewayRouter的IpAddress和MACAddress动态绑定在一起,就能够防备ARP攻打坑骗。②DNS信息绑定。DNS坑骗攻打是利用变更或者假装DNS Server的IP Address,因而也能够应用MACAddress和IP Address动态绑定来进攻DNS坑骗的产生。因为每个Nctwork Card 的MAC Address具备惟一性质,所以能够把DNS Server的 MAC Address与其IPAddress绑定,而后此绑定信息存储在客户机网卡的Eprom中。当客户机每次向DNS Server 收回查问串请后,就会检测DNS Server响应的应答数据包中的MACAddress是否与Eprom存储器的 MAC Address雷同,要是不同,则很有可能该网络中的 DNS Server受到DNS坑骗攻打。这种办法有肯定的有余,因为如果局域网外部的客户主机也保留了DNS Server 的 MAC Address,依然能够用 MACAddress进行假装坑骗攻打 。(2)应用Digital Password 进行分别在不同子网的文件数据传输中,为预防窃取或篡改信息事件的产生,能够应用工作数字签名(TSIG)技术即在主从Donain Name Server中应用雷同的Password和数学模型算法,在数据通信过程中进行分别和确认。因为有Password进行校验的机制,从而使主从 Server的身份位置极难假装,增强了Domain Name信息传递的安全性。在不同子网的文件数据传输中,为预防窃取或篡改信息事件的产生,能够应用工作数字签名(TSIG)技术即在主从Donain Name Server中应用雷同的Password和数学模型算法,在数据通信过程中进行分别和确认。因为有Password进行校验的机制,从而使主从 Server的身份位置极难假装,增强了Domain Name信息传递的安全性。安全性和可靠性更好的 Domain Name Service是应用域名零碎的平安协定(Domain Name System Security,DNSSEC)),用Digital Signature的形式对搜寻中的信息源进行分辨,对 DATA的完整性施行校验。因为在设立 Domain时就会产生Password,同时要求下层的Domain Name也必须进行相干的Domain Password Signature,显然这种办法很简单,所以InterNIC域名治理截至目前尚未应用。然而就技术档次上讲,DNSSEC应该是现今最欠缺的Domain Name设立和解析的方法,对防备Domain Name坑骗攻打等安全事件是十分无效的。(3)间接应用IP地址拜访对个别信息安全等级要求非常严格的WEB站点尽量不要应用DNS进行解析。因为DNS坑骗攻打中不少是针对窃取客户的私密数据面来的,而少数用户拜访的站点并不波及这些隐衷信息,因而当拜访具备严格窃密信息的站点时,能够间接应用IP地址而无需通过DNS解析,这样所有的DNS坑骗攻打可能造成的危害就能够防止了。除此,应该做好 DNS Server的平安配置我的项目和降级DNS软件,正当限定 DNS Server进行响应的IP地址区间,敞开DNS Server的递归查问我的项目等。(4)对DNS数据包进行监测在DNS坑骗攻打中, Client会接管到至多两个 DNS的数据响应包,一个是实在的数据包,另一个是攻打数据包。坑骗攻打数据包为了抢在实在应答包之前回复给Client,它的信息数据结构与实在的数据包相比非常简略,只有应答域,而不包含受权域和附加域。因而,能够通过监测DNS响应包,遵循相应的准则和模型算法对这两种响应包进行分辨,从而防止虚伪数据包的攻打。四、TCP连贯坑骗的常见进攻办法(1)利用网络拓扑构造IP协定自身反对包过滤,当一个数据包从广域网进入局域网时,受害者能够查问源IP地址字段是否属于局域网外部地址段。如果是,则抛弃这个数据包。这种进攻办法的前提是受害者仪信赖局域网内主机。如果受害者不仅信赖局域网内主机,还通过其余协定受权。域网的主机对其进行拜访,那么就无奈利用该办法进攻来自广域网的攻击者。(2)限度仅利用IP地址进行认证的协定比方Unix零碎的Rlogin协定,它仅仅利用IP地址进行身份认证。只有主机的IP地址蕴含在信赖列表中,Rlogin协定就容许近程登录到另一主机,而不需输出明码。这样,攻击者能够利用Rlogin协定轻松地登录到受害者主机。咱们能够限度这些仅利用IP地址进行认证的协定,或对IP地址进行肯定配置或验证,通过危险画像、IP代理检测验明这些IP地址是否存在危险,进步这些协定的安全性。(3)应用加密算法或认证算法对协定进行加密或认证能够组织攻击者篡改或伪造TCP连贯中的数据。而就目前的加密技术或认证技术而言,单方须要共享一个密钥或者协商出一对射私密钥对。这就波及到通信单方必须采纳同种加密或认证伎俩,然而,加密算法或认证算法往往波及到简单的数学计算,很耗费系统资源,会使通信效率显著降落。

July 15, 2022 · 1 min · jiezi

关于tcp-ip:TCPIP协议常见漏洞类型

摘要:TCP/IP由网络层的IP协定和传输层的TCP协定组成。常见的破绽类型包含ARP病毒攻打、基于RIP的攻打、DNS坑骗、TCP 连贯坑骗。TCP/IP是TransmissionControlProtocol/InternetProtocol的简写 ,中译名为传输控制协议/因特网互联协定,又名网络通讯协定,是 lnternet 最根本的协定、Interact国际互联网络的根底。TCP/IP由网络层的IP协定和传输层的TCP协定组成。TCP/IP定义了电子设备如何连入因特网,以及数据如何在它们之间传输的规范。TCP/IP协定采纳了4层的层级构造,别离是网络接入层、网络层、传输层和应用层。每一层都呼叫它的下一层所提供的网络来实现本人的需要。 简略来讲,TCP负责发现传输的问题,一有问题就发出信号,要求从新传输,直到所有数据安全正确地传输到目的地。而IP协定规定须要给因特网的每一台电脑规定一个地址,这个地址就是IP地址。IP地址通过软件实现网络物理地址“对立”的办法。这种办法应用对立的地址格局,在对立治理下将地址调配给主机。因为TCP/IP协定是一个开放性的协定导致其在TCP/IP 协定栈中,绝大多数协定没有提供必要的平安机制,存在肯定的破绽平安问题。 TCP/IP 协定常见破绽类型ARP 病毒攻打ARP病毒攻打的工作原理是通过伪造通信单方一端的IP地址或 MAC 地址,让另一端误以为该主机为正确主机从而达到坑骗目标。当网络中源主机A想和目标主机 B 进行通信,A会先播送ARP申请报文,冀望B能收到并返回给A本人的 MAC 地址。但因为报文采纳的是播送模式,因而攻击者 C在收到A的申请报文时会将本人的IP地址伪造成B的IP地址,这在 ARP申请报文中能够很容易取得,接着攻击者C向发送带有 B 的IP地址,C的 MAC地址的返回音讯,让A误以为C就是非法的目标主机 B,从而攻击者C就达到了盗取信息的目标。基于RIP的攻打RIP 是一种基于间隔(跳数)的路由抉择协定,它的作用是计算数据包在网络中路由的最佳门路,因为RIP基于跳数且规定了最大跳数不能够超过15,因而它只实用于中小型的网络。基于RIP的攻打实际上是攻打网络中路由器的路由表。因为 RIP 是基于 UDP 协定进行传输,而 UDP 是一种不牢靠,不须要建设连贯的传输层协定。因而运行着 RIP 协定的路由器会无条件的承受任何来自网路中的报文,包含一些非法的路由表更新报文。路由器在承受这些报文时会在没有执行路由表更新命令的状况下扭转本身的路由表。从而导致该路由器的路由表错乱,甚至可能影响该路由器的邻接路由器,继而导致整个网络瘫痪,带来重大的结果。DNS坑骗DNS(Domain name resolution)又称域名解析协定,它用来将域名和 IP 地址进行互相转换,从而让用户在上网的时候能够间接输出域名而不是简短繁琐的 IP 地址。在 DNS 坑骗中,攻击者通常会先攻打 DNS 服务器并取而代之,并扭转原先 DNS 服务器中的 IP 地址和域名的映射关系。 当用户拜访相应的域名时返回的实际上是一个谬误的网页,而攻击者能够通过这个网页向用户植入病毒或间接开展攻打。DNS坑骗的伎俩分为两种,一种是篡改本地主机的 Hosts 文件,Hosts文件实现的就是 DNS 服务器的性能。例如将Hosts 文件中的一个域名对应的 IP 地址改老本机的回环地址(127.0.0.1),这样用户在拜访这个域名时就无奈达到想要的网页。另一种是DNS劫持,即劫持用户应用的DNS服务器,通常来说黑客会将本人曾经建设好的攻打网站的IP地址映射到用户常常拜访的网站的域名,而该攻打网站和原网站看上去相差无几,这样用户即便被攻打也毫不知情。TCP 连贯坑骗尽管TCP协定是一种牢靠的链路层协定,然而因为每台主机的IP地址在每次上网的时候都可能产生扭转,因而攻击者能够通过这个破绽扰乱两台主机的TCP连贯。TCP连贯坑骗中,攻击者C会始终对主机A进行攻打(例如 Dos 攻打)使其瘫痪,从而阻止A与B进行通信,而后本人再伪造成主机 A与B 建设 TCP连贯。过程如下:C→B:SYN=1,seq=a B→A:SYN=1,ACK=1,seq=b,ack=a+1 C→B:ACK=1,seq=a+1,ack=b+1 攻击者C首先向B发送连贯申请报文,同步位SYN置为1,序列号 seq为a。B收到申请报文后,向A收回确认报文,确认号 ack为 a+1,序号seq 为 b,因为A处于瘫痪中因而不会发送响应报文。C 通过网络嗅探工具失去B向A发送的 ack 和seq,对B发送确认报文,将ACK 置为1,序号 seq为 a+1,确认号 ack为 b+1。这样B和攻击者C之间就间接建设了TCP连贯,并能够间接向B发送指令,而B还认为指令是由非法主机A发送过去的,将执行这些命令。从而导致C能够任意地向B发送攻打命令,以致B瘫痪。那么面对TCP/IP协定常见破绽咱们要如何预防呢?咱们下一篇接着讲。 ...

July 13, 2022 · 1 min · jiezi

关于tcp-ip:TCPIP-协议的三次握手和四次挥手

TCP/IP 协定是传输层的一个面向连贯的安全可靠的一个传输协定,三次握手的机制是为了保障能建设一个安全可靠的连贯 三次握手那么第一次握手是由客户端发动,客户端会向服务端发送一个报文,在报文外面:SYN标记地位为1,示意发动新的连贯。当服务端收到这个报文之后就晓得客户端要和我建设一个新的连贯,于是服务端就向客户端发送一个确认音讯包,在这个音讯包外面:ack标记地位为1,示意确认客户端发动的第一次连贯申请。以上两次握手之后,对于客户端而言:曾经明确了我既能给服务端胜利发消息,也能胜利收到服务端的响应。然而对于服务端而言:两次握手是不够的,因为到目前为止,服务端只晓得一件事,客户端发给我的音讯我能收到,然而我响应给客户端的音讯,客户端能不能收到我是不晓得的。所以,还须要进行第三次握手,第三次握手就是当客户端收到服务端发送的确认响应报文之后,还要持续去给服务端进行回应,也是一个ack标记地位1的确认音讯。通过以上三次连贯,不论是客户端还是服务端,都晓得我既能给对方发送音讯,也能收到对方的响应。那么,这个连贯就被平安的建设了。 四次挥手四次挥手通常也是客户端发动的,客户端会发送一个报文,报文FIN=1,当服务端收到这个报文之后,就晓得了客户端想要和我断开连接然而此时服务端不肯定做好筹备,因为当客户端发动断开连接的报文的时候,服务端有可能还有未发送完的报文音讯须要持续发送,所以此时服务端只能通知客户端我晓得你要和我断开连接了,然而我这里可能还没做好筹备,须要等我一下,等会我会通知你于是,发完这个音讯确认报文之后,稍过片刻之后服务端持续发送一个断开连接的报文,FIN=1,表明服务端曾经做好断开连接的筹备,那么,当这个音讯发给客户端的时候,客户端同样须要持续发送一个音讯确认的报文那么通过这四次的互相沟通和连贯,我就晓得了,不论是客户端还是服务端,都曾经做好了断开的筹备 以上

June 12, 2022 · 1 min · jiezi

关于tcp-ip:网络七层结构是干啥的-看这篇文章就够了

前言“物理层、数据链路层、网络层、传输层、会话层、表示层和应用层”,明天咱们的指标就是把这些个玩意,翻译成“人话”,保障你一看就懂,一学就废~ 网络七层构造,置信是个搞计算机网络的,或者是搞软件开发的,甚至是搞互联网的,99%的人应该都晓得,最起码那也得是听过,就是下方这个玩意: (你要是听都没听过,别跟我说你是混迹于互联网界的啊~) 然而,如果让这些人讲清楚这七层构造是干嘛的,那这个比例,预计能从99%锐减到1%。 明天,就让咱们一起来把这七层构造,翻译成“人话”。 本着“有问题,找百度”的准则,我关上了百度百科,而后就发现了以下这些内容   看到这些查找进去的“答案”,置信大家跟我的感觉是一样的:“看是不可能看懂的,这辈子预计都看不懂了。。。” 想要看懂这些货色怎么办呢? 依照“失常”的思路,咱们须要解决以下问题:这七层都跟哪些内容相干?他们怎么关联起来的?协定这个玩意跟计算机是怎么联合的?操作系统是如何把IP数据包发给网卡的? 于是咱们发奋图强,理解到它大略跟应用程序、操作系统、路由器、交换机这些玩意相干,晓得协定通过一层一层的封包或者解包来传输数据。再钻研一下Linux网络实现,了解操作系统与外设的通信,两头可能还要写个驱动模块加深印象。额,等一下,晶体管是如何起到开关作用的?如同还得学学物理。。。 其实以上说的啥,我本人都不晓得,纯属一顿胡诌,哈哈哈。  但我晓得的是,这个“失常”的思路,相对是“不失常”的,置信很多人,面对生疏的常识时,都会犯这种“打破砂锅问到底”的谬误~ 宏观了解层面,考究的是“不求甚解”,只须要了解到以下这种水平即可。 翻译 整个网络当中,最根本或者是最外围的就是数据的传输,整个网络的搭建,都是为数据传输服务的,咱们类比一下快递物流的例子,就能够初步了解这七层都是干嘛的了: 1. 应用层 应用层的作用是为应用程序提供服务并规定应用程序中通信相干的细节,也就是为利用提供服务。常见的协定有 HTTP,FTP,TELNET、SMTP 等。 翻译成“人话”: 相当于收件员。当客户(利用)打电话(发动申请)给收件员(应用层)时,收件员能够依据客户的不同需要提供不同的服务(不同协定),比方隔天送达、指定工夫送达等等。 2. 表示层 表示层的作用是将利用解决的信息转换为适宜网络传输的格局,或者将来自下一层的数据转换为下层能解决的格局。它次要负责数据格式的转换。具体来说,就是将设施固有的数据格式转换为网络规范格局。常见的协定有 ASCII、SSL/TLS 等。 翻译成“人话”:  相当于打包员。如果快递(数据)太臃肿,他会在不毁坏快递的状况下压扁(压缩)它。如果客户重视安全线,全能的快递公司还能用密码箱( SSL/TLS)打包快递再快送。当然,打包员会确定,目的地快递站的拆包员,能无损地拆开包裹,将快递交给用户。3.会话层 会话层作用是负责建设和断开通信连贯,以及数据宰割等数据传输相干的治理。常见的协定有 ADSP、RPC 等。 翻译成“人话”: 相当于调度员。对快递运输进行调度指挥。例如这次客户要发100吨沙土(数据),到底是空运、陆运还是海运。而运完之后,相干信息(连贯)也能够被销毁了,这些都是他的职责。 4.传输层 传输层起着牢靠传输的作用。只在通信单方节点进行解决,而不需在路由器上解决。此层有两个具备代表性的协定:TCP 与 UDP。 翻译成“人话”:  相当于跟单员。负责任的跟单员(应用 TCP 协定)会保障快递送到客户手上,如果送不到就让公司再发一次。不负责任的跟单员(应用 UDP 协定)只管将快递送到客户指定的中央,不论快递是否送到客户手上。 5. 网络层 网络层负责将数据传输到指标地址。指标地址能够是多个网络通过路由器连贯而成的某一个地址。因而这一层次要负责寻址和路由抉择。次要由 IP、ICMP 两个协定组成。 翻译成“人话”: 相当于路线布局员。快递公司有很多集散中心(路由器),依据集散中心的状况(是否拥挤),找出一条最合适的门路将货物(数据)沿路运过来。 6. 数据链路层 该层负责物理层面上互连的节点之间的通信传输。例如与1个以太网相连的两个节点间的通信。常见的协定有 HDLC、PPP、SLIP 等。 翻译成“人话”:  相当于驾驶员。他们驾驶着汽车,将打包好的快递(数据帧)从一个城市(物理节点)运输到另一个城市。 7. 物理层 物理层负责0、1比特流(0、1序列)与电压高下、光的闪灭之间的调换。典型的协定有 RS 232C、RS 449/422/423、V.24 和 X.21、X.21bis 等。 翻译成“人话”: 相当于交通工具。例如公路、汽车和飞机等,承载货物(数据)的交通运输。 如果以上一堆文字都懒得看的话,那间接看上面这个图也行,这可是我消耗了大半天工夫消化了解的,拿着这张图,你就能够给他人去讲,网络七层构造是干嘛的啦~    1至4层被认为是低层,这些层与数据挪动密切相关。5至7层是高层,蕴含应用程序级的数据。每一层负责一项具体的工作,而后把数据传送到下一层。从上往下,每通过一层,协定就会在这个包裹下面做点手脚,加点货色,传送到接收端,再层层解套进去,如下示意图:   晓得了这些,咱们就能够来看一下“快递”的前进过程。 如果你是一个网络上的操作系统。1层和2层的网卡会接管申请并告诉你什么时候有包裹达到,驱动程序解决2层帧的进口,失去一个发亮和闪光的3层数据包。作为操作系统,你将调用一些罕用的利用程序处理3层数据。   如果你决定保留这个数据包,你将关上它,并且取出4层数据包。如果它是TCP协定,这个TCP子系统将被调用并关上这个数据包,而后把这个7层数据发送给在指标端口期待的应用程序,整个过程就完结了。   在理论过程中,七层构造执行了哪些操作呢? 要答复这个问题,咱们能够思考一下:用户输出一个网址,计算机执行了什么操作? 1. 所有的数据通信通过封装打包后,经由物理线路传送。   2. 所有的主机名都须要解析为IP地址。   3. 应用层应用HTTP协定,利用传输层面面向连贯的TCP协定。   4. WEB利用采纳客户机/服务器的工作模式。   5. 数据包通过路由器,依据路由表进行转发。   6.在每个网络外部,都要把IP地址转换成MAC地址。 ...

June 8, 2022 · 1 min · jiezi

关于tcp-ip:系列解读-SMCR-二融合-TCP-与-RDMA-的-SMCR-通信-龙蜥技术

文/龙蜥社区高性能网络SIG 一、引言通过上一篇文章 《系列解读SMC-R:通明无感晋升云上 TCP 利用网络性能(一)》咱们理解到,RDMA 绝对于 TCP 具备旁路软件协定栈、卸载网络工作到硬件的特点,能无效减少网络带宽、升高网络时延与 CPU 负载。而内核网络协议 SMC-R 在利用 RDMA 技术的同时、又进一步完满兼容了 socket 接口,可能通明无感的为 TCP 利用带来网络性能晋升。因而,龙蜥社区高性能网络 SIG 认为 SMC-R 将成为下一代数据中心内核协定的重要组成,对其进行了大量优化,并踊跃将这些优化回馈到上游 Linux 社区。 本篇文章作为 SMC-R 系列的第二篇,将聚焦一次残缺的 SMC-R 通信流程。通过具体的建连、传输、销毁过程,使读者进一步领会到 SMC-R 是一个交融了通用 TCP 与高性能 RDMA 的 "hybrid" 解决方案。 二、通信流程如前篇所述,应用 SMC-R 协定有两种办法。其一,是在应用程序中显式创立 AF_SMC 族的 socket;其二,是利用 LD_PRELOAD 或 ULP + eBPF 的形式通明的将应用程序中的 AF_INET 族 socket 替换为 AF_SMC 族 socket。咱们默认应用 SMC-R 通信的节点曾经加载了 SMC 内核模块,并通过上述形式将利用程序运行在 SMC-R 协定上。接下来,咱们以 first contact (通信两端建设首个连贯) 场景为例,介绍 SMC-R 通信流程。 2.1 确认对端能力应用 SMC-R 通信时,咱们首先须要确认对端是否同样反对 SMC-R 协定。因而,SMC-R 协定栈为应用程序创立 SMC 类型 socket (smc socket) 的同时,还会在内核创立并保护一个与之关联的 TCP 类型 socket (clcsock),并基于 clcsock 与对端建设起 TCP 连贯。(图/TCP 握手确认对端 SMC-R 能力) ...

April 22, 2022 · 5 min · jiezi

关于tcp-ip:结合中断分析TCPIP协议栈在LINUX内核中的运行时序

目录:1.Linux网络子系统的分层2.TCP/IP分层模型3.Linux 网络协议栈4.Linux 网卡收包时的中断解决问题5.Linux 网络启动的筹备工作6.Linux网络包:中断到网络层接管7.总结 【舒适提醒】文章略长,请急躁观看!Linux网络子系统的分层Linux网络子系统实现须要:l 反对不同的协定族 ( INET, INET6, UNIX, NETLINK...)l 反对不同的网络设备l 反对对立的BSD socket API须要屏蔽协定、硬件、平台(API)的差别,因此采纳分层构造: 零碎调用提供用户的应用程序拜访内核的惟一路径。协定无关接口由socket layer来实现的,其提供一组通用性能,以反对各种不同的协定。网络协议层为socket层提供具体协定接口——proto{},实现具体的协定细节。设施无关接口,提供一组通用函数供底层网络设备驱动程序应用。设施驱动与特定网卡设施相干,定义了具体的协定细节,会调配一个net_device构造,而后用其必须的例程进行初始化。 相干视频举荐手把手带你实现一个Linux内核文件系统Linux内核文件系统具体实现与内核裁剪TCP/IP协定栈深度解析丨实现单机百万连贯丨优化三次握手、四次挥手丨优化TCP的传输速率LinuxC++后盾服务器开发收费学习:C/C++Linux服务器开发/后盾架构师-学习视频 TCP/IP分层模型在TCP/IP网络分层模型里,整个协定栈被分成了物理层、链路层、网络层,传输层和应用层。物理层对应的是网卡和网线,应用层对应的是咱们常见的Nginx,FTP等等各种利用。Linux实现的是链路层、网络层和传输层这三层。在Linux内核实现中,链路层协定靠网卡驱动来实现,内核协定栈来实现网络层和传输层。内核对更下层的应用层提供socket接口来供用户过程拜访。咱们用Linux的视角来看到的TCP/IP网络分层模型应该是上面这个样子的。 首先咱们梳理一下每层模型的职责:链路层:对0和1进行分组,定义数据帧,确认主机的物理地址,传输数据;网络层:定义IP地址,确认主机所在的网络地位,并通过IP进行MAC寻址,对外网数据包进行路由转发;传输层:定义端口,确认主机上应用程序的身份,并将数据包交给对应的应用程序;应用层:定义数据格式,并依照对应的格局解读数据。 而后再把每层模型的职责串联起来,用一句通俗易懂的话讲就是:当你输出一个网址并按下回车键的时候,首先,应用层协定对该申请包做了格局定义;紧接着传输层协定加上了单方的端口号,确认了单方通信的应用程序;而后网络协议加上了单方的IP地址,确认了单方的网络地位;最初链路层协定加上了单方的MAC地址,确认了单方的物理地位,同时将数据进行分组,造成数据帧,采纳播送形式,通过传输介质发送给对方主机。而对于不同网段,该数据包首先会转发给网关路由器,通过屡次转发后,最终被发送到指标主机。指标机接管到数据包后,采纳对应的协定,对帧数据进行组装,而后再通过一层一层的协定进行解析,最终被应用层的协定解析并交给服务器解决。 Linux 网络协议栈 基于TCP/IP协定栈的send/recv在应用层,传输层,网络层和链路层中具体函数调用过程曾经有很多人钻研,本文援用一张比较完善的图如下: 以上阐明根本大抵阐明了TCP/IP中TCP,UDP协定包在网络子系统中的实现流程。本文次要在链路层中,即对于网卡收报触发中断到进入网络层之间的过程探索。 【文章福利】小编举荐本人的linuxC/C++语言交换群:832218493,整顿了一些集体感觉比拟好的学习书籍、视频材料共享在外面,有须要的能够自行添加哦!~! Linux 网卡收包时的中断解决问题 中断,个别指硬件中断,多由零碎本身或与之链接的外设(如键盘、鼠标、网卡等)产生。中断首先是处理器提供的一种响应外设申请的机制,是处理器硬件反对的个性。一个外设通过产生一种电信号告诉中断控制器,中断控制器再向处理器发送相应的信号。处理器检测到了这个信号后就会打断本人以后正在做的工作,转而去解决这次中断(所以才叫中断)。当然在转去解决中断和中断返回时都有爱护现场和返回现场的操作,这里不赘述。 那软中断又是什么呢?咱们晓得在中断解决时CPU没法解决其它事物,对于网卡来说,如果每次网卡收包时中断的工夫都过长,那很可能造成丢包的可能性。当然咱们不能完全避免丢包的可能性,以太包的传输是没有100%保障的,所以网络才有协定栈,通过高层的协定来保障间断数据传输的数据完整性(比方在协定发现丢包时要求重传)。然而即便有协定保障,那咱们也不能胡作非为的应用中断,中断的工夫越短越好,尽快放开处理器,让它能够去响应下次中断甚至进行调度工作。基于这样的思考,咱们将中断分成了高低两局部,上半局部就是下面说的中断局部,须要疾速及时响应,同时须要越快完结越好。而下半局部就是实现一些能够推后执行的工作。对于网卡收包来说,网卡收到数据包,告诉内核数据包到了,中断解决将数据包存入内存这些都是急切需要实现的工作,放到上半部实现。而解析解决数据包的工作则能够放到下半部去执行。软中断就是下半部应用的一种机制,它通过软件模拟硬件中断的处理过程,然而和硬件没有关系,单纯的通过软件达到一种异步解决的形式。其它下半部的解决机制还包含tasklet,工作队列等。根据所解决的场合不同,抉择不同的机制,网卡收包个别应用软中断。对应NET_RX_SOFTIRQ这个软中断,软中断的类型如下:enum{ HI_SOFTIRQ=0, TIMER_SOFTIRQ, NET_TX_SOFTIRQ, NET_RX_SOFTIRQ, BLOCK_SOFTIRQ, IRQ_POLL_SOFTIRQ, TASKLET_SOFTIRQ, SCHED_SOFTIRQ, HRTIMER_SOFTIRQ, RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */ NR_SOFTIRQS};通过以上能够理解到,Linux中断注册显然应该包含网卡的硬中断,包解决的软中断两个步骤。 l 注册网卡中断咱们以一个具体的网卡驱动为例,比方e1000。其模块初始化函数就是:static int __init e1000_init_module(void){ int ret; pr_info("%s - version %s\n", e1000_driver_string, e1000_driver_version); pr_info("%s\n", e1000_copyright); ret = pci_register_driver(&e1000_driver);... ...

September 13, 2021 · 4 min · jiezi

关于tcp-ip:TCP缓冲区和粘包拆包有什么关系

 欢送大家搜寻“小猴子的技术笔记”关注我的公众号,支付丰盛面试材料和学习材料。 你理解TCP缓冲区吗?它和TCP传输中的粘包和拆包有什么关系呢?粘包和拆包别离产生在TCP的那个阶段呢? 先简略回顾下TCP概念:在网络传输中TCP是面向连贯的、牢靠的、双通道、字节流一对一传输。TCP单方通信必须要先建设连贯,而后调配必要的内核资源。单方替换结束数据之后必须都要断开连接用来开释系统资源,长链接能够不用断开连接复用同一个通道。那么什么是TCP的缓冲区呢? 操作系统中有两个空间:用户空间和内核空间。每一个socket连贯都是在内核空间,内核针对每一个socket都有一个发送缓冲区和接收缓冲区。TCP的双工工作模式以及流量管制就是依赖这两个缓冲区的填充来实现的。 咱们之前用socket获取“OutputStream”获取一个输入流进行字节的写出,其实是写入到了“send buffer”发送缓冲区中,这个时候数据不肯定会发送到对方机器上。“write()”办法仅仅是将用户空间数据拷贝到了内核发送缓冲区中,具体什么时候发送由TCP决定。 TCP会从发送缓冲区中把数据通过网卡发送到指标机器的内核缓冲区中。如果零碎始终没有调用"recv()"办法进行读取的话,那么数据将会始终挤压在socket的recv buffer中。 TCP 粘包、拆包问题的由来: 如果你看懂了下面这幅图的话,那么对于粘包和拆包的问题就比拟好了解了。在这里我想先问一个问题,粘包和拆包是产生在传输过程中吗? 粘包和拆包问题到底产生在什么阶段?首先咱们须要分明地理解TCP数据是牢靠的,因而必定不是传输的过程中!因为数据发送是从缓冲区->网卡,因而粘包问题是从缓冲区读取数据的时候产生的。拆包则是从缓冲区到网卡的阶段产生的。 这里先解释下粘包:所谓的粘包就是发送方在同一时刻收回了两个或者两个以上的包到接收端。 假如发送端须要发送两条数据“别缓和,你这样没事的!”和“好好看文章,你肯定能够学会”。首先会把这两条数据放到发送缓冲区中,而后在通过网卡进行数据的发送到接管方的接收缓冲区中。如果接管方没有及时从接收缓冲区中获取往外取数据,那么数据就会在缓冲区挤压,这样两条数据就会积压在一块,就成了一条数据,这就是粘包的问题! 那么什么是拆包问题呢?拆包问题是TCP每次发送的长度是有限度的,如果发送一个包的数据过大的话,TCP就会把这个包拆成两个包来进行发送。 假如要发送的数据“别缓和,你这样没事的!”很大,TCP在发送的时候把它拆成了“别缓和,你这样”和“没事的!”进行发送,那么在接管方就会收到两个报文,这就是拆包的问题。 实际上过大的话,还有可能会被拆成三个或者更多的包进行发送。然而无论被拆成几个包,TCP都可能保障发送包的程序性和正确性。 那么产生粘包和拆包的起因是什么呢?这个和TCP的缓冲区与滑块窗口、MSS/MTU限度、Nagle算法无关。 有了粘包和拆包的问题,咱们在理论的开发中应该怎么防止或者解决这个问题呢?那就是定义咱们的通信协定。这样如果粘包了就能够依据协定来辨别不同的包,如果拆包了就期待数据形成一个残缺的音讯之后在进行解决。 第一种形式---定长协定:所谓的定长协定就是指定一个报文的固定长度,每次单方依照约定截取固定的长度。假如咱们须要发送“hello”和“very”两个单词,依照约定的5个字节进行一次截取。那么有余5个字节的单词能够增加0作为补充,则产生的规定如下。 因为有余约定长度的须要进行补0,因而定长协定会造成带宽的节约。 第二种形式---特殊字符分隔符:应用特殊字符分隔符就是在报文的结尾进行追加特殊字符分隔符,用次分隔符来标注这是一个残缺的报文,例如遇到了“\n”。 这样尽管能够对报文进行划分,然而要求就是报文中不能蕴含非凡分隔符。 第三种形式---固定头长度:发送数据之前,须要先获取须要发送内容的二进制字节大小,而后在须要发送的内容后面增加一个固定长度头整数,示意音讯体二进制字节的长度。 这种形式防止了特殊字符带来的问题,是生产中能够采取的一个形式,我在之前的文章中有介绍过这样的应用办法。 其实对于java程序员来说,咱们不用过分关怀接管和发送缓冲区,须要理解其概念,因为底层曾经为咱们做了封装。明确“粘包”和“拆包”产生的过程和起因。 通过观察用户空间和内核空间的数据交互,你兴许会发现进行一次残缺的交互须要进行四次的数据拷贝,这在性能上可能会有所影响。这也就有了面试官常常问的“零拷贝”的问题,尝试着本人对本文的了解学习一下“零拷贝”,这是为前面学习Netty打下松软的根底。

March 15, 2021 · 1 min · jiezi

关于tcp-ip:TCP的三次握手和四次挥手

一图胜千言,先上图: 三次握手的过程首先由客户端发动连贯申请,客户端将本人的序列号 seq 设为 x 并发送 SYN 包给服务端,客户端进入 SYN_SENT 状态。服务端在接管到客户端发来的 SYN 包之后,由 LISTEN 状态转为 SYN_RCVD 状态,服务端将 ack 设为 x+1 (收到的序列号+1) 同时将本人的 seq 设为 y ,并将 SYN-ACK 确认包发送给客户端。客户端收到服务端的确认之后,将 ack 设为 y+1 (收到的序列号+1) 并发送 ACK 确认包给服务端,客户端进入 ESTABLISHED 状态。服务端收到客户端发来的确认包之后,也进入 ESTABLISHED 状态。TCP 进行握手初始化一个连贯的指标是:分配资源、初始化序列号(告诉 peer 对端我的初始序列号是多少)。整个握手过程能够简化为上面的交互: 1)client 端首先发送一个 SYN 包通知 Server 端我的初始序列号是 X;2)Server 端收到 SYN 包后回复给 client 一个 ACK 确认包,通知 client 说我收到了;3)接着 Server 端也须要通知 client 端本人的初始序列号,于是 Server 也发送一个 SYN 包通知 client 我的初始序列号是 Y;4)Client 收到后,回复 Server 一个 ACK 确认包说我晓得了。 ...

March 1, 2021 · 1 min · jiezi

关于tcp-ip:理论-三天两夜万字长文吃透TCPIP

思维导图思维导图如下 计算机体系网络结构分层概述这里进行概述如下 物理层物理层上传送的单位为比特,规定了网络的一些电器特定,次要负责0,1比特流与电子信号之间的转换,如果没有物理层,0,1 形成的比特流将会无奈在物理介质中流传。 链路层数据链路层,又称作为链路层,单纯的0和1是没有任何意义的,必须规定其解读形式,多少个电信号算一组,每个电信号又有什么意义,这就是数据链路层的作用,数据链路层,规定次要有三个性能,别离是封装成帧、通明传输、差错控制。将会顺次解释这三个内容。 封装成帧在一段数据的前后别离增加首部和尾部,来对帧与帧之间实现一个定界。定界如下 通明传输因为不论什么数据,所传送的都应该能在链路上传送,因而通明传输会带来一个问题,当数据中的比特组合恰好统一的时候,如果采纳不适当的措施,将会造成数据被切分。如下图所示。 这里应用字节填充法实现通明传输的问题,发送端的数据在链路层中呈现控制字符SOH或者ETO的时候,在后面增加一个转义字符ESC,如果ESC也呈现的话,这里就在ESC之前持续增加一个ESC实现本义,如下所示。 差错控制在数据传输的过程中,如果呈现失落,或者帧损坏,这里就须要差错控制来进行检测和纠正,这个协定将会在网络层中进行阐明。 MAC地址数据帧筹备好了,这里还有一个问题,计算机A和计算机B之间数据互相发送,然而谁传给谁,如何辨别,这里MAC地址便呈现了。MAC地址,连人网络的每一个计算机都会有网卡接口,每一个网卡都会有一个惟一的地址,这个地址称作为MAC地址,计算机网络之间互相传送的时候,都会应用MAC地址进行互相的传送。 网络层网络层的次要性能负责不同网络之间转发数据,实现这个性能的,为路由器。 如果你在杭州的计算机A要给纽约的计算机B通信,这里就会应用播送形式发送数据包,而后比照MAC地址,雷同的接管,不同的抛弃,很显著,这样相当的不和你,所以在网络层中,划分了子网,协定规定,如果是在同一个子网,就会应用播送的模式把数据发送给对方,如果不是在同一个子网,将会发送给网关,而后进行转发。 传输层通过网络层,A曾经发送到了B,在这里就有了传输层,传输层的次要作用,为相互通信的利用过程,提供数据传输服务,当计算机A与计算机B通信时,在传输层上,还须要指定一个端口,来给特定的应用程序,即,传输层性能是建设端口到端口的通信,相比网络层的性能是建设主机到主机的通信。 在传输层中,次要应用TCP/UDP协定。 TCP 传输控制协议,在数据传输的时候,会建设会话,同时会把须要传输的文件进行分段,提供牢靠传输和流量管制,例如下载视频,当数据较大的时,用的是TCP协定。 UDP 协定,一个数据包就能实现数据通信,也就是说不须要建设会话,不须要流量管制,同时也是不牢靠传输,例如DNS域名解析,屏幕播送,这里应用的就是UDP协定。 应用层当数据传输到了传输层的数据之后,接下来须要解读,因为互联网开放式的,应用层作用规定利用的数据格式,例如TCP协定能够传输Email,WWW,FTP等,这些协定的数据格式。例如域名的DNS,万维网的HTTP协定,电子邮件的SMTP协定等等。这些数据单元称之为报文。 TCP/IP根底具体含意TCP/IP这里指的是一些协定群,具体来说,这里指的是IP或者ICMP,TCP,UDP,FTP等,这些协定,以及HTTP等的TCP/IP协定,等等这些协定都通通称之为TCP/IP网际协议群。在互联网进行通信的时候,须要相应的网络协议,TCP/IP本来就是为互联网开发定制的协定,这里互联网协议就是TCP/IP,TCP/IP就是互联网的一些协定。这里协定如下图所示 根本工作原理TCP/IP模型有四层,别离是应用层,网际层,网络接口层,这四层,每层别离具备不同的性能,TCP/IP协定协定是一组在不同层上的多个协定的组合,每层在实现本身的状况下间接提供服务,同时也为下层提供服务其图示如下 进行封装和拆解的过程如下图 在这里,将会退出相干的数据报,以及相干的数据信息,达到传送数据的目标。 数据包在这里,指的是TCP/IP协定数据通信中的数据单位,即,数据包, 即,从最上层,一层层的封装,直到网络层,最初借由数据链路层发送的数据单元。即。数据包为一个残缺的数据单元,如果超过了MTU,这个时候,会和多个帧组合在一起,而后造成一个残缺的数据包。 数据包的分层如下 在网络传输中,数据包由两个局部组成,一个是协定所须要用的首部,另一部分是上一层传过啦的数据,首部的构造由协定的具体标准进行定义,在数据包的首部,明确表明了协定应该如何读取数据,即,看到首部,就能明确的直到该协定所须要的信息和所须要解决的数据。 传输中和TCP和UDP端口端口,英语为port,称之为连贯端口,端口,协定端口, 位于传输层的通信协议通常须要指定端口号,例如在TCP/IP协定族之下的TCP与UDP协定。在应用层中,应用主从式架构的通信协议,在每个端口上提供多路复用服务(multiplexing service)。经由公认端口号(well-known port numbers),通常能够辨认出这个连线应用的通信协议,其中具代表性的是最根底的1024个公认端口号(well-known port numbers),例如Telnet协定默认应用23端口来连线,Secure Shell协定默认应用22端口,HTTP协定默认应用80端口,HTTPS协定默认应用443端口。 源端口号源端口号个别是由零碎本人动静生成的一个从1024-65535的号码,当一台计算机A通过网络拜访计算机B时,如果它须要对方返回数据的话,它也会随机创立一个大于1023的端口,通知B返回数据时把数据送到本人的哪个端口,而后软件开始侦听这个端口,期待数据返回。而B收到数据后会读取数据包的源端口号和目标端口号,而后记录下来,当软件创立了要返回的数据后就把原来数据包中的原端口号作为目标端口号,而把本人的端口号作为原端口号,也就是说把收到的数据包中的原和目标反过来,而后再送回A,A再反复这个过程如此重复直到数据传输实现。当数据全副传输完A就把源端口释放出来,所以同一个软件每次传输数据时不肯定是同一个源端口号。 UDP UDP全称为用户数据报协定,是一个简略的面向数据报的通信协议,位于OSI模型的传输层,UDP为不牢靠传输, 具备以下几个特点 面向无连贯 UDP不须要和TCP一样在数据发送前进行三次握手进行连贯,只是数据的搬运工,不会对数据进行相干的解决。具体来说, 在发送端,应用层把数据传输为UDP协定,UDP只会给数据减少一个UDP头标识标识是UDP协定。在接收端,网络层把数据传送给传输层,不会做任何的拼接操作。性能点具备单播,多播,播送等性能。 面向报文UDP是面向报文的,既不合并,也不拆分,因而应用程序须要抉择适合的报文,进行发送。 不可靠性UDP回产生数据的失落,因为没有相干的数据的确认过程。 传输效率高因为头部开销小,传输数据的时候报文效率相当的高。 TCP当一台计算机与另一台计算机通信的时候,两台计算机须要通信畅通,并且牢靠,这样能力保障收发数据,所以就有了一个三次握手,四次挥手,实现数据的连贯。 三次握手第一次握手(SYN=1, seq=x):客户端发送一个 TCP 的 SYN 标记地位1的包,指明客户端打算连贯的服务器的端口,以及初始序号 X,保留在包头的序列号(Sequence Number)字段里。 发送结束后,客户端进入 SYN_SEND 状态。 第二次握手(SYN=1, ACK=1, seq=y, ACKnum=x+1):服务器发回确认包(ACK)应答。即 SYN 标记位和 ACK 标记位均为1。服务器端抉择本人 ISN 序列号,放到 Seq 域里,同时将确认序号(Acknowledgement Number)设置为客户的 ISN 加1,即X+1。发送结束后,服务器端进入 SYN_RCVD 状态。 ...

December 29, 2020 · 1 min · jiezi

关于tcp-ip:本文把-TCPIP-讲绝了

一、TCP/IP模型TCP/IP协定模型(Transmission Control Protocol/Internet Protocol),蕴含了一系列形成互联网根底的网络协议,是Internet的外围协定。 基于TCP/IP的参考模型将协定分成四个档次,它们别离是链路层、网络层、传输层和应用层。下图示意TCP/IP模型与OSI模型各层的对照关系。TCP/IP协定族依照档次由上到下,层层包装。最下面的是应用层,这外面有http,ftp等等咱们相熟的协定。而第二层则是传输层,驰名的TCP和UDP协定就在这个档次。第三层是网络层,IP协定就在这里,它负责对数据加上IP地址和其余的数据以确定传输的指标。第四层是数据链路层,这个档次为待传送的数据退出一个以太网协定头,并进行CRC编码,为最初的数据传输做筹备。上图分明地示意了TCP/IP协定中每个层的作用,而TCP/IP协定通信的过程其实就对应着数据入栈与出栈的过程。入栈的过程,数据发送方每层一直地封装首部与尾部,增加一些传输的信息,确保能传输到目的地。出栈的过程,数据接管方每层一直地拆除首部与尾部,失去最终传输的数据。上图以HTTP协定为例,具体阐明。 二、数据链路层物理层负责0、1比特流与物理设施电压高下、光的闪灭之间的调换。数据链路层负责将0、1序列划分为数据帧从一个节点传输到邻近的另一个节点,这些节点是通过MAC来惟一标识的(MAC,物理地址,一个主机会有一个MAC地址)。 封装成帧: 把网络层数据报加头和尾,封装成帧,帧头中包含源MAC地址和目标MAC地址。通明传输:零比特填充、转义字符。牢靠传输: 在出错率很低的链路上很少用,然而无线链路WLAN会保障牢靠传输。过错检测(CRC):接收者检测谬误,如果发现过错,抛弃该帧。三、网络层1.IP协定 IP协定是TCP/IP协定的外围,所有的TCP,UDP,IMCP,IGMP的数据都以IP数据格式传输。要留神的是,IP不是牢靠的协定,这是说,IP协定没有提供一种数据未传播当前的解决机制,这被认为是下层协定:TCP或UDP要做的事件。 1.1 IP地址 在数据链路层中咱们个别通过MAC地址来辨认不同的节点,而在IP层咱们也要有一个相似的地址标识,这就是IP地址。 32位IP地址分为网络位和地址位,这样做能够缩小路由器中路由表记录的数目,有了网络地址,就能够限定领有雷同网络地址的终端都在同一个范畴内,那么路由表只须要保护一条这个网络地址的方向,就能够找到相应的这些终端了。 A类IP地址: 0.0.0.0~127.0.0.0B类IP地址:128.0.0.1~191.255.0.0C类IP地址:192.168.0.0~239.255.255.01.2 IP协定头这里只介绍:八位的TTL字段。这个字段规定该数据包在穿过多少个路由之后才会被摈弃。某个IP数据包每穿过一个路由器,该数据包的TTL数值就会缩小1,当该数据包的TTL成为零,它就会被主动摈弃。 这个字段的最大值也就是255,也就是说一个协定包也就在路由器外面穿行255次就会被抛弃了,依据零碎的不同,这个数字也不一样,个别是32或者是64。 2.ARP及RARP协定 ARP 是依据IP地址获取MAC地址的一种协定。 ARP(地址解析)协定是一种解析协定,原本主机是齐全不晓得这个IP对应的是哪个主机的哪个接口,当主机要发送一个IP包的时候,会首先查一下本人的ARP高速缓存(就是一个IP-MAC地址对应表缓存)。 如果查问的IP-MAC值对不存在,那么主机就向网络发送一个ARP协定播送包,这个播送包外面就有待查问的IP地址,而间接收到这份播送的包的所有主机都会查问本人的IP地址,如果收到播送包的某一个主机发现自己符合条件,那么就筹备好一个蕴含本人的MAC地址的ARP包传送给发送ARP播送的主机。 而播送主机拿到ARP包后会更新本人的ARP缓存(就是寄存IP-MAC对应表的中央)。发送播送的主机就会用新的ARP缓存数据筹备好数据链路层的的数据包发送工作。 RARP协定的工作与此相反,不做赘述。 3.ICMP协定 IP协定并不是一个牢靠的协定,它不保证数据被送达,那么,天然的,保证数据送达的工作应该由其余的模块来实现。其中一个重要的模块就是ICMP(网络管制报文)协定。ICMP不是高层协定,而是IP层的协定。 当传送IP数据包产生谬误。比方主机不可达,路由不可达等等,ICMP协定将会把错误信息封包,而后传送回给主机。给主机一个处理错误的机会,这 也就是为什么说建设在IP层以上的协定是可能做到平安的起因。 四、pingping能够说是ICMP的最驰名的利用,是TCP/IP协定的一部分。利用“ping”命令能够查看网络是否连通,能够很好地帮忙咱们剖析和断定网络故障。 例如:当咱们某一个网站上不去的时候。通常会ping一下这个网站。ping会回显出一些有用的信息。个别的信息如下:ping这个单词源自声纳定位,而这个程序的作用也的确如此,它利用ICMP协定包来侦测另一个主机是否可达。原理是用类型码为0的ICMP发申请,受到申请的主机则用类型码为8的ICMP回应。 五、TracerouteTraceroute是用来侦测主机到目标主机之间所经路由状况的重要工具,也是最便当的工具。 Traceroute的原理是十分十分的有意思,它收到到目标主机的IP后,首先给目标主机发送一个TTL=1的UDP数据包,而通过的第一个路由器收到这个数据包当前,就主动把TTL减1,而TTL变为0当前,路由器就把这个包给摈弃了,并同时产生 一个主机不可达的ICMP数据报给主机。主机收到这个数据报当前再发一个TTL=2的UDP数据报给目标主机,而后刺激第二个路由器给主机发ICMP数据 报。如此往返直到达到目标主机。这样,traceroute就拿到了所有的路由器IP。 六、TCP/UDPTCP/UDP都是是传输层协定,然而两者具备不同的个性,同时也具备不同的利用场景,上面以图表的模式比照剖析。面向报文 面向报文的传输方式是应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。因而,应用程序必须抉择适合大小的报文。若报文太长,则IP层须要分片,升高效率。若太短,会是IP太小。 面向字节流 面向字节流的话,尽管应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序看成是一连串的无构造的字节流。TCP有一个缓冲,当应用程序传送的数据块太长,TCP就能够把它划分短一些再传送。 对于拥塞管制,流量管制,是TCP的重点,前面解说。 TCP和UDP协定的一些利用什么时候应该应用TCP? 当对网络通讯品质有要求的时候,比方:整个数据要准确无误的传递给对方,这往往用于一些要求牢靠的利用,比方HTTP、HTTPS、FTP等传输文件的协定,POP、SMTP等邮件传输的协定。 什么时候应该应用UDP? 当对网络通讯品质要求不高的时候,要求网络通讯速度能尽量的快,这时就能够应用UDP。 七、DNSDNS(Domain Name System,域名零碎),因特网上作为域名和IP地址互相映射的一个分布式数据库,可能使用户更不便的拜访互联网,而不必去记住可能被机器间接读取的IP数串。通过主机名,最终失去该主机名对应的IP地址的过程叫做域名解析(或主机名解析)。DNS协定运行在UDP协定之上,应用端口号53。 八、TCP连贯的建设与终止1.三次握手 TCP是面向连贯的,无论哪一方向另一方发送数据之前,都必须先在单方之间建设一条连贯。在TCP/IP协定中,TCP协定提供牢靠的连贯服务,连贯是通过三次握手进行初始化的。三次握手的目标是同步连贯单方的序列号和确认号并替换 TCP窗口大小信息。 第一次握手:建设连贯。客户端发送连贯申请报文段,将SYN地位为1,Sequence Number为x;而后,客户端进入SYN_SEND状态,期待服务器的确认;第二次握手:服务器收到SYN报文段。服务器收到客户端的SYN报文段,须要对这个SYN报文段进行确认,设置Acknowledgment Number为x+1(Sequence Number+1);同时,本人本人还要发送SYN申请信息,将SYN地位为1,Sequence Number为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RECV状态;第三次握手:客户端收到服务器的SYN+ACK报文段。而后将Acknowledgment Number设置为y+1,向服务器发送ACK报文段,这个报文段发送结束当前,客户端和服务器端都进入ESTABLISHED状态,实现TCP三次握手。为什么要三次握手? 为了避免已生效的连贯申请报文段忽然又传送到了服务端,因此产生谬误。 具体例子:“已生效的连贯申请报文段”的产生在这样一种状况下:client收回的第一个连贯申请报文段并没有失落,而是在某个网络结点长时间的滞留了,以至延误到连贯开释当前的某个工夫才达到server。原本这是一个早已生效的报文段。但server收到此生效的连贯申请报文段后,就误认为是client再次收回的一个新的连贯申请。 于是就向client收回确认报文段,批准建设连贯。假如不采纳“三次握手”,那么只有server收回确认,新的连贯就建设了。因为当初client并没有收回建设连贯的申请,因而不会理会server的确认,也不会向server发送数据。但server却认为新的运输连贯曾经建设,并始终期待client发来数据。这样,server的很多资源就白白浪费掉了。采纳“三次握手”的方法能够避免上述景象产生。例如方才那种状况,client不会向server的确认收回确认。server因为收不到确认,就晓得client并没有要求建设连贯。” 2.四次挥手 当客户端和服务器通过三次握手建设了TCP连贯当前,当数据传送结束,必定是要断开TCP连贯的啊。那对于TCP的断开连接,这里就有了神秘的“四次离别”。 第一次离别:主机1(能够使客户端,也能够是服务器端),设置Sequence Number,向主机2发送一个FIN报文段;此时,主机1进入FIN_WAIT_1状态;这示意主机1没有数据要发送给主机2了;第二次离别:主机2收到了主机1发送的FIN报文段,向主机1回一个ACK报文段,Acknowledgment Number为Sequence Number加1;主机1进入FIN_WAIT_2状态;主机2通知主机1,我“批准”你的敞开申请;第三次离别:主机2向主机1发送FIN报文段,申请敞开连贯,同时主机2进入LAST_ACK状态;第四次离别:主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,而后主机1进入TIME_WAIT状态;主机2收到主机1的ACK报文段当前,就敞开连贯;此时,主机1期待2MSL后仍然没有收到回复,则证实Server端已失常敞开,那好,主机1也能够敞开连贯了。为什么要四次离别? ...

December 24, 2020 · 1 min · jiezi

关于tcp-ip:小菜学网络以太网帧结构

上一大节,咱们通过一个虚构的协定,初步意识了数据链路层的工作原理。数据链路层次要解决由若干主机组成的本地网络的通信问题,寻址 和 复用分用 思维在其中施展着关键作用。 数据链路层有一个十分重要的协定—— 以太网协定 。接下来,咱们一起来揭开它的神秘面纱! 应用以太网协定进行通信的主机间,必须通过某种介质间接相连。通信介质能够是实在的物理设施,如网线、网卡等;也能够是通过虚拟化技术实现的虚构设施。 以太网帧在以太网中,数据通信的根本单位是 以太网帧 ( _frame_ ),由 头部 ( header )、数据 ( data )以及 校验和 ( checksum )三局部形成: 请留神,这图中的单位为字节,而不是比特了。头部以太网帧头部蕴含 3 个字段,顺次是: 目标地址 ,长度是 6 字节,用于标记数据由哪台机器接管;源地址 ,长度也是 6 字节,用于标记数据由哪台机器发送;类型 ,长度是 2 字节,用于标记数据该如何解决, 0x0800 示意该帧数据是一个 IP 包(后续章节介绍)。除了字段长度有所拓展之外,以太网帧跟咱们虚构进去的协定一模一样。对了,咱们留神到一点小差别——在以太网帧中, 目标地址 放在最后面。 这其中有什么非凡思考吗? 的确是有的。接管方收到一个以太网帧后,最先解决 目标地址 字段。如果发现该帧不是发给本人的,前面的字段以及数据就不须要解决了。根底网络协议影响方方面面,设计时解决效率也是一个十分重要的考量。 数据数据 能够是任何须要发送的信息,长度可变, 46 至 1500 字节均可。 下层协定报文,例如 IP 包,能够作为数据封装在以太网帧中,在数据链路层中传输。因而,数据还有另一个更形象的称呼,即 负荷 ( payload )。请自行脑补数据 搭载 在以太网帧这个交通工具上旅行的画面。 校验和因为物理信号可能受到环境的烦扰,网络设备传输的比特流可能会出错。一个以太网帧从一台主机传输到另一台主机的过程中,也可能因各种因素而出错。那么当主机收到以太网帧时,如何确定它是完整无缺的呢? 答案是: 校验和 。咱们能够用诸如 循环冗余校验 ( CRC )算法,为以太网帧计算校验和。如果以太网帧在传输的过程出错,校验和将产生扭转。 留神到,以太网帧最初面有一个 4 字节字段,用于保留校验和。发送者负责为每个以太网帧计算校验和,并将计算结果填写在校验和字段中;接收者接到以太网帧后,从新计算校验和并与校验和字段进行比照;如果两个校验和不统一,阐明该帧在传输时出错了。 【小菜学网络】系列文章首发于公众号【小菜学编程】,敬请关注:

December 15, 2020 · 1 min · jiezi

关于tcp-ip:小菜学网络数据链路层概述

上一大节,咱们以两台主机为例,探讨了一个理想化的物理层模型。 当初,咱们将问题进一步延长:多台主机如何实现两两通信呢?咱们以三台主机为例进行探讨: 如上图,有 _3_ 台主机,名字别离是: _ant_ 、 _bee_ 以及 _cicada_ 。 为了实现主机间通信,咱们将三者连贯到一根共用导线。每台主机都能够扭转导线电平,也能够检测导线电平。 与此同时,假如在硬件层面,多方通信抵触仲裁机制曾经实现并且可用。 这样,是否就解决了多主机通信问题呢? 寻址假如, _ant_ 向 _bee_ 发送一个数据 11110000 (粗体)。因为导线是共享的,所有主机都能够检测到电平信号。换句话讲, _bee_ 和 _cicada_ 都会收到这个数据 11110000 ,而 _cicada_ 本不应该接管这个数据!另一方面, _bee_ 收到数据后,也不晓得数据到底是谁发给它的。 为了简化接下来的探讨,咱们省略了物理层起止管制比特 1010 和 0101 。数据不禁产生困惑:_我从哪来?去往何方?_ 为此,咱们须要引入一些比特,用来标识数据的 起源 以及 目的地 。例子中只有 3 台主机,两个比特就足以惟一确定一台主机: 机器比特ant00bee01cicada10那么,发送数据时,再加上两个比特用于示意起源主机,两个比特示意指标主机,问题不就解决了吗? 如图,主机下方的灰色比特惟一标识一台主机: ant 发送数据时,在最后面加上两个比特(红色)用于标识起源机器, 00 示意 ant ;另外两个比特(绿色)用于标识指标机器, 01 示意 bee 。 当 _bee_ 收到数据后,查看前两个比特(红色),值为 00 ,便晓得它是 _ant_ 收回来的;查看紧接着的两个比特(绿色),值为 01 ,与本人匹配上,便欢快地收下了。相同, _cicada_ 收到数据后,发现 01 和本人 10 匹配不上,便抛弃这个数据。 新引入比特所起的作用,在计算机网络中称为 寻址 。 这两个比特也就称为 地址 ,其中,红色为源地址,绿色为目标地址。 引入寻址机制后,咱们完满地解答了数据从哪来,到哪去的困惑。 复用与分用信道只有一个,然而通信需要是无穷无尽的——传输钻研数值、文件打印、即时通讯,不一而足。 如何解决这个矛盾呢?套路还是一样的——引入新的比特标识数据类型。 假如,总的通信需要就下面这 3 个。那么, 2 个额定的比特即可解决问题。 类型比特钻研数据00文件打印01即时通讯10举个例子,假如 _ant_ 向 _bee_ 上报钻研数据并打印一个文件: _bee_ 接管到数据后,依据紫色比特,决定数据如何解决。通过新引入的紫色比特,咱们在同个信道上实现了不同的通信! 接下来,从实践的视角来扫视这个场景: 信道只有一个,却要承载多样的通信工作。在发送端,通过退出紫色比特,将不同的数据通过一个共用信道发送进来,这个过程叫做 复用 ( _Multiplexing_ );在接收端,从共用信道上接收数据,而后查看紫色比特决定数据如何解决,这个过程叫做 分用 ( _Demultiplexing_ )。 在接下来的章节,咱们将看到 复用分用 的思维贯彻计算机网络的始终。 到目前为止,咱们引入了 _3_ 种不同的比特,别离是 源地址 、 目标地址 以及 数据类型 。 对于这些比特的位数以及含意的约定,便形成 网络协议 。 至此,咱们解决了多台共用信道主机间的通信问题,这相当于网络分层构造中的 数据链路层 。数据链路层负责为下层提供链路通信能力,次要作用是: ...

December 11, 2020 · 1 min · jiezi

关于tcp-ip:小菜学网络物理层概述

通信模型假如,计算机网络当初还没有被创造进去,作为计算机科学家的你,想在两台主机间传输数据,该怎么办? 这时,你可能会想到,用一根电缆将两台主机连接起来: 物理课大家都学过,电压能够分为 低电平 和 高电平 。因而,咱们能够通过管制电平高下,来达到传输信息的目标: 主机①管制电缆电平的高下, 主机②检测电平的高下,主机间数据传输便实现了! 用数学语言进一步形象:以低电平示意 0 ,高电平示意 1 。这样就失去一个理想化的信道: 通过信道,单方能够传输由 0 和 1 组成的比特流,上图中传输的比特流是 1111001011... (从右往左看)。比特流能够编码任意信息,例如:用 1111 通知对方本地开机了,用 0000 通知对方本地筹备关机了。 至此,咱们是否失去一个牢靠的比特流信道,万事具备了呢? ——实践上是这样的,但事实世界往往要比理想化的模型更简单一些。 收发管制信道是无穷无尽的,状态要么为 0 ,要么为 1 ,没有一种示意闲暇的非凡状态: 举个例子,主机①向主机②发送比特序列 101101001101 ,如下图(从右往左读)。最初一个比特是 1 ,对应的电平是高电平。发送结束后,主机①进行管制电缆电平,所以仍放弃着高电平状态: 换句话讲,信道看起来仍依照既定节奏,源源不断地发送比特 1 (灰色局部), 主机②如何检测比特流结尾呢? 咱们能够定义一些非凡的比特序列,用于标识结尾和结尾。例如, 101010 示意结尾, 010101 示意结尾: 主机①首先发送 101010 (绿色),通知主机②,它开始发数据了;主机①接着发送数据 01101011 (彩色局部);主机①最初发送 010101 (红色),通知主机②,数据发送结束;留神到,平时信道为 1 (灰色),也就是代表闲暇状态。 抵触仲裁如果两台服务器同时向信道发送数据,会产生什么事件呢? 一边发 0 ,一边发 1 ,那信道到底应该是 0 还是 1 呢? 必定抵触了嘛!有什么方法能够解决抵触吗? 计划①,引入一根新电缆,组成双电缆构造,每根电缆只负责一个方向的传输。这样一来,两个方向的传输放弃独立,互不烦扰,能够同时进行。这样的传输模式在通信畛域称为 全双工模式 。 计划②,在硬件层面实现一种仲裁机制:当检测到多台主机同时传输数据时,及时叫停,并协商哪一方先发。这样一来,信道同样反对双向通信,但不可同时进行。这种传输模式则称为 半双工模式 。 单工 ( simplex ),只反对单向通信,即从其中一端发往另一端,反之不行;半双工 ( half duplex ),反对双向通信,但不可同时进行;全双工 ( full duplex ),反对双向通信,而且能够同时进行;常见物理介质除了电信号,还有其余物理信号亦可充当通信介质。那么,常见的物理介质都有哪些呢? 电信号,例如电缆,网线就是电缆中的一种;光信号,例如光纤;电磁波,例如 WiFi ,无线网卡,蓝牙等;【小菜学网络】系列文章首发于公众号【小菜学编程】,敬请关注:

December 10, 2020 · 1 min · jiezi

关于tcp-ip:15-张图-把TCPIP-讲得一清二楚

一、TCP/IP模型TCP/IP协定模型(Transmission Control Protocol/Internet Protocol),蕴含了一系列形成互联网根底的网络协议,是Internet的外围协定。 基于TCP/IP的参考模型将协定分成四个档次,它们别离是链路层、网络层、传输层和应用层。下图示意TCP/IP模型与OSI模型各层的对照关系。TCP/IP协定族依照档次由上到下,层层包装。最下面的是应用层,这外面有http,ftp 等等咱们相熟的协定。而第二层则是传输层,驰名的TCP和UDP协定就在这个档次。第三层是网络层,IP协定就在这里,它负责对数据加上IP地址和其余的数据以确定传输的指标。第四层是数据链路层,这个档次为待传送的数据退出一个以太网协定头,并进行CRC编码,为最初的数据传输做筹备。上图分明地示意了TCP/IP协定中每个层的作用,而TCP/IP协定通信的过程其实就对应着数据入栈与出栈的过程。入栈的过程,数据发送方每层一直地封装首部与尾部,增加一些传输的信息,确保能传输到目的地。出栈的过程,数据接管方每层一直地拆除首部与尾部,失去最终传输的数据。上图以HTTP协定为例,具体阐明。 二、数据链路层物理层负责0、1比特流与物理设施电压高下、光的闪灭之间的调换。数据链路层负责将0、1序列划分为数据帧从一个节点传输到邻近的另一个节点,这些节点是通过MAC来惟一标识的(MAC,物理地址,一个主机会有一个MAC地址)。 封装成帧: 把网络层数据报加头和尾,封装成帧,帧头中包含源MAC地址和目标MAC地址。通明传输:零比特填充、转义字符。牢靠传输: 在出错率很低的链路上很少用,然而无线链路WLAN会保障牢靠传输。过错检测(CRC):接收者检测谬误,如果发现过错,抛弃该帧。三、网络层1、IP协定IP协定是TCP/IP协定的外围,所有的TCP,UDP,IMCP,IGMP的数据都以IP数据格式传输。要留神的是,IP不是牢靠的协定,这是说,IP协定没有提供一种数据未传播当前的解决机制,这被认为是下层协定:TCP或UDP要做的事件。 1.1 IP地址在数据链路层中咱们个别通过MAC地址来辨认不同的节点,而在IP层咱们也要有一个相似的地址标识,这就是IP地址。 32位IP地址分为网络位和地址位,这样做能够缩小路由器中路由表记录的数目,有了网络地址,就能够限定领有雷同网络地址的终端都在同一个范畴内,那么路由表只须要保护一条这个网络地址的方向,就能够找到相应的这些终端了。 A类IP地址: 0.0.0.0~127.0.0.0B类IP地址:128.0.0.1~191.255.0.0C类IP地址:192.168.0.0~239.255.255.0 1.2 IP协定头这里只介绍:八位的TTL字段。这个字段规定该数据包在穿过多少个路由之后才会被摈弃。某个IP数据包每穿过一个路由器,该数据包的TTL数值就会缩小1,当该数据包的TTL成为零,它就会被主动摈弃。 这个字段的最大值也就是255,也就是说一个协定包也就在路由器外面穿行255次就会被抛弃了,依据零碎的不同,这个数字也不一样,个别是32或者是64。 2、ARP及RARP协定ARP 是依据IP地址获取MAC地址的一种协定。 ARP(地址解析)协定是一种解析协定,原本主机是齐全不晓得这个IP对应的是哪个主机的哪个接口,当主机要发送一个IP包的时候,会首先查一下本人的ARP高速缓存(就是一个IP-MAC地址对应表缓存)。 如果查问的IP-MAC值对不存在,那么主机就向网络发送一个ARP协定播送包,这个播送包外面就有待查问的IP地址,而间接收到这份播送的包的所有主机都会查问本人的IP地址,如果收到播送包的某一个主机发现自己符合条件,那么就筹备好一个蕴含本人的MAC地址的ARP包传送给发送ARP播送的主机。 而播送主机拿到ARP包后会更新本人的ARP缓存(就是寄存IP-MAC对应表的中央)。发送播送的主机就会用新的ARP缓存数据筹备好数据链路层的的数据包发送工作。 RARP协定的工作与此相反,不做赘述。 3、ICMP协定IP协定并不是一个牢靠的协定,它不保证数据被送达,那么,天然的,保证数据送达的工作应该由其余的模块来实现。其中一个重要的模块就是ICMP(网络管制报文)协定。ICMP不是高层协定,而是IP层的协定。 当传送IP数据包产生谬误。比方主机不可达,路由不可达等等,ICMP协定将会把错误信息封包,而后传送回给主机。给主机一个处理错误的机会,这 也就是为什么说建设在IP层以上的协定是可能做到平安的起因。 四、pingping能够说是ICMP的最驰名的利用,是TCP/IP协定的一部分。利用“ping”命令能够查看网络是否连通,能够很好地帮忙咱们剖析和断定网络故障。 例如:当咱们某一个网站上不去的时候。通常会ping一下这个网站。ping会回显出一些有用的信息。个别的信息如下:ping这个单词源自声纳定位,而这个程序的作用也的确如此,它利用ICMP协定包来侦测另一个主机是否可达。原理是用类型码为0的ICMP发申请,受到申请的主机则用类型码为8的ICMP回应。 五、TracerouteTraceroute是用来侦测主机到目标主机之间所经路由状况的重要工具,也是最便当的工具。 Traceroute的原理是十分十分的有意思,它收到到目标主机的IP后,首先给目标主机发送一个TTL=1的UDP数据包,而通过的第一个路由器收到这个数据包当前,就主动把TTL减1,而TTL变为0当前,路由器就把这个包给摈弃了,并同时产生 一个主机不可达的ICMP数据报给主机。主机收到这个数据报当前再发一个TTL=2的UDP数据报给目标主机,而后刺激第二个路由器给主机发ICMP数据 报。如此往返直到达到目标主机。这样,traceroute就拿到了所有的路由器IP。 六、TCP/UDPTCP/UDP都是是传输层协定,然而两者具备不同的个性,同时也具备不同的利用场景,上面以图表的模式比照剖析。面向报文 面向报文的传输方式是应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。因而,应用程序必须抉择适合大小的报文。若报文太长,则IP层须要分片,升高效率。若太短,会是IP太小。 面向字节流 面向字节流的话,尽管应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序看成是一连串的无构造的字节流。TCP有一个缓冲,当应用程序传送的数据块太长,TCP就能够把它划分短一些再传送。 对于拥塞管制,流量管制,是TCP的重点,前面解说。 TCP和UDP协定的一些利用 什么时候应该应用TCP?当对网络通讯品质有要求的时候,比方:整个数据要准确无误的传递给对方,这往往用于一些要求牢靠的利用,比方HTTP、HTTPS、FTP等传输文件的协定,POP、SMTP等邮件传输的协定。 什么时候应该应用UDP?当对网络通讯品质要求不高的时候,要求网络通讯速度能尽量的快,这时就能够应用UDP。 七、DNSDNS(Domain Name System,域名零碎),因特网上作为域名和IP地址互相映射的一个分布式数据库,可能使用户更不便的拜访互联网,而不必去记住可能被机器间接读取的IP数串。通过主机名,最终失去该主机名对应的IP地址的过程叫做域名解析(或主机名解析)。DNS协定运行在UDP协定之上,应用端口号53。 八、TCP连贯的建设与终止1、三次握手TCP是面向连贯的,无论哪一方向另一方发送数据之前,都必须先在单方之间建设一条连贯。在TCP/IP协定中,TCP协定提供牢靠的连贯服务,连贯是通过三次握手进行初始化的。三次握手的目标是同步连贯单方的序列号和确认号并替换 TCP窗口大小信息。第一次握手:建设连贯。客户端发送连贯申请报文段,将SYN地位为1,Sequence Number为x;而后,客户端进入SYN_SEND状态,期待服务器的确认; 第二次握手:服务器收到SYN报文段。服务器收到客户端的SYN报文段,须要对这个SYN报文段进行确认,设置Acknowledgment Number为x+1(Sequence Number+1);同时,本人本人还要发送SYN申请信息,将SYN地位为1,Sequence Number为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RECV状态; 第三次握手:客户端收到服务器的SYN+ACK报文段。而后将Acknowledgment Number设置为y+1,向服务器发送ACK报文段,这个报文段发送结束当前,客户端和服务器端都进入ESTABLISHED状态,实现TCP三次握手。 为什么要三次握手?为了避免已生效的连贯申请报文段忽然又传送到了服务端,因此产生谬误。 具体例子:“已生效的连贯申请报文段”的产生在这样一种状况下:client收回的第一个连贯申请报文段并没有失落,而是在某个网络结点长时间的滞留了,以至延误到连贯开释当前的某个工夫才达到server。原本这是一个早已生效的报文段。但server收到此生效的连贯申请报文段后,就误认为是client再次收回的一个新的连贯申请。 于是就向client收回确认报文段,批准建设连贯。假如不采纳“三次握手”,那么只有server收回确认,新的连贯就建设了。因为当初client并没有收回建设连贯的申请,因而不会理会server的确认,也不会向server发送数据。但server却认为新的运输连贯曾经建设,并始终期待client发来数据。这样,server的很多资源就白白浪费掉了。采纳“三次握手”的方法能够避免上述景象产生。例如方才那种状况,client不会向server的确认收回确认。server因为收不到确认,就晓得client并没有要求建设连贯。” 2、四次挥手当客户端和服务器通过三次握手建设了TCP连贯当前,当数据传送结束,必定是要断开TCP连贯的啊。那对于TCP的断开连接,这里就有了神秘的“四次离别”。第一次离别:主机1(能够使客户端,也能够是服务器端),设置Sequence Number,向主机2发送一个FIN报文段;此时,主机1进入FIN_WAIT_1状态;这示意主机1没有数据要发送给主机2了; 第二次离别:主机2收到了主机1发送的FIN报文段,向主机1回一个ACK报文段,Acknowledgment Number为Sequence Number加1;主机1进入FIN_WAIT_2状态;主机2通知主机1,我“批准”你的敞开申请;第三次离别:主机2向主机1发送FIN报文段,申请敞开连贯,同时主机2进入LAST_ACK状态; 第四次离别:主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,而后主机1进入TIME_WAIT状态;主机2收到主机1的ACK报文段当前,就敞开连贯;此时,主机1期待2MSL后仍然没有收到回复,则证实Server端已失常敞开,那好,主机1也能够敞开连贯了。 为什么要四次离别?TCP协定是一种面向连贯的、牢靠的、基于字节流的运输层通信协议。TCP是全双工模式,这就意味着,当主机1收回FIN报文段时,只是示意主机1曾经没有数据要发送了,主机1通知主机2,它的数据曾经全副发送结束了;然而,这个时候主机1还是能够承受来自主机2的数据;当主机2返回ACK报文段时,示意它曾经晓得主机1没有数据发送了,然而主机2还是能够发送数据到主机1的;当主机2也发送了FIN报文段时,这个时候就示意主机2也没有数据要发送了,就会通知主机1,我也没有数据要发送了,之后彼此就会欢快的中断这次TCP连贯。 为什么要期待2MSL?MSL:报文段最大生存工夫,它是任何报文段被抛弃前在网络内的最长工夫。起因有二: 保障TCP协定的全双工连贯可能牢靠敞开保障这次连贯的反复数据段从网络中隐没第一点:如果主机1间接CLOSED了,那么因为IP协定的不可靠性或者是其它网络起因,导致主机2没有收到主机1最初回复的ACK。那么主机2就会在超时之后持续发送FIN,此时因为主机1曾经CLOSED了,就找不到与重发的FIN对应的连贯。所以,主机1不是间接进入CLOSED,而是要放弃TIME_WAIT,当再次收到FIN的时候,可能保障对方收到ACK,最初正确的敞开连贯。 ...

December 8, 2020 · 1 min · jiezi

关于tcp-ip:深入浅出-TCPIP-协议栈

TCP/IP 协定栈是一系列网络协议的总和,是形成网络通信的外围骨架,它定义了电子设备如何连入因特网,以及数据如何在它们之间进行传输。TCP/IP 协定采纳4层构造,别离是应用层、传输层、网络层和链路层,每一层都呼叫它的下一层所提供的协定来实现本人的需要。因为咱们大部分工夫都工作在应用层,上层的事件不必咱们操心;其次网络协议体系自身就很简单宏大,入门门槛高,因而很难搞分明TCP/IP的工作原理,艰深一点讲就是,一个主机的数据要通过哪些过程能力发送到对方的主机上。 接下来,咱们就来摸索一下这个过程。 0、物理介质 物理介质就是把电脑连接起来的物理伎俩,常见的有光纤、双绞线,以及无线电波,它决定了电信号(0和1)的传输方式,物理介质的不同决定了电信号的传输带宽、速率、传输间隔以及抗干扰性等等。 TCP/IP协定栈分为四层,每一层都由特定的协定与对方进行通信,而协定之间的通信最终都要转化为 0 和 1 的电信号,通过物理介质进行传输能力达到对方的电脑,因而物理介质是网络通信的基石。 上面咱们通过一张图先来大略理解一下TCP/IP协定的根本框架: 当通过http发动一个申请时,应用层、传输层、网络层和链路层的相干协定顺次对该申请进行包装并携带对应的首部,最终在链路层生成以太网数据包,以太网数据包通过物理介质传输给对方主机,对方接管到数据包当前,而后再一层一层采纳对应的协定进行拆包,最初把应用层数据交给利用程序处理。 网络通信就好比送快递,商品里面的一层层包裹就是各种协定,协定蕴含了商品信息、收货地址、收件人、联系方式等,而后还须要配送车、配送站、快递员,商品能力最终达到用户手中。 个别状况下,快递是不能中转的,须要先转发到对应的配送站,而后由配送站再进行派件。 配送车就是物理介质,配送站就是网关, 快递员就是路由器,收货地址就是IP地址,联系方式就是MAC地址。 快递员负责把包裹转发到各个配送站,配送站依据播种地址里的省市区,确认是否须要持续转发到其余配送站,当包裹达到了指标配送站当前,配送站再依据联系方式找到收件人进行派件。 有了整体概念当前,上面咱们具体理解一下各层的分工。 1、链路层 网络通信就是把有特定意义的数据通过物理介质传送给对方,单纯的发送 0 和 1 是没有意义的,要传输有意义的数据,就须要以字节为单位对 0 和 1 进行分组,并且要标识好每一组电信号的信息特色,而后依照分组的程序顺次发送。以太网规定一组电信号就是一个数据包,一个数据包被称为一帧, 制订这个规定的协定就是以太网协定。一个残缺的以太网数据包如下图所示: 整个数据帧由首部、数据和尾部三局部组成,首部固定为14个字节,蕴含了指标MAC地址、源MAC地址和类型;数据最短为46个字节,最长为1500个字节,如果须要传输的数据很长,就必须宰割成多个帧进行发送;尾部固定为4个字节,示意数据帧校验序列,用于确定数据包在传输过程中是否损坏。因而,以太网协定通过对电信号进行分组并造成数据帧,而后通过物理介质把数据帧发送给接管方。那么以太网如何来识接管方的身份呢? 以太网规协定定,接入网络的设施都必须装置网络适配器,即网卡, 数据包必须是从一块网卡传送到另一块网卡。而网卡地址就是数据包的发送地址和接管地址,也就是帧首部所蕴含的MAC地址,MAC地址是每块网卡的身份标识,就如同咱们身份证上的身份证号码,具备寰球唯一性。MAC地址采纳十六进制标识,共6个字节, 前三个字节是厂商编号,后三个字节是网卡流水号,例如4C-0F-6E-12-D2-19 有了MAC地址当前,以太网采纳播送模式,把数据包发给该子网内所有主机,子网内每台主机在接管到这个包当前,都会读取首部里的指标MAC地址,而后和本人的MAC地址进行比照,如果雷同就做下一步解决,如果不同,就抛弃这个包。 所以链路层的次要工作就是对电信号进行分组并造成具备特定意义的数据帧,而后以播送的模式通过物理介质发送给接管方。 这里分享几个视频解说、手写代码实现一个协定栈: Linux 服务器开发——tcp训练营epoll与网络io 单线程,多线程 丨手写代码丨后盾开发丨Linux网络编程丨底层原理 上_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili Linux 服务器开发——tcp训练营epoll与网络io 单线程,多线程 丨手写代码丨后盾开发丨Linux网络编程丨底层原理 下_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili Linux 服务器开发——tcp训练营,滑动窗口,udp并发,状态迁徙图,挥手中间状态丨网络底层原理丨手写代码实现网络协议栈 上_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili Linux 服务器开发——tcp训练营,滑动窗口,udp并发,状态迁徙图,挥手中间状态丨网络底层原理丨手写代码实现网络协议栈 下_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili 更多Linux C/C++后盾服务器开发知识点分享+qun720209036:内容包含C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,MongoDB,ZK,流媒体,P2P,Skynet,Linux内核,Docker,TCP/IP,协程,DPDK多个高级知识点。 2、网络层 ...

November 4, 2020 · 1 min · jiezi

关于tcp-ip:关于-TCPIP必知必会的十个问题

起源:https://juejin.im/post/684490...作者:Ruheng本文整顿了一些TCP/IP协定簇中须要必知必会的十大问题,既是面试高频问题,又是程序员必备根底素养。 TCP/IP十个问题 一、TCP/IP模型TCP/IP协定模型(Transmission Control Protocol/InternetProtocol),蕴含了一系列形成互联网根底的网络协议,是Internet的外围协定。 基于TCP/IP的参考模型将协定分成四个档次,它们别离是链路层、网络层、传输层和应用层。下图示意TCP/IP模型与OSI模型各层的对照关系。 TCP/IP协定族依照档次由上到下,层层包装。最下面的是应用层,这外面有http,ftp,等等咱们相熟的协定。而第二层则是传输层,驰名的TCP和UDP协定就在这个档次。第三层是网络层,IP协定就在这里,它负责对数据加上IP地址和其余的数据以确定传输的指标。第四层是数据链路层,这个档次为待传送的数据退出一个以太网协定头,并进行CRC编码,为最初的数据传输做筹备。 上图分明地示意了TCP/IP协定中每个层的作用,而TCP/IP协定通信的过程其实就对应着数据入栈与出栈的过程。入栈的过程,数据发送方每层一直地封装首部与尾部,增加一些传输的信息,确保能传输到目的地。出栈的过程,数据接管方每层一直地拆除首部与尾部,失去最终传输的数据。 上图以HTTP协定为例,具体阐明。 二、数据链路层物理层负责0、1比特流与物理设施电压高下、光的闪灭之间的调换。数据链路层负责将0、1序列划分为数据帧从一个节点传输到邻近的另一个节点,这些节点是通过MAC来惟一标识的(MAC,物理地址,一个主机会有一个MAC地址)。 封装成帧: 把网络层数据报加头和尾,封装成帧,帧头中包含源MAC地址和目标MAC地址。通明传输:零比特填充、转义字符。牢靠传输: 在出错率很低的链路上很少用,然而无线链路WLAN会保障牢靠传输。过错检测(CRC):接收者检测谬误,如果发现过错,抛弃该帧。三、网络层1.IP协定IP协定是TCP/IP协定的外围,所有的TCP,UDP,IMCP,IGMP的数据都以IP数据格式传输。要留神的是,IP不是牢靠的协定,这是说,IP协定没有提供一种数据未传播当前的解决机制,这被认为是下层协定:TCP或UDP要做的事件。 1.1 IP地址在数据链路层中咱们个别通过MAC地址来辨认不同的节点,而在IP层咱们也要有一个相似的地址标识,这就是IP地址。 32位IP地址分为网络位和地址位,这样做能够缩小路由器中路由表记录的数目,有了网络地址,就能够限定领有雷同网络地址的终端都在同一个范畴内,那么路由表只须要保护一条这个网络地址的方向,就能够找到相应的这些终端了。 A类IP地址: 0.0.0.0~127.0.0.0 B类IP地址:128.0.0.1~191.255.0.0 C类IP地址:192.168.0.0~239.255.255.01.2 IP协定头 这里只介绍:八位的TTL字段。这个字段规定该数据包在穿过多少个路由之后才会被摈弃。某个IP数据包每穿过一个路由器,该数据包的TTL数值就会缩小1,当该数据包的TTL成为零,它就会被主动摈弃。 这个字段的最大值也就是255,也就是说一个协定包也就在路由器外面穿行255次就会被抛弃了,依据零碎的不同,这个数字也不一样,个别是32或者是64。 2.ARP及RARP协定ARP 是依据IP地址获取MAC地址的一种协定。 ARP(地址解析)协定是一种解析协定,原本主机是齐全不晓得这个IP对应的是哪个主机的哪个接口,当主机要发送一个IP包的时候,会首先查一下本人的ARP高速缓存(就是一个IP-MAC地址对应表缓存)。 如果查问的IP-MAC值对不存在,那么主机就向网络发送一个ARP协定播送包,这个播送包外面就有待查问的IP地址,而间接收到这份播送的包的所有主机都会查问本人的IP地址,如果收到播送包的某一个主机发现自己符合条件,那么就筹备好一个蕴含本人的MAC地址的ARP包传送给发送ARP播送的主机。 而播送主机拿到ARP包后会更新本人的ARP缓存(就是寄存IP-MAC对应表的中央)。发送播送的主机就会用新的ARP缓存数据筹备好数据链路层的的数据包发送工作。 RARP协定的工作与此相反,不做赘述。 3\. ICMP协定IP协定并不是一个牢靠的协定,它不保证数据被送达,那么,天然的,保证数据送达的工作应该由其余的模块来实现。其中一个重要的模块就是ICMP(网络管制报文)协定。ICMP不是高层协定,而是IP层的协定。 当传送IP数据包产生谬误。比方主机不可达,路由不可达等等,ICMP协定将会把错误信息封包,而后传送回给主机。给主机一个处理错误的机会,这也就是为什么说建设在IP层以上的协定是可能做到平安的起因。 四、pingping能够说是ICMP的最驰名的利用,是TCP/IP协定的一部分。利用“ping”命令能够查看网络是否连通,能够很好地帮忙咱们剖析和断定网络故障。 例如:当咱们某一个网站上不去的时候。通常会ping一下这个网站。ping会回显出一些有用的信息。个别的信息如下: ping这个单词源自声纳定位,而这个程序的作用也的确如此,它利用ICMP协定包来侦测另一个主机是否可达。原理是用类型码为0的ICMP发请求,受到申请的主机则用类型码为8的ICMP回应。 ping程序来计算间隔时间,并计算有多少个包被送达。用户就能够判断网络大抵的状况。咱们能够看到, ping给进去了传送的工夫和TTL的数据。 五、TracerouteTraceroute是用来侦测主机到目标主机之间所经路由状况的重要工具,也是最便当的工具。 Traceroute的原理是十分十分的有意思,它收到到目标主机的IP后,首先给目标主机发送一个TTL=1的UDP数据包,而通过的第一个路由器收到这个数据包当前,就主动把TTL减1,而TTL变为0当前,路由器就把这个包给摈弃了,并同时产生一个主机不可达的ICMP数据报给主机。主机收到这个数据报当前再发一个TTL=2的UDP数据报给目标主机,而后刺激第二个路由器给主机发ICMP数据报。如此往返直到达到目标主机。这样,traceroute就拿到了所有的路由器IP。 六、TCP/UDPTCP/UDP都是是传输层协定,然而两者具备不同的个性,同时也具备不同的利用场景,上面以图表的模式比照剖析。 面向报文面向报文的传输方式是应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。因而,应用程序必须抉择适合大小的报文。若报文太长,则IP层须要分片,升高效率。若太短,会是IP太小。 面向字节流面向字节流的话,尽管应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序看成是一连串的无构造的字节流。TCP有一个缓冲,当应用程序传送的数据块太长,TCP就能够把它划分短一些再传送。 对于拥塞管制,流量管制,是TCP的重点,前面解说。 TCP和UDP协定的一些利用 什么时候应该应用TCP?当对网络通讯品质有要求的时候,比方:整个数据要准确无误的传递给对方,这往往用于一些要求牢靠的利用,比方HTTP、HTTPS、FTP等传输文件的协定,POP、SMTP等邮件传输的协定。 什么时候应该应用UDP?当对网络通讯品质要求不高的时候,要求网络通讯速度能尽量的快,这时就能够应用UDP。 七、DNSDNS(Domain NameSystem,域名零碎),因特网上作为域名和IP地址互相映射的一个分布式数据库,可能使用户更不便的拜访互联网,而不必去记住可能被机器间接读取的IP数串。通过主机名,最终失去该主机名对应的IP地址的过程叫做域名解析(或主机名解析)。DNS协定运行在UDP协定之上,应用端口号53。 八、TCP连贯的建设与终止1.三次握手TCP是面向连贯的,无论哪一方向另一方发送数据之前,都必须先在单方之间建设一条连贯。在TCP/IP协定中,TCP协定提供牢靠的连贯服务,连贯是通过三次握手进行初始化的。三次握手的目标是同步连贯单方的序列号和确认号并替换TCP窗口大小信息。 第一次握手: 建设连贯。客户端发送连贯申请报文段,将SYN地位为1,SequenceNumber为x;而后,客户端进入SYN_SEND状态,期待服务器的确认; 第二次握手: 服务器收到SYN报文段。服务器收到客户端的SYN报文段,须要对这个SYN报文段进行确认,设置Acknowledgment Number为x+1(Sequence Number+1);同时,本人本人还要发送SYN申请信息,将SYN地位为1,SequenceNumber为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RECV状态; 第三次握手: 客户端收到服务器的SYN+ACK报文段。而后将AcknowledgmentNumber设置为y+1,向服务器发送ACK报文段,这个报文段发送结束当前,客户端和服务器端都进入ESTABLISHED状态,实现TCP三次握手。 ...

October 31, 2020 · 1 min · jiezi

关于tcp-ip:这次一定让你记住-TCP-三次握手四手挥手

TCP协定全称为:Transmission Control Protocol,是一种面向链接、保障数据传输平安、牢靠的数据传输协定。为了确保数据的牢靠传输,不仅须要对收回的每个字节进行编号确认,还须要验证每一个数据包的有效性。每个TCP数据包是关闭在IP包中的,每个一IP包的前面紧跟着的是TCP头,TCP报文格式如下: 源端口和目标端口字段 TCP源端口(Source Port):源计算机上的应用程序的端口号,占 16 位。TCP目标端口(Destination Port):指标计算机的应用程序端口号,占 16 位。序列号字段 CP序列号(Sequence Number):占 32 位。它示意本报文段所发送数据的第一个字节的编号。在 TCP 连贯中,所传送的字节流的每一个字节都会按程序编号。当SYN标记不为1时,这是以后数据分段第一个字母的序列号;如果SYN的值是1时,这个字段的值就是初始序列值(ISN),用于对序列号进行同步。这时,第一个字节的序列号比这个字段的值大1,也就是ISN加1。 确认号字段 TCP 确认号(Acknowledgment Number,ACK Number):占 32 位。它示意接管方冀望收到发送方下一个报文段的第一个字节数据的编号。其值是接管计算机行将接管到的下一个序列号,也就是下一个接管到的字节的序列号加1。 数据偏移字段 TCP 首部长度(Header Length):数据偏移是指数据段中的“数据”局部起始处间隔 TCP 数据段起始处的字节偏移量,占 4 位。其实这里的“数据偏移”也是在确定 TCP 数据段头局部的长度,通知接收端的应用程序,数据从何处开始。 保留字段 保留(Reserved):占 4 位。为 TCP 未来的倒退预留空间,目前必须全副为 0。 标记位字段 CWR(Congestion Window Reduce):拥塞窗口缩小标记,用来表明它接管到了设置 ECE 标记的 TCP 包。并且,发送方收到音讯之后,通过减小发送窗口的大小来升高发送速率。ECE(ECN Echo):用来在 TCP 三次握手时表明一个 TCP 端是具备 ECN 性能的。在数据传输过程中,它也用来表明接管到的 TCP 包的 IP 头部的 ECN 被设置为 11,即网络线路拥挤。URG(Urgent):示意本报文段中发送的数据是否蕴含紧急数据。URG=1 时示意有紧急数据。当 URG=1 时,前面的紧急指针字段才无效。ACK:示意后面的确认号字段是否无效。ACK=1 时示意无效。只有当 ACK=1 时,后面的确认号字段才无效。TCP 规定,连贯建设后,ACK 必须为 1。PSH(Push):通知对方收到该报文段后是否立刻把数据推送给下层。如果值为 1,示意该当立刻把数据提交给下层,而不是缓存起来。RST:示意是否重置连贯。如果 RST=1,阐明 TCP 连贯呈现了严重错误(如主机解体),必须开释连贯,而后再从新建设连贯。SYN:在建设连贯时应用,用来同步序号。当 SYN=1,ACK=0 时,示意这是一个申请建设连贯的报文段;当 SYN=1,ACK=1 时,示意对方批准建设连贯。SYN=1 时,阐明这是一个申请建设连贯或批准建设连贯的报文。只有在前两次握手中 SYN 才为 1。FIN:标记数据是否发送结束。如果 FIN=1,示意数据曾经发送实现,能够开释连贯。窗口大小字段 ...

October 12, 2020 · 2 min · jiezi

关于tcp-ip:最详细的Linux-TCPIP-协议栈源码分析

一.linux内核网络栈代码的筹备常识1. linux内核ipv4网络局部分层构造: BSD socket层: 这一部分解决BSD socket相干操作,每个socket在内核中以struct socket构造体现。这一部分的文件 次要有:/net/socket.c /net/protocols.c etc INET socket层:BSD socket是个能够用于各种网络协议的接口,而当用于tcp/ip,即建设了AF_INET模式的socket时, 还须要保留些额定的参数,于是就有了struct sock构造。文件次要 有:/net/ipv4/protocol.c /net/ipv4/af_inet.c /net/core/sock.c etc TCP/UDP层:解决传输层的操作,传输层用struct inet_protocol和struct proto两个构造示意。文件次要 有:/net/ipv4/udp.c /net/ipv4/datagram.c /net/ipv4/tcp.c /net/ipv4/tcp_input.c /net/ipv4//tcp_output.c /net/ipv4/tcp_minisocks.c /net/ipv4/tcp_output.c /net/ipv4/tcp_timer.c etc IP层:解决网络层的操作,网络层用struct packet_type构造示意。文件次要有:/net/ipv4/ip_forward.c ip_fragment.c ip_input.c ip_output.c etc. 数据链路层和驱动程序:每个网络设备以struct net_device示意,通用的解决在dev.c中,驱动程序都在/driver/net目 录下。 2. 两台主机建设udp通信所走过的函数列表 ^ | sys_read fs/read_write.c | sock_read net/socket.c | sock_recvmsg net/socket.c | inet_recvmsg net/ipv4/af_inet.c | udp_recvmsg net/ipv4/udp.c skb_recv_datagram net/core/datagram.csock_queue_rcv_skb include/net/sock.hudp_queue_rcv_skb net/ipv4/udp.cudp_rcv net/ipv4/udp.cip_local_deliver_finish net/ipv4/ip_input.cip_local_deliver net/ipv4/ip_input.cip_recv net/ipv4/ip_input.cnet_rx_action net/dev.cnetif_rx net/dev.cel3_rx driver/net/3c309.cel3_interrupt driver/net/3c309.c========================== | sys_write fs/read_write.c | sock_writev net/socket.c | sock_sendmsg net/socket.c | inet_sendmsg net/ipv4/af_inet.c | udp_sendmsg net/ipv4/udp.c | ip_build_xmit net/ipv4/ip_output.c | output_maybe_reroute net/ipv4/ip_output.c | ip_output net/ipv4/ip_output.c | ip_finish_output net/ipv4/ip_output.c ...

October 12, 2020 · 3 min · jiezi

关于tcp-ip:TCP三次握手调优

TCP(Transmission Control Protocol)传输控制协议是一种面向连贯的、牢靠的、基于字节流的传输层协定。从TCP的定义中能够看出,TCP是面向连贯的牢靠的通信形式,连贯单方都须要确定各自的连贯通道都是OK的。三次握手的目标就是为了确定各自的通道是OK的,同时告诉对方本人的起始SEQ。当客户端调用connect函数时便发送了SYN报文同时告诉对方本人的起始SEQ,从而发动第一次握手,客户端进入SYN_SENT状态;服务端收到SYN报文后,返回SYN+ACK报文到客户端同时告诉对方本人的起始SEQ,从而发动了第二次握手,服务端进入SYN_RCV状态;客户端收到服务端的SYN+ACK后,回复ACK报文,从而发动第三次握手,客户端进入ESTABLISHED状态;服务端收到ACK报文后服务端进入ESTABLISHED状态。自此三次握手就实现了,其流程图如下: TCP的三次握手过程如下: 客户端调优1、当客户端发动第一次握手的时候,如果迟迟收不到对方的应答,那么客户端会重试,重试的次数由/proc/sys/net/ipv4/tcp_syn_retries管制,默认值是5,重试距离是1,2,4,8,16,32,总共须要破费63s。能够依据客户端与服务端的网络情况以及服务端的负载,适当升高重试次数调小,如2次,从而出现异常的时候,客户端能够尽快感知到异样。 服务端调优1、当服务端发动第二次握手的时候,如果迟迟收不到对方的应答,那么服务端也会重试,重试的次数由/proc/sys/net/ipv4/tcp_synack_retries管制,默认值是5,重试距离是1,2,4,8,16,32,总共须要破费63s。同样的,如果客户端与服务器的网络情况挺好的,能够把重试次数调小。2、当服务端发动第二次握手后,会把连贯放入到半连贯队列,队列的大小由/proc/sys/net/ipv4/tcp_max_syn_backlog管制,默认大小是2048。当这个队列满时,服务器将无奈建设连贯。那么咱们怎么晓得这个队列是否有溢出呢?能够通过如下的命令看到 netstat -s | grep 'SYNs to LISTEN'75571 SYNs to LISTEN sockets ignored这个是个累计值,如果发现这个值一直的变大,能够把这个队列调大。同时还能够设置/proc/sys/net/ipv4/tcp_syncookies=1,关上tcp_syncookies性能。tcp_syncookies能够取如下的值:A. tcp_syncookies=0时,敞开syncookies性能,当半连贯队列满时,服务端将无奈建设连贯;B. tcp_syncookies=1时,当半连贯队列满时,服务端将启用syncookies性能;C. tcp_syncookies=2时,服务端将始终启用syncookies性能。tcp_syncookies的次要工作流程如下:服务端接管到SYN报文并返回TSYN+ACK报文时,不插入半连贯队列,而是依据这个SYN报文计算出一个cookie值。这个cookie作为将要返回的SYN ACK报文的初始序列号。当客户端返回一个ACK报文时,依据报文头信息计算cookie,与返回的确认序列号(初始序列号+1)进行比照,如果雷同,则是一个失常连贯,而后将连贯放入accept队列。如果通过netstat -lap发现SYN_RCV状态的连接不断的增长,那么就须要通过抓包工具剖析是不是产生了syn泛洪攻打,如果产生了泛洪攻打,须要通过防火墙阻止这种连贯。所谓的SYN泛洪攻打利用的是TCP的三次握手机制,攻打端利用伪造的IP地址向被攻打端发出请求,而被攻打端收回的响应报文将永远发送不到目的地,那么被攻打端在期待敞开这个连贯的过程中耗费了资源,如果有大量的这种连贯,主机资源将被耗尽,从而达到攻打的目标。3、当服务端收到第三次握手的ACK应答报文后,服务端会把连贯放入accept队列,accept队列由listen()函数传入的参数(参数的值能够通过ss -lnt命令的输入“Send-Q”列查看)与/proc/sys/net/core/somaxconn独特管制,取2者的小值。能够通过如下的命令查看是否由溢出: netstat -s | grep overflow75571 times the listen queue of a socket overflowed如果这个值一直的变大,阐明应用程序没有及时的调用accept函数接管连贯,能够先调高上文进步的2个参数。accept队列满后是否抛弃连贯,是由参数/proc/sys/net/ipv4/tcp_abort_on_overflow管制,默认是0。如果设置为1并且溢出,则发送RST报文敞开连贯。个别倡议设置为0,因为抛弃后,客户端如果发送了数据+ACK,因为等不到应答,那么就会反复发送数据+ACK,当服务端接管到ACK后,如果accept队列不满了,那么连贯就建设了。可见tcp_abort_on_overflow=0,能够进步TCP连贯建设胜利的概率。只有accept队列长期溢出的时候,才设置tcp_abort_on_overflow=1。4、另外还能够关上TFO性能,进步TCP连贯建设的效率,TFO详见文档:https://tools.ietf.org/html/r...https://www.cnblogs.com/passz...

October 5, 2020 · 1 min · jiezi

关于tcp-ip:TCP报文格式

TCP(Transmission Control Protocol)传输控制协议是一种面向连贯的、牢靠的、基于字节流的传输层协定。报文格式如下:1、源端口号、目标端口号同IP数据报中的源IP与目标IP惟一确定一条TCP连贯。2、序号(4字节)与确认序号(4字节):是TCP牢靠传输的要害局部。序号是本报文段发送的数据组的第一个字节的序号。在TCP传送的流中,每一个字节一个序号。确认序号,即ACK,指明下一个期待收到的字节序号,表明该序号之前的所有数据曾经正确无误的收到。确认序号只有当ACK标记为1时才无效。比方建设连贯时,SYN报文的ACK标记位为0。3、首部长度(4位):以4字节为单位,因为首部可能含有可选项内容,因而TCP报头的长度是不确定的,报头不蕴含任何可选字段则长度为20字节,4位首部长度字段所能示意的最大值为1111,10进制为15,15*4 = 60,故报头最大长度为60字节。4、保留:为未来定义新的用处保留,个别置0。5、管制位:URG ACK PSH RST SYN FIN,共6个,每一个标记位示意一个管制性能。1)URG:紧急指针标记,为1时示意紧急指针无效,为0则疏忽紧急指针。2)ACK:确认序号标记,为1时示意确认号无效,为0示意报文中不含确认信息,疏忽确认号字段。3)PSH:push标记,为1示意是带有push标记的数据,批示接管方在接管到该报文段当前,应尽快将这个报文段交给应用程序,而不是在缓冲区排队。4)RST:重置连贯标记,用于重置因为主机解体或其余起因而呈现谬误的连贯。或者用于回绝非法的报文段和回绝连贯申请。5)SYN:同步序号,用于建设连贯过程。6)FIN:finish标记,用于开释连贯,为1时示意发送方曾经没有数据发送了,即敞开本方数据流。6、窗口:滑动窗口大小,用来告知发送端承受端的缓存大小,以此管制发送端发送数据的速率,从而达到流量管制。窗口大小是一个16bit字段,因此窗口大小最大为65535。7、校验和:奇偶校验,此校验和是对整个的 TCP 报文段,包含 TCP 头部和 TCP 数据,以 16 位字进行计算所得。由发送端计算和存储,并由接收端进行验证。8、紧急指针:只有当 URG 标记置 1 时紧急指针才无效。紧急指针是一个正的偏移量,和顺序号字段中的值相加示意紧急数据最初一个字节的序号。 TCP 的紧急形式是发送端向另一端发送紧急数据的一种形式。9、选项和填充:最常见的可选字段是最长报文大小,又称为MSS(Maximum Segment Size),每个连贯方通常都在通信的第一个报文段(为建设连贯而设置SYN标记为1的那个段)中指明这个选项,它示意本端所能承受的最大报文段的长度。另外也会保留2个4字节的工夫戳,包含本方的以后工夫戳与对端的承受到的最新工夫戳。选项长度不肯定是32位的整数倍,所以要加填充位,即在这个字段中退出额定的零,以保障TCP头是32的整数倍。

October 5, 2020 · 1 min · jiezi

关于tcp-ip:建议收藏TCP协议面试灵魂12-问

起源 | urlify.cn/rqumIn先亮出这篇文章的思维导图: TCP 作为传输层的协定,是一个IT工程师素养的体现,也是面试中常常被问到的知识点。在此,我将 TCP 外围的一些问题梳理了一下,心愿能帮到各位。 001. 能不能说一说 TCP 和 UDP 的区别?首先概括一下根本的区别: TCP是一个面向连贯的、牢靠的、基于字节流的传输层协定。 而UDP是一个面向无连贯的传输层协定。(就这么简略,其它TCP的个性也就没有了)。 具体来剖析,和 UDP 相比,TCP 有三大外围个性: 面向连贯。所谓的连贯,指的是客户端和服务器的连贯,在单方相互通信之前,TCP 须要三次握手建设连贯,而 UDP 没有相应建设连贯的过程。可靠性。TCP 花了十分多的功夫保障连贯的牢靠,这个可靠性体现在哪些方面呢?一个是有状态,另一个是可管制。TCP 会精准记录哪些数据发送了,哪些数据被对方接管了,哪些没有被接管到,而且保障数据包按序达到,不容许半点过错。这是有状态。 当意识到丢包了或者网络环境不佳,TCP 会依据具体情况调整本人的行为,管制本人的发送速度或者重发。这是可管制。 相应的,UDP 就是无状态, 不可控的。 面向字节流。UDP 的数据传输是基于数据报的,这是因为仅仅只是继承了 IP 层的个性,而 TCP 为了保护状态,将一个个 IP 包变成了字节流。002: 说说 TCP 三次握手的过程?为什么是三次而不是两次、四次?恋爱模仿以谈恋爱为例,两个人可能在一起最重要的事件是首先确认各自爱和被爱的能力。接下来咱们以此来模仿三次握手的过程。 第一次: 男: 我爱你。 女方收到。 由此证明男方领有爱的能力。 第二次: 女: 我收到了你的爱,我也爱你。 男方收到。 OK,当初的状况阐明,女方领有爱和被爱的能力。 第三次: 男: 我收到了你的爱。 女方收到。 当初可能保障男方具备被爱的能力。 由此残缺地确认了单方爱和被爱的能力,两人开始一段苦涩的恋情。 实在握手当然刚刚那段属于扯淡,不代表自己价值观,目标是让大家了解整个握手过程的意义,因为两个过程十分类似。对应到 TCP 的三次握手,也是须要确认单方的两样能力: 发送的能力和接管的能力。于是便会有上面的三次握手的过程: 从最开始单方都处于CLOSED状态。而后服务端开始监听某个端口,进入了LISTEN状态。 而后客户端被动发动连贯,发送 SYN , 本人变成了SYN-SENT状态。 ...

August 10, 2020 · 5 min · jiezi

快速理解TCPIP三次握手与四次挥手

TCP/IP三次握手TCP建立连接为什么是三次握手,而不是两次或四次?TCP,名为传输控制协议,是一种可靠的传输层协议,IP协议号为6。顺便说一句,原则上任何数据传输都无法确保绝对可靠,三次握手只是确保可靠的基本需要。 对应为客户端与服务器之间的通信:于是有了以下对话:我:1+1等于几?她:2,2+2等于几?我:4 首先两个人约定协议1.感觉网络情况不对的时候,任何一方都可以发起询问2.任何情况下,若发起询问后5秒还没收到回复,则认为网络不通3.网络不通的情况下等1min路由器之后再发起询问 对于我而言,发起 “1+1等于几”的询问后 若5s内没有收到回复,则认为网络不通若收到回复,则我确认①我能听到她的消息 ②她能听到我的消息,然后回复她的问题的答案对于她而言,当感觉网络情况不对的时候 若没有收到我的询问,则她发起询问若收到“1+1等于几”,则她确认 ①她可以听到我的消息,然后回复我的问题的答案和她的问题“2,2+2等于几”若5s内没有收到我的回复“4”,则她确认 ②我听不见她的消息若5s内收到了我的回复“4”,则她确认 ②我可以听见她的消息这样,如果上面的对话得以完成,就证明双方都可以确认自己可以听到对方的声音,对方也可以听到自己的声音! 这个解释足够简单了吧!接下来我们看四次挥手。 TCP/IP四次挥手三次握手耳熟能详,四次挥手估计就..所谓四次挥手(Four-Way Wavehand)即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发,整个流程如下图所示: 服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。简单点说,当被动方收到主动方的FIN报文通知时,它仅仅表示主动方没有数据再发送给被动方了。但未必被动方所有的数据都完整的发送给了主动方,所以被动方不会马上关闭SOCKET,它可能还需要发送一些数据给主动方后,再发送FIN报文给主动方,告诉主动方同意关闭连接,所以这里的ACK报文和FIN报文多数情况下都是分开发送的。

July 11, 2019 · 1 min · jiezi

TCPIP五层模型和OSI七层模型

TCP/IP五层模型和OSI七层模型Tcp/IP模型的各层的作用主要是为传输的数据添加不同数据协议格式的头部和尾部信息,对传输的数据进行包装和编码,最终通过物理层以二进制码的形式进行传输。例如:0010101010...,下图说明了TCP/IP模型和OSI模型的对应关系: OSI七层模型解释

May 4, 2019 · 1 min · jiezi

我们应该相信那些狂热的天才工程师么

先声明一下,一个人逻辑好,数学好,不代表这个人是理性的。理性的意思是一个人能正确的认识现实情况,从而设定合理的目标。我国现实案例一则 狂热工程师的特点不断的添加特性他们觉得比特币脚本太简陋了,于是发明图灵完整的EVM虚拟机。后来者觉得EVM太low了于是引入更加高级的WASM,还有更狂热的把lua脚本都塞进来。 用区块链解决一切问题觉得区块链能解决很多问题,所以一定要搞一个特别酷的通用平台,如果只是专注转账简直不好意思见人。 藐视专业相信自己比数学家更厉害,能发明安全的哈希算法。 藐视市场相信一个商品的价格可以由数学公式来决定,而不是市场。 专断口口声声说自己是去中心化系统,却可以发出指令封禁别人账户。被人诟病之后,以打破之前的承诺为代价,直接强行部署新规则。 不承认现实情况设计一个高速的layer2,example1, example2, example3,却无法为比特币实现onchain或者offchain服务。 滥用比喻他们将自己定义为区块链届的TCP/IP层 根本不酷炫的实用主义开发者是如何做的收敛比特币直到今天也不是图灵完整。但是通过扎实的开发工作,实现了若干次稳妥而扎实的进步,支持了闪电网络。 专注没有那么大的野心,直到今天,比特币和闪电网络依然是点对点电子现金系统。 谦逊不自己发明新算法,不使用未经验证的算法。 不忘初心比特币和闪电网络一直以来都从permissionless出发,保证资金安全的前提下尝试提高性能。 承认有些问题无法彻底解决比特币就是51%算力说了算,BFT就是2f+1说了算。坏人太多怎么办?先打倒坏人。 TCP/IP是牛逼专家闭门想出来么?这里有一个帖子很有意思,简单说结论: 在计算机科学发展的历史上,一直就存在着实用化和理论上更为先进这两个声音的不断争执。而每每都是那个取得比较合适的折衷并且能真正符合实际需要的那一方才能胜出。

April 24, 2019 · 1 min · jiezi

TCP报文发送的那些事

今天我们来总结学习一下TCP发送报文的相关知识,主要包括发送报文的步骤,MSS,滑动窗口和Nagle算法。发送报文 该节主要根据陶辉大神的系列文章总结而来。如下图所示,我们一起来看一下TCP发送报文时操作系统内核都做了那些事情。其中有些概念在接下来的小节中会介绍。 首先,用户程序在用户态调用send方法来发送一段较长的数据。然后send函数调用内核态的tcp_sendmsg方法进行处理。 主要注意的是,send方法返回成功,内核也不一定真正将IP报文都发送到网络中,也就是说内核发送报文和send方法是不同步的。所以,内核需要将用户态内存中的发送数据,拷贝到内核态内存中,不依赖于用户态内存,使得进程可以快速释放发送数据占用的用户态内存。 在拷贝过程中,内核将待发送的数据,按照MSS来划分成多个尽量接近MSS大小的分片,放到这个TCP连接对应的tcp_write_queue发送队列中。 内核中为每个TCP连接分配的内核缓存,也就是tcp_write_queue队列的大小是有限的。当没有多余的空间来复制用户态的待发送数据时,就需要调用sk_stream_wait_memory方法来等待空间,等到滑动窗口移动,释放出一些缓存出来(收到发送报文相对应的ACK后,不需要再缓存该已发送出的报文,因为既然已经确认对方收到,就不需要重发,可以释放缓存)。 当这个套接字是阻塞套接字时,等待的超时时间就是SO_SNDTIMEO选项指定的发送超时时间。如果这个套接字是非阻塞套接字,则超时时间就是0。也就是说,sk_stream_wait_memory对于非阻塞套接字会直接返回,并将 errno错误码置为EAGAIN。 我们假定使用了阻塞套接字,且等待了足够久的时间,收到了对方的ACK,滑动窗口释放出了缓存。所以,可以将剩下的用户态数据都组成MSS报文拷贝到内核态的缓存队列中。 最后,调用tcp_push等方法,它最终会调用IP层的方法来发送tcp_write_queue队列中的报文。注意的是,IP层方法返回时,也不意味着报文发送了出去。 在发送函数处理过程中,Nagle算法、滑动窗口、拥塞窗口都会影响发送操作。MTU和MSS 我们都知道TCP/IP架构有五层协议,低层协议的规则会影响到上层协议,比如说数据链路层的最大传输单元MTU和传输层TCP协议的最大报文段长度MSS。 数据链路层协议会对网络分组的长度进行限制,也就是不能超过其规定的MTU,例如以太网限制为1500字节,802.3限制为1492字节。但是,需要注意的时,现在有些网卡具备自动分包功能,所以也可以传输远大于MTU的帧。 网络层的IP协议试图发送报文时,若报文的长度大于MTU限制,就会被分成若干个小于MTU的报文,每个报文都会有独立的IP头部。IP协议能自动获取所在局域网的MTU值,然后按照这个MTU来分片。IP协议的分片机制对于传输层是透明的,接收方的IP协议会根据收到的多个IP包头部,将发送方IP层分片出的IP包重组为一个消息。 这种IP层的分片效率是很差的,因为首先做了额外的分片操作,然后所有分片都到达后,接收方才能重组成一个包,其中任何一个分片丢失了,都必须重发所有分片。 所以,TCP层为了避免IP层执行数据报分片定义了最大报文段长度MSS。在TCP建立连接时会通知各自期望接收到的MSS的大小。 需要注意的是MSS的值是预估值。两台主机只是根据其所在局域网的计算MSS,但是TCP连接上可能会穿过许多中间网络,这些网络分别具有不同的数据链路层,导致问题。比如说,若中间途径的MTU小于两台主机所在的网络MTU时,选定的MSS仍然太大了,会导致中间路由器出现IP层的分片或者直接返回错误(设置IP头部的DF标志位)。 比如阿里中间件的这篇文章(链接不见的话,请看文末)所说,当上述情况发生时,可能会导致卡死状态,比如scp的时候进度卡着不懂,或者其他更复杂操作的进度卡死。滑动窗口 IP层协议属于不可靠的协议,IP层并不关心数据是否发送到了接收方,TCP通过确认机制来保证数据传输的可靠性。 除了保证数据必定发送到对端,TCP还要解决包乱序(reordering)和流控的问题。包乱序和流控会涉及滑动窗口和接收报文的out_of_order队列,另外拥塞控制算法也会处理流控,详情请看TCP拥塞控制算法简介。 TCP头里有一个字段叫Window,又叫Advertised-Window,这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,否则会导致接收端处理不过来。 我们可以将发送的数据分为以下四类,将它们放在时间轴上统一观察。Sent and Acknowledged: 表示已经发送成功并已经被确认的数据,比如图中的前31个字节的数据Send But Not Yet Acknowledged:表示发送但没有被确认的数据,数据被发送出去,没有收到接收端的ACK,认为并没有完成发送,这个属于窗口内的数据。Not Sent,Recipient Ready to Receive:表示需要尽快发送的数据,这部分数据已经被加载到缓存等待发送,也就是发送窗口中。接收方ACK表示有足够空间来接受这些包,所以发送方需要尽快发送这些包。Not Sent,Recipient Not Ready to Receive: 表示属于未发送,同时接收端也不允许发送的,因为这些数据已经超出了发送端所接收的范围 除了四种不同范畴的数据外,我们可以看到上边的示意图中还有三种窗口。Window Already Sent:已经发送了,但是没有收到ACK,和Send But Not Yet Acknowledged部分重合。Usable Window : 可用窗口,和Not Sent,Recipient Ready to Receive部分重合Send Window: 真正的窗口大小。建立连接时接收方会告知发送方自己能够处理的发送窗口大小,同时在接收过程中也不断的通告能处理窗口的大小,来实时调节。 下面,我们来看一下滑动窗口的滑动。下图是滑动窗口滑动的示意图。 当发送方收到发送数据的确认消息时,会移动发送窗口。比如上图中,接收到36字节的确认,将其之前的5个字节都移除发送窗口,然后46-51的字节发出,最后将52到56的字节加入到可用窗口。 下面我们来看一下整体的示意图。 图片来源为tcpipguide. client端窗口中不同颜色的矩形块代表的含义和上边滑动窗口示意图中相同。我们只简单看一下第二三四步。接收端发送的TCP报文window为260,表示发送窗口减少100,可以发现黑色矩形缩短了,也就是发送窗口减少了100。并且ack为141,所以发送端将140个字节的数据从发送窗口中移除,这些数据从Send But Not Yet Acknowledged变为Sent and Acknowledged,也就是从蓝色变成紫色。然后发送端发送180字节的数据,就有180字节的数据从Not Sent,Recipient Ready to Receive变为Send But Not Yet Acknowledged,也就是从绿色变为蓝色。Nagle算法 上述滑动窗口会出现一种Silly Window Syndrome的问题,当接收端来不及取走Receive Windows里的数据,会导致发送端的发送窗口越来越小。到最后,如果接收端腾出几个字节并告诉发送端现在有几个字节的window,而我们的发送端会义无反顾地发送这几个字节。 只为了发送几个字节,要加上TCP和IP头的40多个字节。这样,效率太低,就像你搬运物品,明明一次可以全部搬完,但是却偏偏一次只搬一个物品,来回搬多次。 为此,TCP引入了Nagle算法。应用进程调用发送方法时,可能每次只发送小块数据,造成这台机器发送了许多小的TCP报文。对于整个网络的执行效率来说,小的TCP报文会增加网络拥塞的可能。因此,如果有可能,应该将相临的TCP报文合并成一个较大的TCP报文(当然还是小于MSS的)发送。 Nagle算法的规则如下所示(可参考tcp_output.c文件里tcp_nagle_check函数注释):如果包长度达到MSS,则允许发送;如果该包含有FIN,则允许发送;设置了TCP_NODELAY选项,则允许发送;未设置TCP_CORK选项时,若所有发出去的小数据包(包长度小于MSS)均被确认,则允许发送;上述条件都未满足,但发生了超时(一般为200ms),则立即发送。 当对请求的时延非常在意且网络环境非常好的时候(例如同一个机房内),Nagle算法可以关闭。使用TCP_NODELAY套接字选项就可以关闭Nagle算法 订阅最新文章,欢迎关注我的微信公众号个人博客: Remcarpediem个人微信公众号:参考阿里中间件 http://jm.taobao.org/2017/07/… ...

April 18, 2019 · 1 min · jiezi

对libuv的C++封装

libuv_cpp11是一个基于libuv的C++封装网络库。接口较为简单易用,并对libuv一些特性做了扩展及优化。压力测试结果稳定、高效。未发现内存泄漏及崩溃。为什么需要封装libuv截至目前,C++没有标准网络库,常见的有ACE和boost.asio。ACE较为庞大臃肿,封装复杂,个人不推荐。boost.asio是boost库的一部分,需要依赖boost的部分实现,使用asio需要在项目引入较为庞大的boost库。而C语言的网络库主要有libevent、libev及libuv。libuv是nodejs的底层,较为成熟。所以如果在项目需要一套轻量级,且没有太多依赖的网络组件,最好的办法,还是自己封装一套。libuv_cpp11功能简介1.实现了C++功能的回调首先libuv是一个C语言库,意味着回调函数是C语言的回调,所以直接使用libuv网络消息回调,相关对象必须是全局的或者static对象,这是令人难以容忍的。这里通过libuv的用户数据功能实现了C++风格的回调,回调函数可以类成员函数,或者lambda。同时封装了TcpServer及TcpClient等类,简化编程。2.对线程安全做了优化libuv是一个非线程安全的库,跨线程发送数据数不允许的。libuv_cpp11中实现了线程安全的跨线程write数据操作。基于libuv的async异步机制实现,同时在跨线程调用时候会检查当前调用线程,如果在该loop线程中则直接发送,减少了不必要的性能损耗。实现如下:void uv::EventLoop::runInThisLoop(const std::function<void()>& func){ if (nullptr == func) return; if (isRunInLoopThread()) { func(); return; } async_->runInThisLoop(func);}同时libuv的aysnc接口存在多次调用一次执行的可能(问题),比如有些操作需要在回调里面释放数据,这样就会内存泄漏。libuv_cpp11中的Async类优化这个问题,确保每次调用一定会被执行。3.实现了定时器及时间轮对libuv定时器做了一层封装,并实现了一个时间复杂度O(1)的时间轮,用于检测心跳超时。4.实现整包发送/接受协议机制实现了ListBuffer和CycleBuffe两种缓存机制,用于解决TCP的粘包及残包。数据会重新组成完整的包数据用于读取。性能测试显示CycleBuffe会损失20%~30%的性能。5日志接口libuv_cpp11没有实现日志功能,但是保留了接口,可以注册/绑定到自定义日志库中使用。libuv_cpp11的使用详见example文件夹:https://github.com/wlgq2/libu…

March 19, 2019 · 1 min · jiezi

通过TCP与简易内存数据库进行数据交互的实现

目的运用TCP相关原理,实现一个简单的server端和client端的数据库交互程序,可以将client端输入的指令被server端解析,将返回信息又返送给client端。之前的简单内存数据库的实现:T-Tree、T*-Tree的理解与简单内存数据库的实现TCP/IP,socket等相关计算机网络原理七层网络模型七层网络模型TCP/IPTCP/IP是互联网协议簇的统称。TCP-transmission control protocal-传输控制协议IP-Internet Protocal-因特网协议UDP 是User Datagram Protocol 是无连接类型的传输层协议,socket是什么socket是对TCP/IP协议的封装,socket翻译为套接字,socket是一个接口/插座。TCPIP 是Socket的一种实现,Socket并不只有TCP/IP。两种socket:stream sockets,datagram socketsocket其实不止两种。stream socket:串流式socket。是有连接类型的,网页浏览器所使用的 HTTP 协议是用 stream sockets 取得网页。datagram socket:讯息式socket。是无连接类型的,用于语音通信,视频传输较多。TCP serverserver端socket()函数#include <sys/types.h>#include <sys/socket.h>int socket(int domain, int type, int protocol);domain一个地址描述。目前仅支持AF_INET格式,也就是说ARPA Internet地址格式。type指定socket类型。新套接口的类型描述类型,如TCP(SOCK_STREAM)和UDP(SOCK_DGRAM)。常用的socket类型有,SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等等。protocol指定协议。套接口所用的协议。如不想指定,可用0。常用的协议有,IPPROTO_TCP、IPPROTO_UDP、IPPROTO_STCP、IPPROTO_TIPC等,它们分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。bind()函数#include <sys/types.h>#include <sys/socket.h>int bind(int sockfd, struct sockaddr *my_addr, int addrlen);bind()将一本地地址与一socket捆绑.sockfdsockfd 是 socket() 传回的 socket file descriptor。my_addrmy_addr是指向包含你的地址资料丶名称及 IP address 的 struct sockaddr 之指针。addrlenaddrlen 是以 byte 为单位的地址长度。connect#include <sys/types.h>#include <sys/socket.h>int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);connect()从client端连接到server端listen(),accept()int listen(int sockfd, int backlog);—————————————————————–#include <sys/types.h>#include <sys/socket.h>int accept(int sockfd, struct sockaddr *addr, socklen_t addrlen);send(),recv()int send(int sockfd, const void msg, int len, int flags);————————————————————int recv(int sockfd, void buf, int len, int flags);send() 会返回实际有送出的 byte 数,可能会少与所要传送的数目。recv()若返回0,则说明远端那边已经关闭了你的连接close()close(sockfd);关闭socket。一个tcp server 的示例代码:#include <netdb.h> #include <netinet/in.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #define MAX 80 #define PORT 8080 #define SA struct sockaddr // Function designed for chat between client and server. void func(int sockfd) { char buff[MAX]; int n; // infinite loop for chat for (;;) { bzero(buff, MAX); // read the message from client and copy it in buffer read(sockfd, buff, sizeof(buff)); // print buffer which contains the client contents printf(“From client: %s\t To client : “, buff); bzero(buff, MAX); n = 0; // copy server message in the buffer while ((buff[n++] = getchar()) != ‘\n’) ; // and send that buffer to client write(sockfd, buff, sizeof(buff)); // if msg contains “Exit” then server exit and chat ended. if (strncmp(“exit”, buff, 4) == 0) { printf(“Server Exit…\n”); break; } } } // Driver function int main() { int sockfd, connfd, len; struct sockaddr_in servaddr, cli; // socket create and verification sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { printf(“socket creation failed…\n”); exit(0); } else printf(“Socket successfully created..\n”); bzero(&servaddr, sizeof(servaddr)); // assign IP, PORT servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(PORT); // Binding newly created socket to given IP and verification if ((bind(sockfd, (SA)&servaddr, sizeof(servaddr))) != 0) { printf(“socket bind failed…\n”); exit(0); } else printf(“Socket successfully binded..\n”); // Now server is ready to listen and verification if ((listen(sockfd, 5)) != 0) { printf(“Listen failed…\n”); exit(0); } else printf(“Server listening..\n”); len = sizeof(cli); // Accept the data packet from client and verification connfd = accept(sockfd, (SA)&cli, &len); if (connfd < 0) { printf(“server acccept failed…\n”); exit(0); } else printf(“server acccept the client…\n”); // Function for chatting between client and server func(connfd); // After chatting close the socket close(sockfd); } client端一个tcp client的示例代码:// Write CPP code here #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #define MAX 80 #define PORT 8080 #define SA struct sockaddr void func(int sockfd) { char buff[MAX]; int n; for (;;) { bzero(buff, sizeof(buff)); printf(“Enter the string : “); n = 0; while ((buff[n++] = getchar()) != ‘\n’) ; write(sockfd, buff, sizeof(buff)); bzero(buff, sizeof(buff)); read(sockfd, buff, sizeof(buff)); printf(“From Server : %s”, buff); if ((strncmp(buff, “exit”, 4)) == 0) { printf(“Client Exit…\n”); break; } } } int main() { int sockfd, connfd; struct sockaddr_in servaddr, cli; // socket create and varification sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { printf(“socket creation failed…\n”); exit(0); } else printf(“Socket successfully created..\n”); bzero(&servaddr, sizeof(servaddr)); // assign IP, PORT servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = inet_addr(“127.0.0.1”); servaddr.sin_port = htons(PORT); // connect the client socket to server socket if (connect(sockfd, (SA)&servaddr, sizeof(servaddr)) != 0) { printf(“connection with the server failed…\n”); exit(0); } else printf(“connected to the server..\n”); // function for chat func(sockfd); // close the socket close(sockfd); } 通过TCP与简易内存数据库的数据交互为了让client端和server中的内存数据库,通信如果server端和client建立连接之后则进入一个大循环,大循环的退出条件是client端发去“EXIT”,client端随即断开连接。通过TCP和内存数据库通信的所以代码所有代码都在github里:slarsar/ttree_mmdb_tcp_server_client参考GeeksforGeeksBeej’s Guide to Network Programming 简体中文版 ...

March 18, 2019 · 3 min · jiezi

TCP/IP的底层队列

自从上次学习了TCP/IP的拥塞控制算法后,我越发想要更加深入的了解TCP/IP的一些底层原理,搜索了很多网络上的资料,看到了陶辉大神关于高性能网络编程的专栏,收益颇多。今天就总结一下,并且加上自己的一些思考。 我自己比较了解Java语言,对Java网络编程的理解就止于Netty框架的使用。Netty的源码贡献者Norman Maurer对于Netty网络开发有过一句建议,“Never block the event loop, reduce context-swtiching”。也就是尽量不要阻塞IO线程,也尽量减少线程切换。我们今天只关注前半句,对这句话感兴趣的同学可以看一下[蚂蚁通信框架实践](https://mp.weixin.qq.com/s/JR…。 为什么不能阻塞读取网络信息的IO线程呢?这里就要从经典的网络C10K开始理解,服务器如何支持并发1万请求。C10K的根源在于网络的IO模型。Linux 中网络处理都用同步阻塞的方式,也就是每个请求都分配一个进程或者线程,那么要支持1万并发,难道就要使用1万个线程处理请求嘛?这1万个线程的调度、上下文切换乃至它们占用的内存,都会成为瓶颈。解决C10K的通用办法就是使用I/O 多路复用,Netty就是这样。 Netty有负责服务端监听建立连接的线程组(mainReactor)和负责连接读写操作的IO线程组(subReactor),还可以有专门处理业务逻辑的Worker线程组(ThreadPool)。三者相互独立,这样有很多好处。一是有专门的线程组负责监听和处理网络连接的建立,可以防止TCP/IP的半连接队列(sync)和全连接队列(acceptable)被占满。二是IO线程组和Worker线程分开,双方并行处理网络I/O和业务逻辑,可以避免IO线程被阻塞,防止TCP/IP的接收报文的队列被占满。当然,如果业务逻辑较少,也就是IO 密集型的轻计算业务,可以将业务逻辑放在IO线程中处理,避免线程切换,这也就是Norman Maurer话的后半部分。 TCP/IP怎么就这么多队列啊?今天我们就来细看一下TCP/IP的几个队列,包括建立连接时的半连接队列(sync),全连接队列(accept)和接收报文时的receive、out_of_order、prequeue以及backlog队列。建立连接时的队列 如上图所示,这里有两个队列:syns queue(半连接队列)和accept queue(全连接队列)。三次握手中,服务端接收到客户端的SYN报文后,把相关信息放到半连接队列中,同时回复SYN+ACK给客户端。 第三步的时候服务端收到客户端的ACK,如果这时全连接队列没满,那么从半连接队列拿出相关信息放入到全连接队列中,否则按tcp_abort_on_overflow的值来执行相关操作,直接抛弃或者过一段时间在重试。接收报文时的队列 相比于建立连接,TCP在接收报文时的处理逻辑更为复杂,相关的队列和涉及的配置参数更多。 应用程序接收TCP报文和程序所在服务器系统接收网络里发来的TCP报文是两个独立流程。二者都会操控socket实例,但是会通过锁竞争来决定某一时刻由谁来操控,由此产生很多不同的场景。例如,应用程序正在接收报文时,操作系统通过网卡又接收到报文,这时该如何处理?若应用程序没有调用read或者recv读取报文时,操作系统收到报文又会如何处理? 我们接下来就以三张图为主,介绍TCP接收报文时的三种场景,并在其中介绍四个接收相关的队列。接收报文场景一上图是TCP接收报文场景一的示意图。操作系统首先接收报文,存储到socket的receive队列,然后用户进程再调用recv进行读取。1) 当网卡接收报文并且判断为TCP协议时,经过层层调用,最终会调用到内核的tcp_v4_rcv方法。由于当前TCP要接收的下一个报文正是S1,所以tcp_v4_rcv函数将其直接加入到receive队列中。receive队列是将已经接收到的TCP报文,去除了TCP头部、排好序放入的、用户进程可以直接按序读取的队列。由于socket不在用户进程上下文中(也就是没有用户进程在读socket),并且我们需要S1序号的报文,而恰好收到了S1报文,因此,它进入了receive队列。2) 接收到S3报文,由于TCP要接收的下一个报文序号是S2,所以加入到out_of_order队列,所有乱序的报文会放在这里。3) 接着,收到了TCP期望的S2报文,直接进入recevie队列。由于此时out_of_order队列不为空,需要检查一下。4) 每次向receive队列插入报文时都会检查out_of_order队列,由于接收到S2报文后,期望的的序号为S3,所以out_of_order队列中的S3报文会被移到receive队列。5) 用户进程开始读取socket,先在进程中分配一块内存,然后调用read或者recv方法。socket有一系列的具有默认值的配置属性,比如socket默认是阻塞式的,它的SO_RCVLOWAT属性值默认为1。当然,recv这样的方法还会接收一个flag参数,它可以设置为MSG_WAITALL、MSG_PEEK、MSG_TRUNK等等,这里我们假定为最常用的0。进程调用了recv方法。6) 调用tcp_recvmsg方法7) tcp_recvmsg方法会首先锁住socket。socket是可以被多线程使用的,而且操作系统也会使用,所以必须处理并发问题。要操控socket,就先获取锁。8) 此时,receive队列已经有3个报文了,将第一个报文拷贝到用户态内存中,由于第五步中socket的参数并没有带MSG_PEEK,所以将第一个报文从队列中移除,从内核态释放掉。反之,MSG_PEEK标志位会导致receive队列不会删除报文。所以,MSG_PEEK主要用于多进程读取同一套接字的情形。9) 拷贝第二个报文,当然,执行拷贝前都会检查用户态内存的剩余空间是否足以放下当前这个报文,不够时会直接返回已经拷贝的字节数。10) 拷贝第三个报文。11) receive队列已经为空,此时会检查SO_RCVLOWAT这个最小阈值。如果已经拷贝字节数小于它,进程会休眠,等待更多报文。默认的SO_RCVLOWAT值为1,也就是读取到报文就可以返回。12) 检查backlog队列,backlog队列是用户进程正在拷贝数据时,网卡收到的报文会进这个队列。如果此时backlog队列有数据,就顺带处理下。backlog队列是没有数据的,因此释放锁,准备返回用户态。13) 用户进程代码开始执行,此时recv等方法返回的就是从内核拷贝的字节数。接收报文场景二 第二张图给出了第二个场景,这里涉及了prequeue队列。用户进程调用recv方法时,socket队列中没有任何报文,而socket是阻塞的,所以进程睡眠了。然后操作系统收到了报文,此时prequeue队列开始产生作用。该场景中,tcp_low_latency为默认的0,套接字socket的SO_RCVLOWAT是默认的1,仍然是阻塞socket,如下图。 其中1,2,3步骤的处理和之前一样。我们直接从第四步开始。4) 由于此时receive,prequeue和backlog队列都为空,所以没有拷贝一个字节到用户内存中。而socket的配置要求至少拷贝SO_RCVLOWAT也就是1字节的报文,因此进入阻塞式套接字的等待流程。最长等待时间为SO_RCVTIMEO指定的时间。socket在进入等待前会释放socket锁,会使第五步中,新来的报文不再只能进入backlog队列。5) 接到S1报文,将其加入prequeue队列中。6) 插入到prequeue队列后,会唤醒在socket上休眠的进程。7) 用户进程被唤醒后,重新获取socket锁,此后再接收到的报文只能进入backlog队列。8) 进程先检查receive队列,当然仍然是空的;再去检查prequeue队列,发现有报文S1,正好是正在等待序号的报文,于是直接从prequeue队列中拷贝到用户内存,再释放内核中的这个报文。9) 目前已经拷贝了一个字节的报文到用户内存,检查这个长度是否超过了最低阈值,也就是len和SO_RCVLOWAT的最小值。10) 由于SO_RCVLOWAT使用了默认值1,拷贝字节数大于最低阈值,准备返回用户态,顺便会查看一下backlog队列中是否有数据,此时没有,所以准备放回,释放socket锁。11) 返回用户已经拷贝的字节数。接收报文场景三 在第三个场景中,系统参数tcp_low_latency为1,socket上设置了SO_RCVLOWAT属性值。服务器先收到报文S1,但是其长度小于SO_RCVLOWAT。用户进程调用recv方法读取,虽然读取到了一部分,但是没有到达最小阈值,所以进程睡眠了。与此同时,在睡眠前接收的乱序的报文S3直接进入backlog队列。然后,报文S2到达,由于没有使用prequeue队列(因为设置了tcp_low_latency),而它起始序号正是下一个待拷贝的值,所以直接拷贝到用户内存中,总共拷贝字节数已满足SO_RCVLOWAT的要求!最后在返回用户前把backlog队列中S3报文也拷贝给用户。1) 接收到报文S1,正是准备接收的报文序号,因此,将它直接加入到有序的receive队列中。2) 将系统属性tcp_low_latency设置为1,表明服务器希望程序能够及时的接收到TCP报文。用户调用的recv接收阻塞socket上的报文,该socket的SO_RCVLOWAT值大于第一个报文的大小,并且用户分配了足够大的长度为len的内存。3) 调用tcp_recvmsg方法来完成接收工作,先锁住socket。4) 准备处理内核各个接收队列中的报文。5) receive队列中有报文可以直接拷贝,其大小小于len,直接拷贝到用户内存。6) 在进行第五步的同时,内核又接收到S3报文,此时socket被锁,报文直接进入backlog队列。这个报文并不是有序的。7) 在第五步时,拷贝报文S1到用户内存,它的大小小于SO_RCVLOWAT的值。由于socket是阻塞型,所以用户进程进入睡眠状态。进入睡眠前,会先处理backlog队列的报文。因为S3报文是失序的,所以进入out_of_order 队列。用户进程进入休眠状态前都会先处理一下backlog队列。8) 进程休眠,直到超时或者receive队列不为空。9) 内核接收到报文S2。注意,此时由于打开了tcp_low_latency标志位,所以报文是不会进入prequeue队列等待进程处理。10) 由于报文S2正是要接收的报文,同时,一个用户进程在休眠等待该报文,所以直接将报文S2拷贝到用户内存。11) 每处理完一个有序报文后,无论是拷贝到receive队列还是直接复制到用户内存,都会检查out_of_order队列,看看是否有报文可以处理。报文S3拷贝到用户内存,然后唤醒用户进程。12) 唤醒用户进程。13) 此时会检查已拷贝的字节数是否大于SO_RCVLOWAT,以及backlog队列是否为空。两者皆满足,准备返回。 总结一下四个队列的作用。receive队列是真正的接收队列,操作系统收到的TCP数据包经过检查和处理后,就会保存到这个队列中。backlog是“备用队列”。当socket处于用户进程的上下文时(即用户正在对socket进行系统调用,如recv),操作系统收到数据包时会将数据包保存到backlog队列中,然后直接返回。prequeue是“预存队列”。当socket没有正在被用户进程使用时,也就是用户进程调用了read或者recv系统调用,但是进入了睡眠状态时,操作系统直接将收到的报文保存在prequeue中,然后返回。out_of_order是“乱序队列”。队列存储的是乱序的报文,操作系统收到的报文并不是TCP准备接收的下一个序号的报文,则放入out_of_order队列,等待后续处理。后记 如果你觉得本篇文章对你有帮助,请点个赞。同时欢迎订阅本人的微信公众号。个人博客: Remcarpediem参考http://www.voidcn.com/article…https://blog.csdn.net/russell...https://ylgrgyq.github.io/201…

March 10, 2019 · 1 min · jiezi

TCP 拥塞控制算法

最近花了些时间在学习TCP/IP协议上,首要原因是由于本人长期以来对TCP/IP的认识就只限于三次握手四次分手上,所以希望深入了解一下。再者,TCP/IP和Linux系统层级的很多设计都可以用于中间件系统架构上,比如说TCP 拥塞控制算法也可以用于以响应时间来限流的中间件。更深一层,像TCP/IP协议这种基础知识和原理性的技术,都是经过长时间的考验的,都是前人智慧的结晶,可以给大家很多启示和帮助。 本文中会出现一些缩写,因为篇幅问题,无法每个都进行解释,如果你不明白它的含义,请自己去搜索了解,做一个主动寻求知识的人。 TCP协议有两个比较重要的控制算法,一个是流量控制,另一个就是阻塞控制。 TCP协议通过滑动窗口来进行流量控制,它是控制发送方的发送速度从而使接受者来得及接收并处理。而拥塞控制是作用于网络,它是防止过多的包被发送到网络中,避免出现网络负载过大,网络拥塞的情况。 拥塞算法需要掌握其状态机和四种算法。拥塞控制状态机的状态有五种,分别是Open,Disorder,CWR,Recovery和Loss状态。四个算法为慢启动,拥塞避免,拥塞发生时算法和快速恢复。Congestion Control State Machine 和TCP一样,拥塞控制算法也有其状态机。当发送方收到一个Ack时,Linux TCP通过状态机(state)来决定其接下来的行为,是应该降低拥塞窗口cwnd大小,或者保持cwnd不变,还是继续增加cwnd。如果处理不当,可能会导致丢包或者超时。1 Open状态 Open状态是拥塞控制状态机的默认状态。这种状态下,当ACK到达时,发送方根据拥塞窗口cwnd(Congestion Window)是小于还是大于慢启动阈值ssthresh(slow start threshold),来按照慢启动或者拥塞避免算法来调整拥塞窗口。2 Disorder状态 当发送方检测到DACK(重复确认)或者SACK(选择性确认)时,状态机将转变为Disorder状态。在此状态下,发送方遵循飞行(in-flight)包守恒原则,即一个新包只有在一个老包离开网络后才发送,也就是发送方收到老包的ACK后,才会再发送一个新包。3 CWR状态 发送方接收到一个拥塞通知时,并不会立刻减少拥塞窗口cwnd,而是每收到两个ACK就减少一个段,直到窗口的大小减半为止。当cwnd正在减小并且网络中有没有重传包时,这个状态就叫CWR(Congestion Window Reduced,拥塞窗口减少)状态。CWR状态可以转变成Recovery或者Loss状态。4 Recovery状态 当发送方接收到足够(推荐为三个)的DACK(重复确认)后,进入该状态。在该状态下,拥塞窗口cnwd每收到两个ACK就减少一个段(segment),直到cwnd等于慢启动阈值ssthresh,也就是刚进入Recover状态时cwnd的一半大小。 发送方保持 Recovery 状态直到所有进入 Recovery状态时正在发送的数据段都成功地被确认,然后发送方恢复成Open状态,重传超时有可能中断 Recovery 状态,进入Loss状态。5 Loss状态 当一个RTO(重传超时时间)到期后,发送方进入Loss状态。所有正在发送的数据标记为丢失,拥塞窗口cwnd设置为一个段(segment),发送方再次以慢启动算法增大拥塞窗口cwnd。 Loss 和 Recovery 状态的区别是:Loss状态下,拥塞窗口在发送方设置为一个段后增大,而 Recovery 状态下,拥塞窗口只能被减小。Loss 状态不能被其他的状态中断,因此,发送方只有在所有 Loss 开始时正在传输的数据都得到成功确认后,才能退到 Open 状态。四大算法 拥塞控制主要是四个算法:1)慢启动,2)拥塞避免,3)拥塞发生,4)快速恢复。这四个算法不是一天都搞出来的,这个四算法的发展经历了很多时间,到今天都还在优化中。慢热启动算法 – Slow Start 所谓慢启动,也就是TCP连接刚建立,一点一点地提速,试探一下网络的承受能力,以免直接扰乱了网络通道的秩序。 慢启动算法:1) 连接建好的开始先初始化拥塞窗口cwnd大小为1,表明可以传一个MSS大小的数据。2) 每当收到一个ACK,cwnd大小加一,呈线性上升。3) 每当过了一个往返延迟时间RTT(Round-Trip Time),cwnd大小直接翻倍,乘以2,呈指数让升。4) 还有一个ssthresh(slow start threshold),是一个上限,当cwnd >= ssthresh时,就会进入“拥塞避免算法”(后面会说这个算法)拥塞避免算法 – Congestion Avoidance 如同前边说的,当拥塞窗口大小cwnd大于等于慢启动阈值ssthresh后,就进入拥塞避免算法。算法如下:1) 收到一个ACK,则cwnd = cwnd + 1 / cwnd2) 每当过了一个往返延迟时间RTT,cwnd大小加一。 过了慢启动阈值后,拥塞避免算法可以避免窗口增长过快导致窗口拥塞,而是缓慢的增加调整到网络的最佳值。拥塞状态时的算法 一般来说,TCP拥塞控制默认认为网络丢包是由于网络拥塞导致的,所以一般的TCP拥塞控制算法以丢包为网络进入拥塞状态的信号。对于丢包有两种判定方式,一种是超时重传RTO[Retransmission Timeout]超时,另一个是收到三个重复确认ACK。 超时重传是TCP协议保证数据可靠性的一个重要机制,其原理是在发送一个数据以后就开启一个计时器,在一定时间内如果没有得到发送数据报的ACK报文,那么就重新发送数据,直到发送成功为止。 但是如果发送端接收到3个以上的重复ACK,TCP就意识到数据发生丢失,需要重传。这个机制不需要等到重传定时器超时,所以叫做快速重传,而快速重传后没有使用慢启动算法,而是拥塞避免算法,所以这又叫做快速恢复算法。 超时重传RTO[Retransmission Timeout]超时,TCP会重传数据包。TCP认为这种情况比较糟糕,反应也比较强烈:由于发生丢包,将慢启动阈值ssthresh设置为当前cwnd的一半,即ssthresh = cwnd / 2.cwnd重置为1进入慢启动过程 最为早期的TCP Tahoe算法就只使用上述处理办法,但是由于一丢包就一切重来,导致cwnd又重置为1,十分不利于网络数据的稳定传递。 所以,TCP Reno算法进行了优化。当收到三个重复确认ACK时,TCP开启快速重传Fast Retransmit算法,而不用等到RTO超时再进行重传:cwnd大小缩小为当前的一半ssthresh设置为缩小后的cwnd大小然后进入快速恢复算法Fast Recovery。快速恢复算法 – Fast Recovery TCP Tahoe是早期的算法,所以没有快速恢复算法,而Reno算法有。在进入快速恢复之前,cwnd和ssthresh已经被更改为原有cwnd的一半。快速恢复算法的逻辑如下:cwnd = cwnd + 3 MSS,加3 MSS的原因是因为收到3个重复的ACK。重传DACKs指定的数据包。如果再收到DACKs,那么cwnd大小增加一。如果收到新的ACK,表明重传的包成功了,那么退出快速恢复算法。将cwnd设置为ssthresh,然后进入拥塞避免算法。 如图所示,第五个包发生了丢失,所以导致接收方接收到三次重复ACK,也就是ACK5。所以将ssthresh设置当当时cwnd的一半,也就是6/2 = 3,cwnd设置为3 + 3 = 6。然后重传第五个包。当收到新的ACK时,也就是ACK11,则退出快速恢复阶段,将cwnd重新设置为当前的ssthresh,也就是3,然后进入拥塞避免算法阶段。后记 本文为大家大致描述了TCP拥塞控制的一些机制,但是这些拥塞控制还是有很多缺陷和待优化的地方,业界也在不断推出新的拥塞控制算法,比如说谷歌的BBR。这些我们后续也会继续探讨,请大家继续关注。个人博客:Remcarpediem引用Congestion Control in Linux TCPTCP BBR算法与Reno/CUBIC的对比 ...

March 1, 2019 · 1 min · jiezi

温习一下网络基础TCP/IP

通常使用的网络(包括互联网)是在TCP/IP协议族的基础上运作的,而HTTP属于它内部的一个子集~先来一波书上的知识做个小笔记~而TCP/IP协议是计算机与网络设备互相通讯的规则;简单的说从电缆的规格到IP地址的选定方法等与互联网相关联的协议集合起来总称TCP/IP通过TCP/IP进行分层管理TCP/IP协议族按照层次分为4层:应用层、传输层、网络层、数据链路层应用层: 决定了向用户提供应用服务时通信的活动;HTTP协议也处于该层;DNS服务同样处于这层传输层:提供处于网络连接中的两台计算机之间的数据传输;在传输层有两个性质不同的协议:TCP 和 UDP网络层: 处理网络上流动的数据包;IP协议链路层/网络接口层:处理连接网络的硬件设备以上四层的通讯顺讯用HTTP来举例:发送端输入URL发送请求(http协议,http请求)查看web页面其中IP协议的作用是把数据包传送给对方;确保准确的传送的两个重要条件是IP地址和MAC地址;MAC地址是指网卡所属的固定地址接下来,要敲小黑板划重点了常常放在口中的TCP连接3次握手和四次挥手,到底是怎么实现的呢?emmm…确实每次都是话到口边却说不来了下面来打包一下,做个一次性总结:为了准确无误的将数据送到目标地,连接时TCP采用3次握手策略,握手中使用了TCP的标志:syn和ack发送端首先发送带syn同步序列标志的数据包给接收端接收端收到后回传一个带有syn/ack(确认)标志的数据包表示传达确认信息发送端收到后,在发送一个带有ack(确认)标志的数据包表示握手结束当客户端不想再连接了,那么它接下来就要向服务端发起结束请求了,但是这不是谈恋爱,不是一方说分手就能分手的。因为客户端发起结束请求,并不代表服务端此刻已经把所有的数据都返给客户端了;所以就有了四次挥手, 目的也是为了确保客户端与服务端的数据传输是完整的首先是客户端发起的结束请求,也就是发送FIN报文;此时的客户端进入FIN_WAIT_1状态服务端收到FIN后,发送一个ACK给客户端,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),服务端进入CLOSE_WAIT状态服务端发送一个FIN,用来关闭服务端到客户端的数据传送,服务端进入LAST_ACK状太客户端收到FIN后,客户端进入TIME_WAIT状态,接着发送一个ACK给服务端,确认序号为收到序号+1,服务端进入CLOSED状态,完成四次挥手。HTTP协议与其他协议之间的关系DNS服务:解析对应域名的IPhttp协议:生成针对目标Web服务器的HTTP请求报文TCP协议: 为了方便数据传递,将HTTP请求报文分割成报文段,把每个报文段可靠的传送给对方;或者接收对方的报文段,重组成报文IP协议:搜索对方的地址,一边中转一边传送

February 26, 2019 · 1 min · jiezi

“三次握手,四次挥手”你真的懂吗?

记得刚毕业找工作面试的时候,经常会被问到:你知道“3次握手,4次挥手”吗?这时候我会“胸有成竹”地“背诵”前期准备好的“答案”,第一次怎么怎么,第二次……答完就没有下文了,面试官貌似也没有深入下去的意思,深入下去我也不懂,皆大欢喜!作为程序员,要有“刨根问底”的精神。知其然,更要知其所以然。这篇文章希望能抽丝剥茧,还原背后的原理。什么是“3次握手,4次挥手”TCP是一种面向连接的单播协议,在发送数据前,通信双方必须在彼此间建立一条连接。所谓的“连接”,其实是客户端和服务器的内存里保存的一份关于对方的信息,如ip地址、端口号等。TCP可以看成是一种字节流,它会处理IP层或以下的层的丢包、重复以及错误问题。在连接的建立过程中,双方需要交换一些连接的参数。这些参数可以放在TCP头部。TCP提供了一种可靠、面向连接、字节流、传输层的服务,采用三次握手建立一个连接。采用4次挥手来关闭一个连接。TCP服务模型在了解了建立连接、关闭连接的“三次握手和四次挥手”后,我们再来看下TCP相关的东西。一个TCP连接由一个4元组构成,分别是两个IP地址和两个端口号。一个TCP连接通常分为三个阶段:启动、数据传输、退出(关闭)。当TCP接收到另一端的数据时,它会发送一个确认,但这个确认不会立即发送,一般会延迟一会儿。ACK是累积的,一个确认字节号N的ACK表示所有直到N的字节(不包括N)已经成功被接收了。这样的好处是如果一个ACK丢失,很可能后续的ACK就足以确认前面的报文段了。一个完整的TCP连接是双向和对称的,数据可以在两个方向上平等地流动。给上层应用程序提供一种双工服务。一旦建立了一个连接,这个连接的一个方向上的每个TCP报文段都包含了相反方向上的报文段的一个ACK。序列号的作用是使得一个TCP接收端可丢弃重复的报文段,记录以杂乱次序到达的报文段。因为TCP使用IP来传输报文段,而IP不提供重复消除或者保证次序正确的功能。另一方面,TCP是一个字节流协议,绝不会以杂乱的次序给上层程序发送数据。因此TCP接收端会被迫先保持大序列号的数据不交给应用程序,直到缺失的小序列号的报文段被填满。TCP头部源端口和目的端口在TCP层确定双方进程,序列号表示的是报文段数据中的第一个字节号,ACK表示确认号,该确认号的发送方期待接收的下一个序列号,即最后被成功接收的数据字节序列号加1,这个字段只有在ACK位被启用的时候才有效。当新建一个连接时,从客户端发送到服务端的第一个报文段的SYN位被启用,这称为SYN报文段,这时序列号字段包含了在本次连接的这个方向上要使用的第一个序列号,即初始序列号ISN,之后发送的数据是ISN加1,因此SYN位字段会消耗一个序列号,这意味着使用重传进行可靠传输。而不消耗序列号的ACK则不是。头部长度(图中的数据偏移)以32位字为单位,也就是以4bytes为单位,它只有4位,最大为15,因此头部最大长度为60字节,而其最小为5,也就是头部最小为20字节(可变选项为空)。ACK —— 确认,使得确认号有效。RST —— 重置连接(经常看到的reset by peer)就是此字段搞的鬼。SYN —— 用于初如化一个连接的序列号。FIN —— 该报文段的发送方已经结束向对方发送数据。当一个连接被建立或被终止时,交换的报文段只包含TCP头部,而没有数据。状态转换三次握手和四次挥手的状态转换如下图。为什么要“三次握手,四次挥手”三次握手换个易于理解的视角来看为什么要3次握手。客户端和服务端通信前要进行连接,“3次握手”的作用就是双方都能明确自己和对方的收、发能力是正常的。第一次握手:客户端发送网络包,服务端收到了。这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。第二次握手:服务端发包,客户端收到了。这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。从客户端的视角来看,我接到了服务端发送过来的响应数据包,说明服务端接收到了我在第一次握手时发送的网络包,并且成功发送了响应数据包,这就说明,服务端的接收、发送能力正常。而另一方面,我收到了服务端的响应数据包,说明我第一次发送的网络包成功到达服务端,这样,我自己的发送和接收能力也是正常的。第三次握手:客户端发包,服务端收到了。这样服务端就能得出结论:客户端的接收、发送能力,服务端的发送、接收能力是正常的。第一、二次握手后,服务端并不知道客户端的接收能力以及自己的发送能力是否正常。而在第三次握手时,服务端收到了客户端对第二次握手作的回应。从服务端的角度,我在第二次握手时的响应数据发送出去了,客户端接收到了。所以,我的发送能力是正常的。而客户端的接收能力也是正常的。经历了上面的三次握手过程,客户端和服务端都确认了自己的接收、发送能力是正常的。之后就可以正常通信了。每次都是接收到数据包的一方可以得到一些结论,发送的一方其实没有任何头绪。我虽然有发包的动作,但是我怎么知道我有没有发出去,而对方有没有接收到呢?而从上面的过程可以看到,最少是需要三次握手过程的。两次达不到让双方都得出自己、对方的接收、发送能力都正常的结论。其实每次收到网络包的一方至少是可以得到:对方的发送、我方的接收是正常的。而每一步都是有关联的,下一次的“响应”是由于第一次的“请求”触发,因此每次握手其实是可以得到额外的结论的。比如第三次握手时,服务端收到数据包,表明看服务端只能得到客户端的发送能力、服务端的接收能力是正常的,但是结合第二次,说明服务端在第二次发送的响应包,客户端接收到了,并且作出了响应,从而得到额外的结论:客户端的接收、服务端的发送是正常的。用表格总结一下:视角客收客发服收服发客视角二一 + 二一 + 二二服视角二 + 三一一二 + 三四次挥手TCP连接是双向传输的对等的模式,就是说双方都可以同时向对方发送或接收数据。当有一方要关闭连接时,会发送指令告知对方,我要关闭连接了。这时对方会回一个ACK,此时一个方向的连接关闭。但是另一个方向仍然可以继续传输数据,等到发送完了所有的数据后,会发送一个FIN段来关闭此方向上的连接。接收方发送ACK确认关闭连接。注意,接收到FIN报文的一方只能回复一个ACK, 它是无法马上返回对方一个FIN报文段的,因为结束数据传输的“指令”是上层应用层给出的,我只是一个“搬运工”,我无法了解“上层的意志”。“三次握手,四次挥手”怎么完成?其实3次握手的目的并不只是让通信双方都了解到一个连接正在建立,还在于利用数据包的选项来传输特殊的信息,交换初始序列号ISN。3次握手是指发送了3个报文段,4次挥手是指发送了4个报文段。注意,SYN和FIN段都是会利用重传进行可靠传输的。三次握手客户端发送一个SYN段,并指明客户端的初始序列号,即ISN(c).服务端发送自己的SYN段作为应答,同样指明自己的ISN(s)。为了确认客户端的SYN,将ISN(c)+1作为ACK数值。这样,每发送一个SYN,序列号就会加1. 如果有丢失的情况,则会重传。为了确认服务器端的SYN,客户端将ISN(s)+1作为返回的ACK数值。四次挥手客户端发送一个FIN段,并包含一个希望接收者看到的自己当前的序列号K. 同时还包含一个ACK表示确认对方最近一次发过来的数据。服务端将K值加1作为ACK序号值,表明收到了上一个包。这时上层的应用程序会被告知另一端发起了关闭操作,通常这将引起应用程序发起自己的关闭操作。服务端发起自己的FIN段,ACK=K+1, Seq=L客户端确认。ACK=L+1为什么建立连接是三次握手,而关闭连接却是四次挥手呢?这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方是否现在关闭发送数据通道,需要上层应用来决定,因此,己方ACK和FIN一般都会分开发送。“三次握手,四次挥手”进阶ISN三次握手的一个重要功能是客户端和服务端交换ISN(Initial Sequence Number), 以便让对方知道接下来接收数据的时候如何按序列号组装数据。如果ISN是固定的,攻击者很容易猜出后续的确认号。ISN = M + F(localhost, localport, remotehost, remoteport)M是一个计时器,每隔4微秒加1。F是一个Hash算法,根据源IP、目的IP、源端口、目的端口生成一个随机数值。要保证hash算法不能被外部轻易推算得出。序列号回绕因为ISN是随机的,所以序列号容易就会超过2^31-1. 而tcp对于丢包和乱序等问题的判断都是依赖于序列号大小比较的。此时就出现了所谓的tcp序列号回绕(sequence wraparound)问题。怎么解决?/** The next routines deal with comparing 32 bit unsigned ints* and worry about wraparound (automatic with unsigned arithmetic).*/static inline int before(__u32 seq1, __u32 seq2){ return (__s32)(seq1-seq2) < 0;}#define after(seq2, seq1) before(seq1, seq2)上述代码是内核中的解决回绕问题代码。__s32是有符号整型的意思,而__u32则是无符号整型。序列号发生回绕后,序列号变小,相减之后,把结果变成有符号数了,因此结果成了负数。假设seq1=255, seq2=1(发生了回绕)。seq1 = 1111 1111 seq2 = 0000 0001我们希望比较结果是 seq1 - seq2= 1111 1111-0000 0001———– 1111 1110由于我们将结果转化成了有符号数,由于最高位是1,因此结果是一个负数,负数的绝对值为 0000 0001 + 1 = 0000 0010 = 2因此seq1 - seq2 < 0syn flood攻击最基本的DoS攻击就是利用合理的服务请求来占用过多的服务资源,从而使合法用户无法得到服务的响应。syn flood属于Dos攻击的一种。如果恶意的向某个服务器端口发送大量的SYN包,则可以使服务器打开大量的半开连接,分配TCB(Transmission Control Block), 从而消耗大量的服务器资源,同时也使得正常的连接请求无法被相应。当开放了一个TCP端口后,该端口就处于Listening状态,不停地监视发到该端口的Syn报文,一 旦接收到Client发来的Syn报文,就需要为该请求分配一个TCB,通常一个TCB至少需要280个字节,在某些操作系统中TCB甚至需要1300个字节,并返回一个SYN ACK命令,立即转为SYN-RECEIVED即半开连接状态。系统会为此耗尽资源。常见的防攻击方法有:无效连接的监视释放监视系统的半开连接和不活动连接,当达到一定阈值时拆除这些连接,从而释放系统资源。这种方法对于所有的连接一视同仁,而且由于SYN Flood造成的半开连接数量很大,正常连接请求也被淹没在其中被这种方式误释放掉,因此这种方法属于入门级的SYN Flood方法。延缓TCB分配方法消耗服务器资源主要是因为当SYN数据报文一到达,系统立即分配TCB,从而占用了资源。而SYN Flood由于很难建立起正常连接,因此,当正常连接建立起来后再分配TCB则可以有效地减轻服务器资源的消耗。常见的方法是使用Syn Cache和Syn Cookie技术。Syn Cache技术系统在收到一个SYN报文时,在一个专用HASH表中保存这种半连接信息,直到收到正确的回应ACK报文再分配TCB。这个开销远小于TCB的开销。当然还需要保存序列号。Syn Cookie技术Syn Cookie技术则完全不使用任何存储资源,这种方法比较巧妙,它使用一种特殊的算法生成Sequence Number,这种算法考虑到了对方的IP、端口、己方IP、端口的固定信息,以及对方无法知道而己方比较固定的一些信息,如MSS(Maximum Segment Size,最大报文段大小,指的是TCP报文的最大数据报长度,其中不包括TCP首部长度。)、时间等,在收到对方 的ACK报文后,重新计算一遍,看其是否与对方回应报文中的(Sequence Number-1)相同,从而决定是否分配TCB资源。使用SYN Proxy防火墙一种方式是防止墙dqywb连接的有效性后,防火墙才会向内部服务器发起SYN请求。防火墙代服务器发出的SYN ACK包使用的序列号为c, 而真正的服务器回应的序列号为c’, 这样,在每个数据报文经过防火墙的时候进行序列号的修改。另一种方式是防火墙确定了连接的安全后,会发出一个safe reset命令,client会进行重新连接,这时出现的syn报文会直接放行。这样不需要修改序列号了。但是,client需要发起两次握手过程,因此建立连接的时间将会延长。连接队列在外部请求到达时,被服务程序最终感知到前,连接可能处于SYN_RCVD状态或是ESTABLISHED状态,但还未被应用程序接受。对应地,服务器端也会维护两种队列,处于SYN_RCVD状态的半连接队列,而处于ESTABLISHED状态但仍未被应用程序accept的为全连接队列。如果这两个队列满了之后,就会出现各种丢包的情形。查看是否有连接溢出netstat -s | grep LISTEN半连接队列满了在三次握手协议中,服务器维护一个半连接队列,该队列为每个客户端的SYN包开设一个条目(服务端在接收到SYN包的时候,就已经创建了request_sock结构,存储在半连接队列中),该条目表明服务器已收到SYN包,并向客户发出确认,正在等待客户的确认包。这些条目所标识的连接在服务器处于Syn_RECV状态,当服务器收到客户的确认包时,删除该条目,服务器进入ESTABLISHED状态。目前,Linux下默认会进行5次重发SYN-ACK包,重试的间隔时间从1s开始,下次的重试间隔时间是前一次的双倍,5次的重试时间间隔为1s, 2s, 4s, 8s, 16s, 总共31s, 称为指数退避,第5次发出后还要等32s才知道第5次也超时了,所以,总共需要 1s + 2s + 4s+ 8s+ 16s + 32s = 63s, TCP才会把断开这个连接。由于,SYN超时需要63秒,那么就给攻击者一个攻击服务器的机会,攻击者在短时间内发送大量的SYN包给Server(俗称SYN flood攻击),用于耗尽Server的SYN队列。对于应对SYN 过多的问题,linux提供了几个TCP参数:tcp_syncookies、tcp_synack_retries、tcp_max_syn_backlog、tcp_abort_on_overflow 来调整应对。参数作用tcp_syncookiesSYNcookie将连接信息编码在ISN(initialsequencenumber)中返回给客户端,这时server不需要将半连接保存在队列中,而是利用客户端随后发来的ACK带回的ISN还原连接信息,以完成连接的建立,避免了半连接队列被攻击SYN包填满。tcp_syncookies内核放弃建立连接之前发送SYN包的数量。tcp_synack_retries内核放弃连接之前发送SYN+ACK包的数量tcp_max_syn_backlog默认为1000. 这表示半连接队列的长度,如果超过则放弃当前连接。tcp_abort_on_overflow如果设置了此项,则直接reset. 否则,不做任何操作,这样当服务器半连接队列有空了之后,会重新接受连接。Linux坚持在能力许可范围内不忽略进入的连接。客户端在这期间会重复发送sys包,当重试次数到达上限之后,会得到connection time out响应。全连接队列满了当第三次握手时,当server接收到ACK包之后,会进入一个新的叫 accept 的队列。当accept队列满了之后,即使client继续向server发送ACK的包,也会不被响应,此时ListenOverflows+1,同时server通过tcp_abort_on_overflow来决定如何返回,0表示直接丢弃该ACK,1表示发送RST通知client;相应的,client则会分别返回read timeout 或者 connection reset by peer。另外,tcp_abort_on_overflow是0的话,server过一段时间再次发送syn+ack给client(也就是重新走握手的第二步),如果client超时等待比较短,就很容易异常了。而客户端收到多个 SYN ACK 包,则会认为之前的 ACK 丢包了。于是促使客户端再次发送 ACK ,在 accept队列有空闲的时候最终完成连接。若 accept队列始终满员,则最终客户端收到 RST 包(此时服务端发送syn+ack的次数超出了tcp_synack_retries)。服务端仅仅只是创建一个定时器,以固定间隔重传syn和ack到服务端参数作用tcp_abort_on_overflow如果设置了此项,则直接reset. 否则,不做任何操作,这样当服务器半连接队列有空了之后,会重新接受连接。Linux坚持在能力许可范围内不忽略进入的连接。客户端在这期间会重复发送sys包,当重试次数到达上限之后,会得到connection time out响应。min(backlog, somaxconn)全连接队列的长度。命令netstat -s命令[root@server ~]# netstat -s | egrep “listen|LISTEN” 667399 times the listen queue of a socket overflowed667399 SYNs to LISTEN sockets ignored上面看到的 667399 times ,表示全连接队列溢出的次数,隔几秒钟执行下,如果这个数字一直在增加的话肯定全连接队列偶尔满了。[root@server ~]# netstat -s | grep TCPBacklogDrop查看 Accept queue 是否有溢出ss命令[root@server ~]# ss -lntState Recv-Q Send-Q Local Address:Port Peer Address:PortLISTEN 0 128 *:6379 *:*LISTEN 0 128 *:22 :如果State是listen状态,Send-Q 表示第三列的listen端口上的全连接队列最大为50,第一列Recv-Q为全连接队列当前使用了多少。非 LISTEN 状态中 Recv-Q 表示 receive queue 中的 bytes 数量;Send-Q 表示 send queue 中的 bytes 数值。小结当外部连接请求到来时,TCP模块会首先查看max_syn_backlog,如果处于SYN_RCVD状态的连接数目超过这一阈值,进入的连接会被拒绝。根据tcp_abort_on_overflow字段来决定是直接丢弃,还是直接reset.从服务端来说,三次握手中,第一步server接受到client的syn后,把相关信息放到半连接队列中,同时回复syn+ack给client. 第三步当收到客户端的ack, 将连接加入到全连接队列。一般,全连接队列比较小,会先满,此时半连接队列还没满。如果这时收到syn报文,则会进入半连接队列,没有问题。但是如果收到了三次握手中的第3步(ACK),则会根据tcp_abort_on_overflow字段来决定是直接丢弃,还是直接reset.此时,客户端发送了ACK, 那么客户端认为三次握手完成,它认为服务端已经准备好了接收数据的准备。但此时服务端可能因为全连接队列满了而无法将连接放入,会重新发送第2步的syn+ack, 如果这时有数据到来,服务器TCP模块会将数据存入队列中。一段时间后,client端没收到回复,超时,连接异常,client会主动关闭连接。“三次握手,四次挥手”redis实例分析我在dev机器上部署redis服务,端口号为6379,通过tcpdump工具获取数据包,使用如下命令tcpdump -w /tmp/a.cap port 6379 -s0-w把数据写入文件,-s0设置每个数据包的大小默认为68字节,如果用-S 0则会抓到完整数据包在dev2机器上用redis-cli访问dev:6379, 发送一个ping, 得到回复pong停止抓包,用tcpdump读取捕获到的数据包tcpdump -r /tmp/a.cap -n -nn -A -x| vim -(-x 以16进制形式展示,便于后面分析)共收到了7个包。抓到的是IP数据包,IP数据包分为IP头部和IP数据部分,IP数据部分是TCP头部加TCP数据部分。IP的数据格式为:它由固定长度20B+可变长度构成。10:55:45.662077 IP dev2.39070 > dev.6379: Flags [S], seq 4133153791, win 29200, options [mss 1460,sackOK,TS val 2959270704 ecr 0,nop,wscale 7], length 0 0x0000: 4500 003c 08cf 4000 3606 14a5 0ab3 b561 0x0010: 0a60 5cd4 989e 18eb f65a ebff 0000 0000 0x0020: a002 7210 872f 0000 0204 05b4 0402 080a 0x0030: b062 e330 0000 0000 0103 0307对着IP头部格式,来拆解数据包的具体含义。字节值字节含义0x4IP版本为ipv40x5首部长度为5 * 4字节=20B0x00服务类型,现在基本都置为00x003c总长度为316+12=60字节,上面所有的长度就是60字节0x08cf标识。同一个数据报的唯一标识。当IP数据报被拆分时,会复制到每一个数据中。0x40003bit 标志 + 13bit 片偏移。3bit 标志对应 R、DF、MF。目前只有后两位有效,DF位:为1表示不分片,为0表示分片。MF:为1表示“更多的片”,为0表示这是最后一片。13bit 片位移:本分片在原先数据报文中相对首位的偏移位。(需要再乘以8 )0x36生存时间TTL。IP报文所允许通过的路由器的最大数量。每经过一个路由器,TTL减1,当为 0 时,路由器将该数据报丢弃。TTL 字段是由发送端初始设置一个 8 bit字段.推荐的初始值由分配数字 RFC 指定。发送 ICMP 回显应答时经常把 TTL 设为最大值 255。TTL可以防止数据报陷入路由循环。 此处为54.0x06协议类型。指出IP报文携带的数据使用的是哪种协议,以便目的主机的IP层能知道要将数据报上交到哪个进程。TCP 的协议号为6,UDP 的协议号为17。ICMP 的协议号为1,IGMP 的协议号为2。该 IP 报文携带的数据使用 TCP 协议,得到了验证。0x14a516bitIP首部校验和。0x0ab3 b56132bit源ip地址。0x0a60 5cd432bit目的ip地址。剩余的数据部分即为TCP协议相关的。TCP也是20B固定长度+可变长度部分。字节值字节含义0x989e16bit源端口。1161616+81616+1416+11=390700x18eb16bit目的端口63790xf65a ebff32bit序列号。41331537910x0000 000032bit确认号。0xa4bit首部长度,以4byte为单位。共104=40字节。因此TCP报文的可选长度为40-20=200b0000006bit保留位。目前置为0.0b0000106bitTCP标志位。从左到右依次是紧急 URG、确认 ACK、推送 PSH、复位 RST、同步 SYN 、终止 FIN。0x7210滑动窗口大小,滑动窗口即tcp接收缓冲区的大小,用于tcp拥塞控制。292000x872f16bit校验和。0x0000紧急指针。仅在 URG = 1时才有意义,它指出本报文段中的紧急数据的字节数。当 URG = 1 时,发送方 TCP 就把紧急数据插入到本报文段数据的最前面,而在紧急数据后面的数据仍是普通数据。可变长度部分,协议如下:字节值字节含义0x0204 05b4最大报文长度为,05b4=1460. 即可接收的最大包长度,通常为MTU减40字节,IP头和TCP头各20字节0x0402表示支持SACK0x080a b062 e330 0000 0000时间戳。Ts val=b062 e330=2959270704, ecr=00x01无操作0x03 0307窗口扩大因子为7. 移位7, 乘以128这样第一个包分析完了。dev2向dev发送SYN请求。也就是三次握手中的第一次了。SYN seq(c)=4133153791第二个包,dev响应连接,ack=4133153792. 表明dev下次准备接收这个序号的包,用于tcp字节注的顺序控制。dev(也就是server端)的初始序号为seq=4264776963, syn=1.SYN ack=seq(c)+1 seq(s)=4264776963第三个包,client包确认,这里使用了相对值应答。seq=4133153792, 等于第二个包的ack. ack=4264776964.ack=seq(s)+1, seq=seq(c)+1至此,三次握手完成。接下来就是发送ping和pong的数据了。接着第四个包。10:55:48.090073 IP dev2.39070 > dev.6379: Flags [P.], seq 1:15, ack 1, win 229, options [nop,nop,TS val 2959273132 ecr 3132256230], length 14 0x0000: 4500 0042 08d1 4000 3606 149d 0ab3 b561 0x0010: 0a60 5cd4 989e 18eb f65a ec00 fe33 5504 0x0020: 8018 00e5 4b5f 0000 0101 080a b062 ecac 0x0030: bab2 6fe6 2a31 0d0a 2434 0d0a 7069 6e67 0x0040: 0d0atcp首部长度为32B, 可选长度为12B. IP报文的总长度为66B, 首部长度为20B, 因此TCP数据部分长度为14B. seq=0xf65a ec00=4133153792ACK, PSH. 数据部分为2a31 0d0a 2434 0d0a 7069 6e67 0d0a0x2a31 -> *10x0d0a -> \r\n0x2434 -> $40x0d0a -> \r\n0x7069 0x6e67 -> ping0x0d0a -> \r\ndev2向dev发送了ping数据,第四个包完毕。第五个包,dev2向dev发送ack响应。序列号为0xfe33 5504=4264776964, ack确认号为0xf65a ec0e=4133153806=(4133153792+14). 第六个包,dev向dev2响应pong消息。序列号fe33 5504,确认号f65a ec0e, TCP头部可选长度为12B, IP数据报总长度为59B, 首部长度为20B, 因此TCP数据长度为7B.数据部分2b50 4f4e 470d 0a, 翻译过来就是+PONG\r\n.至此,Redis客户端和Server端的三次握手过程分析完毕。总结“三次握手,四次挥手”看似简单,但是深究进去,还是可以延伸出很多知识点的。比如半连接队列、全连接队列等等。以前关于TCP建立连接、关闭连接的过程很容易就会忘记,可能是因为只是死记硬背了几个过程,没有深入研究背后的原理。所以,“三次握手,四次挥手”你真的懂了吗?欢迎一起交流~~参考资料【redis】https://segmentfault.com/a/11…【tcp option】https://blog.csdn.net/wdscq12…【滑动窗口】https://www.zhihu.com/questio…【全连接队列】http://jm.taobao.org/2017/05/…【client fooling】 https://github.com/torvalds/l…【backlog RECV_Q】http://blog.51cto.com/5909093…【定时器】https://www.cnblogs.com/mengh…【队列图示】https://www.itcodemonkey.com/…【tcp flood攻击】https://www.cnblogs.com/hubav…【MSS MTU】https://blog.csdn.net/LoseInV… ...

February 15, 2019 · 3 min · jiezi

tcp ip高效编程 笔记

CS架构与对等实体CS位置备注特点举例同一机器数据会被环回,并不会放到网络设备输出队列中几乎没有网络延迟和丢包自己开发web程序调试同一局域网内 极少没有网络延迟和丢包打印机不同网络位于广域网途径的路由器如果队列空间耗尽,就会导致丢弃分组,进而导致重传。重传又会引起分组的重复和乱序。真实环境基本套接字API回顾SOCKET socket (int domain, int type, int protocol)// 成功返回套接字描述符,失败时返回-1套接字API与协议无关。domain是个常量,表示通信域,有以下两个AF_INET 用于因特网AF_LOCAL 用于同一台机器上的IPC通信,即进程间通信type说明套接字的类型,有常见的以下几种SOCK_STREAM 提供可靠,全双工,面向连接的字节流,例如TCPSOCK_DGRAM 提供不可靠,尽力而为的数据服务,例如UDPSOCK_RAW 允许对IP层的某些数据进行访问,例如监听ICMP报文protocol说明使用哪种协议,对tcp/ip来说,可以直接由type字段隐式说明,参数被设置为0int connect (SOCKET s, const struct socketaddr *peer, int peer_len)// 成功时返回0, 失败时返回非0s: 套接字描述符peer: 是一个地址结构,存储对等实体的地址和其他信息peer_len; 是地址结构的长度connect一旦建立起来,就可以传输数据。在unix中,套接字描述符可以像文件描述符那样调用read和write。但是windowsint recv (SOCKET s, void *buf, size_t len, int flags)int rend (SOCKET s, cosnt void *buf, size_t len, int flags)参数s, buf, len和read, write参数一样。flags通常和系统有关。unix和win都支持以下flagMSG_OOB 收发紧急数据MSG_PEEK 查看输入数据,但是不从缓冲区删除数据。俗称瞥一眼MSG_DONTROUTE 绕过通常的选路函数,通常只有选路函数使用,或用于诊断理解面向连接和无连接协议的区别面向连接和无连接,指的都是协议,不是物理介质,是指数据在介质上如何传输本质区别是,对于无连接协议,每个分组的处理都是独立的。对于面向连接的协议,分组还要维护后续分组的相关信息。无连接协议是面向连接协议的基础无连接协议就像是寄信,每封信都有自己的收件人地址,你可以同时给多个人寄信。邮局处理信件也不会管每封信之间的关系。面向连接的协议就像是打电话,一个人先拨号,等另一个人说喂,然后自己在说我是某某某。说完话了,一个人会说,拜拜,另一个也会说拜拜。 有时候你听不清楚对方在说什么,还会说:麻烦你在说一遍,我没听清。或者:你说的太快了,麻烦说慢一点。——–应用程序——–TCP和UDP——– IP——–物理接口——–TCP的每个分组成为段(segment), 是放在IP数据包中发送的。但是IP数据报并不保证数据的可靠到达。所以TCP必须自己实现可靠性。TCP使用三个功能实现可靠性校验和:校验和用来校验数据有没有被中途损坏,保证安全性序列号:每个段都有自己的序号,用来重新排列乱序的段,保证顺序性确认重传机制: 保证每个段都被对方收到,保证可靠性TCP的三个功能中,确认重传机制最为复杂。TCP接收窗口左边箭头表示窗口的左边界,所期望下一个字节的序列号右边箭头表示窗口的右边界,表示TCP缓冲区所能容纳字节的最大编号,用来防止缓冲区溢出TCP到达时,所有序列号在窗口范围之外的,都会被直接丢弃如果段中的第一个字节序号是期望的字节号,就通知应用程序有数据可读。并且将窗口向右滑动TCP发送窗口发送窗口分为两个部分,已经发送出的但是还没有收到确认的,还有可以发送但还没有发送的在4-7字节已经发送出去之后,TCP会启动一个RTO(retransmission timeout)超时重传定时器,如果定时器超时之前这四个字节没有被确认,就会重传这四个字节。要注意重传的自己可以要比四个字节要多。重传并不意味着数据没有到达目的地,也有可能是ACK丢失TCP是一种流协议TCP是一种流协议,并没有固定的报文和报文流的概念。发送两次报文并不发送两个独立的实体,两次调用send, 只是将数据交给底层TCP/IP栈。至于底层是如何发送这两个数据的,由底层自己决定。底层将数据发出去有很多决定因素发送窗口拥塞窗口路径最大传输单元输出队列中有多少数据不要低估TCP的性能TCP并不是绝对可靠故障模式对等实体崩溃网络中断不要把OSI七层模型太当回事实际上OSI模型由很多缺点,本质上说OSI协议已经停用了。OSI模型是理想,TCP/IP才是现实。理解TCP写操作从应用程序角度看,send从TCP角度看,慢启动,ng算法TIME-WAIT通常,只有主动关闭连接的一方会进入TIME-WAIT阶段RFC 793将MSL定义为两分钟,那么2MSL就是4分钟。实际的操作系统可以将MSL设置为更低的值,如30秒。如果连接处于TIME-WAIT阶段,又有分组到达,就会重启2MSL定时器。使用TIME-WAIT的目的维护连接状态,以防主动发起连接关闭的哪一方最后一个ACK丢失造成另一端发送FIN耗尽网络中所有此连接的走失提供时间想一想,如果主机1在发出ACK之后立即关闭了连接,会发生什么事?AB分别为主机有 TIME-WAIT状态时,如果ACK丢失,那么B会重发FIN, A处于TIME_WAIT阶段时,再次收到FIN, 那么就会再次发送ACK, 并重启激动2MSL计时。无TIME-WAIT状态时, 主机A的收到FIN后,立即释放端口,那么该端口处于未监听状态。当数据被发送到为监听的端口时,发送方会收到链接重置的报文。无TIME-WAIT状态时, 主机A的端口已经被新的应用程序占用,新的连接的数据可能被迟来的数据破坏。TCP的状态转移图TCP一共有11中状态左下角虚线方框中是主动关闭方关闭时会经历的状态转移尽可能写入一个大块数据,而不是频繁的写入小块的数据参考书籍TCP/IP高效编程TCP/IP详解 卷1:协议UNIX网络编程 卷1:套接字联网API(第3版)

January 30, 2019 · 1 min · jiezi

从一起丢包故障来谈谈 nginx 中的 tcp keep-alive

一、故障基本架构如图所示,客户端发起 http 请求给 nginx,nginx 转发请求给网关,网关再转发请求到后端微服务。故障现象是,每隔十几分钟或者几个小时不等,客户端就会得到一个或者连续多个请求超时错误。查看 nginx 日志,对应请求返回 499;查看网关日志,没有收到对应的请求。从日志分析,问题应该处在 nginx 或者 spring-cloud-gateway 上。nginx 版本:1.14.2,spring-cloud 版本:Greenwich.RC2。nginx 主要配置如下:[root@wh-hlwzxtest1 conf]# cat nginx.confworker_processes 8;events { use epoll; worker_connections 10240;}http { include mime.types; default_type application/octet-stream; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; #gzip on; upstream dbg2 { server 10.201.0.27:8888; keepalive 100; } server { listen 80; server_name localhost; charset utf-8; location /dbg2/ { proxy_pass http://dbg2/; proxy_http_version 1.1; proxy_set_header Connection “”; } }}为了提高性能,nginx 发送给网关的请求为 http 1.1,可以复用 tcp 连接。二、排查1、查看 tcp 连接[root@10.197.0.38 logs]# ss -n | grep 10.201.0.27:8888tcp ESTAB 0 0 10.197.0.38:36674 10.201.0.27:8888tcp ESTAB 0 0 10.197.0.38:40106 10.201.0.27:8888[root@10.201.0.27 opt]# ss -n | grep 10.197.0.38tcp ESTAB 0 0 ::ffff:10.201.0.27:8888 ::ffff:10.197.0.38:40106tcp ESTAB 0 0 ::ffff:10.201.0.27:8888 ::ffff:10.197.0.38:39266可以看到 nginx 和网关之间建立的 socket 连接为 (10.201.0.27:8888,10.197.0.38:40106),另外的 2 条记录就很可疑了。猜测原因是:一端异常关闭了 tcp 连接却没有通知对端,或者通知了对端但对端没有收到。2、抓包分析先看下 nginx 的抓包数据:序号 8403:转发 http 请求给网关;序号 8404:在 RTT 时间内没有收到 ack 包,重发报文;序号 8505:RTT 约等于 0.2s,tcp 重传;序号 8506:0.4s 没收到 ack 包,tcp 重传;序号 8507:0.8s 没收到 ack 包,tcp 重传;序号 8509:1.6s 没收到 ack 包,tcp 重传;…序号8439:28.1s(128RTT)没收到 ack 包,tcp 重传。序号 8408:请求设置了超时时间为 3s,因此发送 FIN 包。再看下网关的抓包数据:序号 1372:17:24:31 收到了 nginx 发过来的 ack 确认包,对应 nginx 抓包图中的序号 1348(nginx 那台服务器时间快了差不多 1 分 30 秒);序号 4221:2 小时后,发送 tcp keep-alive 心跳报文,(从 nginx 抓包图中也可以看出这 2 小时之内该 tcp 连接空闲);序号 4253:75s 后再次发送 tcp keep-alive 心跳;序号 4275:75s 后再次发送心跳;连续 9 次;序号 4489:发送 RST 包,通过对端重置连接。2 小时,75s, 9 次,系统默认设置。[root@eureka2 opt]# cat /proc/sys/net/ipv4/tcp_keepalive_time7200[root@eureka2 opt]# cat /proc/sys/net/ipv4/tcp_keepalive_intvl75[root@eureka2 opt]# cat /proc/sys/net/ipv4/tcp_keepalive_probes9具体这几个参数的作用,参考文章:为什么基于TCP的应用需要心跳包3、分析通过以上抓包分析,基本确认了问题出在 nginx 上。19:25 时,网关发送 tcp keep-alive 心跳包给 nginx 那台服务器,此时那台服务器上保留着该 tcp 连接,却没有回应;22:20 时,nginx 发送 http 请求给网关,而网关已经关闭该 tcp 连接,因此没有应答。三、解决1、proxy_send_timeoutnginx 中与 upstream 相关的超时配置主要有如下参数,参考:Nginx的超时timeout配置详解proxy_connect_timeout:nginx 与 upstream server 的连接超时时间;proxy_read_timeout:nginx 接收 upstream server 数据超时, 默认 60s, 如果连续的 60s 内没有收到 1 个字节, 连接关闭;proxy_send_timeout:nginx 发送数据至 upstream server 超时, 默认 60s, 如果连续的 60s 内没有发送 1 个字节, 连接关闭。这几个参数,都是针对 http 协议层面的。比如 proxy_send_timeout = 60s,并不是指如果 60s 没有发送 http 请求,就关闭连接;而是指发送 http 请求后,在两次 write 操作期间,如果超过 60s,就关闭连接。所以这几个参数,显然不是我们需要的。2、upstream 模块的 keepalive_timeout 参数查看官网文档,Module ngx_http_upstream_module,Syntax: keepalive_timeout timeout;Default: keepalive_timeout 60s;Context: upstreamThis directive appeared in version 1.15.3.Sets a timeout during which an idle keepalive connection to an upstream server will stay open.设置 tcp 连接空闲时间超过 60s 后关闭,这正是我们需要的。为了使用该参数,升级 nginx 版本到 1.15.8,配置文件如下:http { upstream dbg2 { server 10.201.0.27:8888; keepalive 100; keepalive_requests 30000; keepalive_timeout 300s; } …}设置 tcp 连接上跑了 30000 个 http 请求或者空闲 300s,那么就关闭连接。之后继续测试,没有发现丢包。序号 938:空闲 5 分钟后,nginx 主动发起 FIN 报文,关闭连接。 ...

January 24, 2019 · 2 min · jiezi

协议简史:如何学习网络协议?

大学时,学到网络协议的7层模型时,老师教了大家一个顺口溜:物数网传会表应。并说这是重点,年年必考,5分的题目摆在这里,你们爱背不背。考试的时候,果然遇到这个问题,搜索枯肠,只能想到这7个字的第一个字,因为这5分,差点挂科。后来工作面试,面试官也是很喜欢七层模型,三次握手之类的问题,但是遇到这些问题时,总是觉得很心虚。1. 协议分层四层网络协议模型中,应用层以下一般都是交给操作系统来处理。应用层对于四层模型来说,仅仅是冰山一角。海面下巨复杂的三层协议,都被操作系统给隐藏起来了,一般我们在页面上发起一个ajax请求,看见了network面板多了一个http请求,至于底层是如何实现的,我们并不关心。应⽤层负责处理特定的应⽤程序细节。运输层运输层主要为两台主机上的应⽤程序提供端到端的通信。网络层处理理分组在⽹网络中的活动,例例如分组的选路链路层处理理与电缆(或其他任何传输媒介)的物理理接⼝口细节下面重点讲一下运输层和网络层1.1. 运输层的两兄弟运输层有两个比较重要的协议。tcp和udp。大哥tcp是比较严谨认真、温柔体贴、慢热内向的协议,发出去的消息,总是一个一个认真检查,等待对方回复和确认,如果一段时间内,对方没有回复确认消息,还会再次发送消息,如果对方回复说你发的太快了,tcp还会体贴的把发送消息的速度降低。弟弟udp则比较可爱呆萌、调皮好动、不负责任的协议。哥哥tcp所具有的特点,弟弟udp一个也没有。但是有的人说不清哪里好 但就是谁都替代不了,udp没有tcp那些复杂的校验和重传等复杂的步骤,所以它发送消息非常快,而且并不保证对方一定收到。如果对方收不到消息,那么udp就会呆萌的看着你,笑着对你说:我已经尽力了。一般语音而视频数据都是用udp协议传输的,因为音频或者视频卡了一下并不影响整体的质量,而对实时性的要求会更高。1.2. 运输层和网络层的区别运输层关注的是端到端层面,及End1到End2,忽略中间的任何点。网络层关注两点之间的层面,即hop1如何到hop2,hop2如何到hop3网络层并不保证消息可靠性,可靠性上层的传输层负责。TCP采用超时重传,分组确认的机制,保证消息不会丢失。从下图tcp, udp, ip协议中,可以发现传输层的tcp和udp都是有源端口和目的端口,但是没有ip字段源ip和目的ip只在ip数据报中理解各个协议,关键在于理解报文的各个字段的含义1.3. ip和端口号的真正含义上个章节讲到运输层和网络层的区别,其中端口号被封装在运输层,ip被封装到网络成,那么端口号和ip地址到底有什么区别呢?ip用来用来标记主机的位置端口号用来标记该数据应该被目标主机上的哪个应用程序去处理1.4. 数据在协议栈的流动 封装与分用当发送消息时,数据在向下传递时,经过不同层次的协议处理,打上各种头部信息当接受消息时,数据在向上传递,通过不同的头部信息字段,才知道要交给上层的那个模块来处理。比如一个ip包,如果没有头部信息,那么这个消息究竟是交给tcp协议来处理,还是udp来处理,就不得而知了2. 深入阅读,好书推荐《http权威指南》 有人说这本书太厚,偷偷告诉你,其实这本书并厚,因为这本书的后面的30%部分都是附录,这本书的精华是前50%的部分《图解http》、《图解tcp/ip》这两本图解的书,知识点讲的都是比较通俗易懂的,适合入门《tcp/ip 详解 卷1》这本书,让你知其然,更知其所以然《tcp/ip 基础》、《tcp/ip 路由技术》这两本书,会让你从不同角度思考协议《精通wireshark》、《wireshark网络分析实战》如果你看了很多书,却从来没有试过网络抓包,那你只是懂纸上谈兵罢了。你永远无法理解tcp三次握手的怦然心动,与四次分手的刻骨铭心。

January 19, 2019 · 1 min · jiezi

tcp没用吗?为什么MOBA、“吃鸡”游戏不推荐用tcp协议

本文由云+社区发表作者:腾讯云游戏行业资深架构师 余国良MOBA类和“吃鸡”游戏为什么对网络延迟要求高?我们知道,不同类型的游戏因为玩法、竞技程度不一样,采用的同步算法不一样,对网络延迟的要求也不一样。例如,MOBA类游戏多使用帧同步为主要同步算法,竞技性也较高,无论从流畅性,还是从公平性要求来说,对响应延迟的要求都最高,根据业内经验,当客户端与服务器的网络延迟超过150ms时,会开始出现卡顿,当延迟超过250ms时,会对玩家操作造成较大影响,游戏无法公平进行。类似地,“吃鸡”游戏(如《绝地求生》)玩法对玩家坐标、动作的同步要求极高,延迟稍大导致的数据不一致对体验都会造成较大影响,其实时性要求接近MOBA类游戏。而对于传统mmorpg来说,多采用状态同步算法,以属性养成和装备获取为关注点,也有一定竞技性,出于对游戏流畅性的要求,对延迟也有一定要求,同步算法的优化程度不一样,这一要求也不一样,一般情况下为保证游戏正常进行,需要响应延迟保持在300ms以下。相比之下,对于炉石传说、斗地主、梦幻西游等回合制游戏来说,同时只有一个玩家在操作双方数据,无数据竞争,且时间粒度较粗,甚至可通过特效掩盖延迟,因此对网络延迟的要求不高,即便延迟达到500ms~1000ms,游戏也能正常进行。这里,我们不对同步算法做进一步说明,重点说一下协议的问题。传输层协议和延迟不同传输层协议在可靠性、流量控制等方面都有差别,而这些技术细节会对延迟造成影响。tcp追求的是完全可靠性和顺序性,丢包后会持续重传直至该包被确认,否则后续包也不会被上层接收,且重传采用指数避让策略,决定重传时间间隔的RTO(retransmission timeout)不可控制,linux内核实现中最低值为200ms,这样的机制会导致丢包率短暂升高的情况下应用层消息响应延迟急剧提高,并不适合实时性高、网络环境复杂的游戏。加速方案基于udp定制传输层协议,引入顺序性和适当程度或者可调节程度的可靠性,修改流控算法。适当放弃重传,如:设置最大重传次数,即使重传失败,也不需要重新建立连接。比较知名的tcp加速开源方案有:quic、enet、kcp、udt。其中,quic是源自google的tcp替代方案,其主要目的是为了整合TCP协议的可靠性和udp协议的速度和效率,其主要特性包括:避免前序包阻塞、减少数据包、向前纠错、会话重启和并行下载等,然而QUIC对标的是TCP+TLS+SPDY,相比其他方案更重,目前国内用于网络游戏较少。kcp的作者是国内优秀开发者,社区也发展良好,kcp的作者和社区开发者对enet、kcp、udt做了性能测试,详情可参见:https://github.com/skywind300…, 从测试情况可以看到,kcp表现不错,其次是enet,表现最差的是udt。不过,这里也提出一个问题,原始enet保留了tcp重传的指数避让特性,每次重传间隔还是乘以2,默认rto也较高,这可能是测试中enet表现不如kcp的主要原因,如果对enet代码稍作调整,结果又当如何?这里,我们先排除传输性能,从其他方面对enet和kcp做一对比(满分5分):我们对libenet略微做一些调整——默认rtt从500ms调整成50ms, 去除超时重传的指数避让策略。Linux下用TC命令模拟网络延迟和丢包率,控制延迟分别为30ms, 50ms, 70ms,控制丢包率分别为1%, 3%, 5%, 7%, 10%,在模拟出的不同网络环境下,对tcp, 原始enet和改进后的enet进行了对比测试。测试中考察两个性能指标:1)平均响应时间;2)响应时间超过300ms的包的比例。libenet的代码调整: 图 1 调整默认RTT为50ms 图 2 取消指数避让tc命令如下:模拟延迟100ms(rtt为200ms): tc qdisc add dev eth0 root netem delay 100ms模拟1%丢包率:tc qdisc add dev eth0 root netem loss 1%对比结果数据如下:图 3 不同丢包率和网络延迟下TCP协议、ENET、优化后ENET的平均响应时间对比图 4 不同丢包率和网络延迟下TCP协议、ENET、优化后ENET的超时响应比例对比从图中可见,在平均响应方面,TCP协议的劣势不明显,在延迟为30ms,丢包率为1%时,改进后的ENET平均RTT为69ms, 原始ENET平均RTT为67ms, TCP平均RTT为67ms;但是从响应时间超过300ms的比例看,在延迟为30ms,丢包率为1%时,改进后的ENET RTT超过300ms的包为0,而TCP RTT超过300ms的比例则超过了2%,如果是在游戏中,这个表现已经能明显影响游戏体验了。结果表明,TCP在网络稍不稳定的情况下就已经有比较大的问题了,改进后的ENET有明显优势。总结测试结果符合预期,在实时性方面,TCP协议的网络抗性欠佳,对MOBA类或其他实时性要求较高的游戏,我们不建议使用TCP作为协议载体。事实上,王者荣耀,乱斗西游的通信协议也确实是基于UDP封装的,别问我是怎么知道的。后话对于开发人员来说,优化协议和同步算法是在已有网络环境下提升用户体验的可用方法,也是较平民化的方法,在网络抖动有限、丢包并不频繁、网络环境不至于太差的情况下,的确能有效提高游戏体验;然而这种方法也存在局限性,在网络环境超出可控范围,如在地铁上、商场里等人潮拥挤、存在网络热点,延迟或丢包率极高的环境中,还是无法解决问题,所谓“巧妇难为无米之炊”,再牛X的协议和算法,也无法点石成金,要从根本上解决问题,最终还是要回到网络质量上。此文已由作者授权腾讯云+社区在各渠道发布获取更多新鲜技术干货,可以关注我们腾讯云技术社区-云加社区官方号及知乎机构号v

January 9, 2019 · 1 min · jiezi

一篇文章带你熟悉 TCP/IP 协议-(三)

一篇文章带你熟悉 TCP/IP协议-(一)-https://segmentfault.com/a/11…一篇文章带你熟悉 TCP/IP协议-(二)-https://segmentfault.com/a/11…一篇文章带你熟悉 TCP/IP协议-(三)-https://segmentfault.com/a/11…四、网络层中的 IP 协议IP(IPv4、IPv6)相当于 OSI 参考模型中的第3层——网络层。网络层的主要作用是“实现终端节点之间的通信”。这种终端节点之间的通信也叫“点对点通信”。网络的下一层——数据链路层的主要作用是在互连同一种数据链路的节点之间进行包传递。而一旦跨越多种数据链路,就需要借助网络层。网络层可以跨越不同的数据链路,即使是在不同的数据链路上也能实现两端节点之间的数据包传输。IP 大致分为三大作用模块,它们是 IP 寻址、路由(最终节点为止的转发)以及 IP 分包与组包。1. IP 地址1.1 IP 地址概述在计算机通信中,为了识别通信对端,必须要有一个类似于地址的识别码进行标识。在数据链路中的 MAC 地址正是用来标识同一个链路中不同计算机的一种识别码。作为网络层的 IP ,也有这种地址信息,一般叫做 IP 地址。IP 地址用于在“连接到网络中的所有主机中识别出进行通信的目标地址”。因此,在 TCP/IP 通信中所有主机或路由器必须设定自己的 IP 地址。不论一台主机与哪种数据链路连接,其 IP 地址的形式都保持不变。IP 地址(IPv4 地址)由32位正整数来表示。IP 地址在计算机内部以二进制方式被处理。然而,由于我们并不习惯于采用二进制方式,我们将32位的 IP 地址以每8位为一组,分成4组,每组以 “.” 隔开,再将每组数转换成十进制数。如下:1.2 IP 地址由网络和主机两部分标识组成如下图,网络标识在数据链路的每个段配置不同的值。网络标识必须保证相互连接的每个段的地址不相重复。而相同段内相连的主机必须有相同的网络地址。IP 地址的“主机标识”则不允许在同一个网段内重复出现。由此,可以通过设置网络地址和主机地址,在相互连接的整个网络中保证每台主机的 IP 地址都不会相互重叠。即 IP 地址具有了唯一性。如下图,IP 包被转发到途中某个路由器时,正是利用目标 IP 地址的网络标识进行路由。因为即使不看主机标识,只要一见到网络标识就能判断出是否为该网段内的主机。1.3 IP 地址的分类IP 地址分为四个级别,分别为A类、B类、C类、D类。它根据 IP 地址中从第 1 位到第 4 位的比特列对其网络标识和主机标识进行区分。A 类 IP 地址是首位以 “0” 开头的地址。从第 1 位到第 8 位是它的网络标识。用十进制表示的话,0.0.0.0127.0.0.0 是 A 类的网络地址。A 类地址的后 24 位相当于主机标识。因此,一个网段内可容纳的主机地址上限为16,777,214个。B 类 IP 地址是前两位 “10” 的地址。从第 1 位到第 16 位是它的网络标识。用十进制表示的话,128.0.0.0191.255.0.0 是 B 类的网络地址。B 类地址的后 16 位相当于主机标识。因此,一个网段内可容纳的主机地址上限为65,534个。C 类 IP 地址是前三位为 “110” 的地址。从第 1 位到第 24 位是它的网络标识。用十进制表示的话,192.0.0.0223.255.255.0 是 C 类的网络地址。C 类地址的后 8 位相当于主机标识。因此,一个网段内可容纳的主机地址上限为254个。D 类 IP 地址是前四位为 “1110” 的地址。从第 1 位到第 32 位是它的网络标识。用十进制表示的话,224.0.0.0239.255.255.255 是 D 类的网络地址。D 类地址没有主机标识,常用于多播。在分配 IP 地址时关于主机标识有一点需要注意。即要用比特位表示主机地址时,不可以全部为 0 或全部为 1。因为全部为 0 只有在表示对应的网络地址或 IP 地址不可以获知的情况下才使用。而全部为 1 的主机通常作为广播地址。因此,在分配过程中,应该去掉这两种情况。这也是为什么 C 类地址每个网段最多只能有 254( 28 - 2 = 254)个主机地址的原因。1.4 广播地址广播地址用于在同一个链路中相互连接的主机之间发送数据包。将 IP 地址中的主机地址部分全部设置为 1,就成了广播地址。广播分为本地广播和直接广播两种。在本网络内的广播叫做本地广播;在不同网络之间的广播叫做直接广播。1.5 IP 多播多播用于将包发送给特定组内的所有主机。由于其直接使用 IP 地址,因此也不存在可靠传输。相比于广播,多播既可以穿透路由器,又可以实现只给那些必要的组发送数据包。请看下图:多播使用 D 类地址。因此,如果从首位开始到第 4 位是 “1110”,就可以认为是多播地址。而剩下的 28 位可以成为多播的组编号。此外, 对于多播,所有的主机(路由器以外的主机和终端主机)必须属于 224.0.0.1 的组,所有的路由器必须属于 224.0.0.2 的组。1.6 子网掩码现在一个 IP 地址的网络标识和主机标识已不再受限于该地址的类别,而是由一个叫做“子网掩码”的识别码通过子网网络地址细分出比 A 类、B 类、C 类更小粒度的网络。这种方式实际上就是将原来 A 类、B 类、C 类等分类中的主机地址部分用作子网地址,可以将原网络分为多个物理网络的一种机制。子网掩码用二进制方式表示的话,也是一个 32 位的数字。它对应 IP 地址网络标识部分的位全部为 “1”,对应 IP 地址主机标识的部分则全部为 “0”。由此,一个 IP 地址可以不再受限于自己的类别,而是可以用这样的子网掩码自由地定位自己的网络标识长度。当然,子网掩码必须是 IP 地址的首位开始连续的 “1”。对于子网掩码,目前有两种表示方式。第一种是,将 IP 地址与子网掩码的地址分别用两行来表示。以 172.20.100.52 的前 26 位是网络地址的情况为例,如下:第二种表示方式是,在每个 IP 地址后面追加网络地址的位数用 “/ ” 隔开,如下:另外,在第二种方式下记述网络地址时可以省略后面的 “0” 。例如:172.20.0.0/26 跟 172.20/26 其实是一个意思。2. 路由发送数据包时所使用的地址是网络层的地址,即 IP 地址。然而仅仅有 IP 地址还不足以实现将数据包发送到对端目标地址,在数据发送过程中还需要类似于“指明路由器或主机”的信息,以便真正发往目标地址。保存这种信息的就是路由控制表。该路由控制表的形成方式有两种:一种是管理员手动设置,另一种是路由器与其他路由器相互交换信息时自动刷新。前者也叫做静态路由控制,而后者叫做动态路由控制。IP 协议始终认为路由表是正确的。然后,IP 本身并没有定义制作路由控制表的协议。即 IP 没有制作路由控制表的机制。该表示由一个叫做“路由协议”的协议制作而成。2.1 IP 地址与路由控制IP 地址的网络地址部分用于进行路由控制。路由控制表中记录着网络地址与下一步应该发送至路由器的地址。在发送 IP 包时,首先要确定 IP 包首部中的目标地址,再从路由控制表中找到与该地址具有相同网络地址的记录,根据该记录将 IP 包转发给相应的下一个路由器。如果路由控制表中存在多条相同网络地址的记录,就选择一个最为吻合的网络地址。3. IP 分包与组包每种数据链路的最大传输单元(MTU)都不尽相同,因为每个不同类型的数据链路的使用目的不同。使用目的不同,可承载的 MTU 也就不同。任何一台主机都有必要对 IP 分片进行相应的处理。分片往往在网络上遇到比较大的报文无法一下子发送出去时才会进行处理。经过分片之后的 IP 数据报在被重组的时候,只能由目标主机进行。路由器虽然做分片但不会进行重组。3.1 路径 MTU 发现分片机制也有它的不足。如路由器的处理负荷加重之类。因此,只要允许,是不希望由路由器进行 IP 数据包的分片处理的。为了应对分片机制的不足,“路径 MTU 发现” 技术应运而生。路径 MTU 指的是,从发送端主机到接收端主机之间不需要分片是最大 MTU 的大小。即路径中存在的所有数据链路中最小的 MTU 。进行路径 MTU 发现,就可以避免在中途的路由器上进行分片处理,也可以在 TCP 中发送更大的包。4. IPv6IPv6(IP version 6)是为了根本解决 IPv4 地址耗尽的问题而被标准化的网际协议。IPv4 的地址长度为 4 个 8 位字节,即 32 比特。而 IPv6 的地址长度则是原来的 4 倍,即 128 比特,一般写成 8 个 16 位字节。4.1 IPv6 的特点IP 得知的扩大与路由控制表的聚合。性能提升。包首部长度采用固定的值(40字节),不再采用首部检验码。简化首部结构,减轻路由器负担。路由器不再做分片处理。支持即插即用功能。即使没有DHCP服务器也可以实现自动分配 IP 地址。采用认证与加密功能。应对伪造 IP 地址的网络安全功能以及防止线路窃听的功能。多播、Mobile IP 成为扩展功能。4.2 IPv6 中 IP 地址的标记方法一般人们将 128 比特 IP 地址以每 16 比特为一组,每组用冒号(“:”)隔开进行标记。而且如果出现连续的 0 时还可以将这些 0 省略,并用两个冒号(“::”)隔开。但是,一个 IP 地址中只允许出现一次两个连续的冒号。4.3 IPv6 地址的结构IPv6 类似 IPv4,也是通过 IP 地址的前几位标识 IP 地址的种类。在互联网通信中,使用一种全局的单播地址。它是互联网中唯一的一个地址,不需要正式分配 IP 地址。4.4 全局单播地址全局单播地址是指世界上唯一的一个地址。它是互联网通信以及各个域内部通信中最为常用的一个 IPv6 地址。格式如下图所示,现在 IPv6 的网络中所使用的格式为,n = 48,m = 16 以及 128 - n - m = 64。即前 64 比特为网络标识,后 64 比特为主机标识。4.5 链路本地单播地址链路本地单播地址是指在同一个数据链路内唯一的地址。它用于不经过路由器,在同一个链路中的通信。通常接口 ID 保存 64 比特版的 MAC 地址。4.6 唯一本地地址唯一本地地址是不进行互联网通信时所用的地址。唯一本地地址虽然不会与互联网连接,但是也会尽可能地随机生成一个唯一的全局 ID。L 通常被置为 1全局 ID 的值随机决定子网 ID 是指该域子网地址接口 ID 即为接口的 ID4.7 IPv6 分段处理IPv6 的分片处理只在作为起点的发送端主机上进行,路由器不参与分片。IPv6 中最小 MTU 为 1280 字节,因此,在嵌入式系统中对于那些有一定系统资源限制的设备来说,不需要进行“路径 MTU 发现”,而是在发送 IP 包时直接以 1280 字节为单位分片送出。4.8 IP 首部(暂略)5. IP 协议相关技术IP 旨在让最终目标主机收到数据包,但是在这一过程中仅仅有 IP 是无法实现通信的。必须还有能够解析主机名称和 MAC 地址的功能,以及数据包在发送过程中异常情况处理的功能。5.1 DNS我们平常在访问某个网站时不适用 IP 地址,而是用一串由罗马字和点号组成的字符串。而一般用户在使用 TCP/IP 进行通信时也不使用 IP 地址。能够这样做是因为有了 DNS (Domain Name System)功能的支持。DNS 可以将那串字符串自动转换为具体的 IP 地址。这种 DNS 不仅适用于 IPv4,还适用于 IPv6。5.2 ARP只要确定了 IP 地址,就可以向这个目标地址发送 IP 数据报。然而,在底层数据链路层,进行实际通信时却有必要了解每个 IP 地址所对应的 MAC 地址。ARP 是一种解决地址问题的协议。以目标 IP 地址为线索,用来定位下一个应该接收数据分包的网络设备对应的 MAC 地址。不过 ARP 只适用于 IPv4,不能用于 IPv6。IPv6 中可以用 ICMPv6 替代 ARP 发送邻居探索消息。RARP 是将 ARP 反过来,从 MAC 地址定位 IP 地址的一种协议。5.3 ICMPICMP 的主要功能包括,确认 IP 包是否成功送达目标地址,通知在发送过程当中 IP 包被废弃的具体原因,改善网络设置等。IPv4 中 ICMP 仅作为一个辅助作用支持 IPv4。也就是说,在 IPv4 时期,即使没有 ICMP,仍然可以实现 IP 通信。然而,在 IPv6 中,ICMP 的作用被扩大,如果没有 ICMPv6,IPv6 就无法进行正常通信。5.4 DHCP如果逐一为每一台主机设置 IP 地址会是非常繁琐的事情。特别是在移动使用笔记本电脑、只能终端以及平板电脑等设备时,每移动到一个新的地方,都要重新设置 IP 地址。于是,为了实现自动设置 IP 地址、统一管理 IP 地址分配,就产生了 DHCP(Dynamic Host Configuration Protocol)协议。有了 DHCP,计算机只要连接到网络,就可以进行 TCP/IP 通信。也就是说,DHCP 让即插即用变得可能。DHCP 不仅在 IPv4 中,在 IPv6 中也可以使用。5.5 NATNAT(Network Address Translator)是用于在本地网络中使用私有地址,在连接互联网时转而使用全局 IP 地址的技术。除转换 IP 地址外,还出现了可以转换 TCP、UDP 端口号的 NAPT(Network Address Ports Translator)技术,由此可以实现用一个全局 IP 地址与多个主机的通信。NAT(NAPT)实际上是为正在面临地址枯竭的 IPv4 而开发的技术。不过,在 IPv6 中为了提高网络安全也在使用 NAT,在 IPv4 和 IPv6 之间的相互通信当中常常使用 NAT-PT。5.6 IP 隧道如上图的网络环境中,网络 A 与网络 B 之间无法直接进行通信,为了让它们之间正常通信,这时必须得采用 IP 隧道的功能。IP 隧道可以将那些从网络 A 发过来的 IPv6 的包统合为一个数据,再为之追加一个 IPv4 的首部以后转发给网络 C。一般情况下,紧接着 IP 首部的是 TCP 或 UDP 的首部。然而,现在的应用当中“ IP 首部的后面还是 IP 首部”或者“ IP 首部的后面是 IPv6 ...

December 10, 2018 · 3 min · jiezi

一篇文章带你熟悉 TCP/IP 协议-(二)

三、传输层中的 TCP 和 UDPTCP/IP 中有两个具有代表性的传输层协议,分别是 TCP 和 UDP。TCP 是面向连接的、可靠的流协议。流就是指不间断的数据结构,当应用程序采用 TCP 发送消息时,虽然可以保证发送的顺序,但还是犹如没有任何间隔的数据流发送给接收端。TCP 为提供可靠性传输,实行“顺序控制”或“重发控制”机制。此外还具备“流控制(流量控制)”、“拥塞控制”、提高网络利用率等众多功能。UDP 是不具有可靠性的数据报协议。细微的处理它会交给上层的应用去完成。在 UDP 的情况下,虽然可以确保发送消息的大小,却不能保证消息一定会到达。因此,应用有时会根据自己的需要进行重发处理。TCP 和 UDP 的优缺点无法简单地、绝对地去做比较:TCP 用于在传输层有必要实现可靠传输的情况;而在一方面,UDP 主要用于那些对高速传输和实时性有较高要求的通信或广播通信。TCP 和 UDP 应该根据应用的目的按需使用。1. 端口号数据链路和 IP 中的地址,分别指的是 MAC 地址和 IP 地址。前者用来识别同一链路中不同的计算机,后者用来识别 TCP/IP 网络中互连的主机和路由器。在传输层也有这种类似于地址的概念,那就是端口号。端口号用来识别同一台计算机中进行通信的不同应用程序。因此,它也被称为程序地址。1.1 根据端口号识别应用一台计算机上同时可以运行多个程序。传输层协议正是利用这些端口号识别本机中正在进行通信的应用程序,并准确地将数据传输。1.2 通过 IP 地址、端口号、协议号进行通信识别仅凭目标端口号识别某一个通信是远远不够的。① 和② 的通信是在两台计算机上进行的。它们的目标端口号相同,都是80。这里可以根据源端口号加以区分。③ 和 ① 的目标端口号和源端口号完全相同,但它们各自的源 IP 地址不同。此外,当 IP 地址和端口号全都一样时,我们还可以通过协议号来区分(TCP 和 UDP)。1.3 端口号的确定标准既定的端口号:这种方法也叫静态方法。它是指每个应用程序都有其指定的端口号。但并不是说可以随意使用任何一个端口号。例如 HTTP、FTP、TELNET 等广为使用的应用协议中所使用的端口号就是固定的。这些端口号被称为知名端口号,分布在 01023 之间;除知名端口号之外,还有一些端口号被正式注册,它们分布在 102449151 之间,不过这些端口号可用于任何通信用途。时序分配法:服务器有必要确定监听端口号,但是接受服务的客户端没必要确定端口号。在这种方法下,客户端应用程序完全可以不用自己设置端口号,而全权交给操作系统进行分配。动态分配的端口号范围在 49152~65535 之间。1.4 端口号与协议端口号由其使用的传输层协议决定。因此,不同的传输层协议可以使用相同的端口号。此外,那些知名端口号与传输层协议并无关系。只要端口一致都将分配同一种应用程序进行处理。2. UDPUDP 不提供复杂的控制机制,利用 IP 提供面向无连接的通信服务。并且它是将应用程序发来的数据在收到的那一刻,立即按照原样发送到网络上的一种机制。即使是出现网络拥堵的情况,UDP 也无法进行流量控制等避免网络拥塞行为。此外,传输途中出现丢包,UDP 也不负责重发。甚至当包的到达顺序出现乱序时也没有纠正的功能。如果需要以上的细节控制,不得不交由采用 UDP 的应用程序去处理。UDP 常用于一下几个方面:1.包总量较少的通信(DNS、SNMP等);2.视频、音频等多媒体通信(即时通信);3.限定于 LAN 等特定网络中的应用通信;4.广播通信(广播、多播)。3. TCPTCP 与 UDP 的区别相当大。它充分地实现了数据传输时各种控制功能,可以进行丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。而这些在 UDP 中都没有。此外,TCP 作为一种面向有连接的协议,只有在确认通信对端存在时才会发送数据,从而可以控制通信流量的浪费。根据 TCP 的这些机制,在 IP 这种无连接的网络上也能够实现高可靠性的通信( 主要通过检验和、序列号、确认应答、重发控制、连接管理以及窗口控制等机制实现)。3.1 三次握手(重点)TCP 提供面向有连接的通信传输。面向有连接是指在数据通信开始之前先做好两端之间的准备工作。所谓三次握手是指建立一个 TCP 连接时需要客户端和服务器端总共发送三个包以确认连接的建立。在socket编程中,这一过程由客户端执行connect来触发。下面来看看三次握手的流程图:第一次握手:客户端将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给服务器端,客户端进入SYN_SENT状态,等待服务器端确认。第二次握手:服务器端收到数据包后由标志位SYN=1知道客户端请求建立连接,服务器端将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给客户端以确认连接请求,服务器端进入SYN_RCVD状态。第三次握手:客户端收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给服务器端,服务器端检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,客户端和服务器端进入ESTABLISHED状态,完成三次握手,随后客户端与服务器端之间可以开始传输数据了。3.2 四次挥手(重点)四次挥手即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发。由于TCP连接是全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。下面来看看四次挥手的流程图:中断连接端可以是客户端,也可以是服务器端。第一次挥手:客户端发送一个FIN=M,用来关闭客户端到服务器端的数据传送,客户端进入FIN_WAIT_1状态。意思是说"我客户端没有数据要发给你了",但是如果你服务器端还有数据没有发送完成,则不必急着关闭连接,可以继续发送数据。第二次挥手:服务器端收到FIN后,先发送ack=M+1,告诉客户端,你的请求我收到了,但是我还没准备好,请继续你等我的消息。这个时候客户端就进入FIN_WAIT_2 状态,继续等待服务器端的FIN报文。第三次挥手:当服务器端确定数据已发送完成,则向客户端发送FIN=N报文,告诉客户端,好了,我这边数据发完了,准备好关闭连接了。服务器端进入LAST_ACK状态。第四次挥手:客户端收到FIN=N报文后,就知道可以关闭连接了,但是他还是不相信网络,怕服务器端不知道要关闭,所以发送ack=N+1后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。服务器端收到ACK后,就知道可以断开连接了。客户端等待了2MSL后依然没有收到回复,则证明服务器端已正常关闭,那好,我客户端也可以关闭连接了。最终完成了四次握手。上面是一方主动关闭,另一方被动关闭的情况,实际中还会出现同时发起主动关闭的情况,具体流程如下图:3.3 通过序列号与确认应答提高可靠性在 TCP 中,当发送端的数据到达接收主机时,接收端主机会返回一个已收到消息的通知。这个消息叫做确认应答(ACK)。当发送端将数据发出之后会等待对端的确认应答。如果有确认应答,说明数据已经成功到达对端。反之,则数据丢失的可能性很大。在一定时间内没有等待到确认应答,发送端就可以认为数据已经丢失,并进行重发。由此,即使产生了丢包,仍然能够保证数据能够到达对端,实现可靠传输。未收到确认应答并不意味着数据一定丢失。也有可能是数据对方已经收到,只是返回的确认应答在途中丢失。这种情况也会导致发送端误以为数据没有到达目的地而重发数据。此外,也有可能因为一些其他原因导致确认应答延迟到达,在源主机重发数据以后才到达的情况也屡见不鲜。此时,源主机只要按照机制重发数据即可。对于目标主机来说,反复收到相同的数据是不可取的。为了对上层应用提供可靠的传输,目标主机必须放弃重复的数据包。为此我们引入了序列号。序列号是按照顺序给发送数据的每一个字节(8位字节)都标上号码的编号。接收端查询接收数据 TCP 首部中的序列号和数据的长度,将自己下一步应该接收的序列号作为确认应答返送回去。通过序列号和确认应答号,TCP 能够识别是否已经接收数据,又能够判断是否需要接收,从而实现可靠传输。3.4 重发超时的确定重发超时是指在重发数据之前,等待确认应答到来的那个特定时间间隔。如果超过这个时间仍未收到确认应答,发送端将进行数据重发。最理想的是,找到一个最小时间,它能保证“确认应答一定能在这个时间内返回”。TCP 要求不论处在何种网络环境下都要提供高性能通信,并且无论网络拥堵情况发生何种变化,都必须保持这一特性。为此,它在每次发包时都会计算往返时间及其偏差。将这个往返时间和偏差时间相加,重发超时的时间就是比这个总和要稍大一点的值。在 BSD 的 Unix 以及 Windows 系统中,超时都以0.5秒为单位进行控制,因此重发超时都是0.5秒的整数倍。不过,最初其重发超时的默认值一般设置为6秒左右。数据被重发之后若还是收不到确认应答,则进行再次发送。此时,等待确认应答的时间将会以2倍、4倍的指数函数延长。此外,数据也不会被无限、反复地重发。达到一定重发次数之后,如果仍没有任何确认应答返回,就会判断为网络或对端主机发生了异常,强制关闭连接。并且通知应用通信异常强行终止。3.5 以段为单位发送数据在建立 TCP 连接的同时,也可以确定发送数据包的单位,我们也可以称其为“最大消息长度”(MSS)。最理想的情况是,最大消息长度正好是 IP 中不会被分片处理的最大数据长度。TCP 在传送大量数据时,是以 MSS 的大小将数据进行分割发送。进行重发时也是以 MSS 为单位。MSS 在三次握手的时候,在两端主机之间被计算得出。两端的主机在发出建立连接的请求时,会在 TCP 首部中写入 MSS 选项,告诉对方自己的接口能够适应的 MSS 的大小。然后会在两者之间选择一个较小的值投入使用。3.6 利用窗口控制提高速度TCP 以1个段为单位,每发送一个段进行一次确认应答的处理。这样的传输方式有一个缺点,就是包的往返时间越长通信性能就越低。为解决这个问题,TCP 引入了窗口这个概念。确认应答不再是以每个分段,而是以更大的单位进行确认,转发时间将会被大幅地缩短。也就是说,发送端主机,在发送了一个段以后不必要一直等待确认应答,而是继续发送。如下图所示:窗口大小就是指无需等待确认应答而可以继续发送数据的最大值。上图中窗口大小为4个段。这个机制实现了使用大量的缓冲区,通过对多个段同时进行确认应答的功能。3.7 滑动窗口控制上图中的窗口内的数据即便没有收到确认应答也可以被发送出去。不过,在整个窗口的确认应答没有到达之前,如果其中部分数据出现丢包,那么发送端仍然要负责重传。为此,发送端主机需要设置缓存保留这些待被重传的数据,直到收到他们的确认应答。在滑动窗口以外的部分包括未发送的数据以及已经确认对端已收到的数据。当数据发出后若如期收到确认应答就可以不用再进行重发,此时数据就可以从缓存区清除。收到确认应答的情况下,将窗口滑动到确认应答中的序列号的位置。这样可以顺序地将多个段同时发送提高通信性能。这种机制也别称为滑动窗口控制。3.8 窗口控制中的重发控制在使用窗口控制中, 出现丢包一般分为两种情况:① 确认应答未能返回的情况。在这种情况下,数据已经到达对端,是不需要再进行重发的,如下图:② 某个报文段丢失的情况。接收主机如果收到一个自己应该接收的序列号以外的数据时,会针对当前为止收到数据返回确认应答。如下图所示,当某一报文段丢失后,发送端会一直收到序号为1001的确认应答,因此,在窗口比较大,又出现报文段丢失的情况下,同一个序列号的确认应答将会被重复不断地返回。而发送端主机如果连续3次收到同一个确认应答,就会将其对应的数据进行重发。这种机制比之前提到的超时管理更加高效,因此也被称为高速重发控制。 ...

December 6, 2018 · 1 min · jiezi

网络协议之 - HTTP

前言关于HTTP的知识比较繁杂,也比较零散,于是想要通过这篇文章对常用知识点进行总结,一些知识点描述是从网上搜集而来,如有侵权,可以联系我进行修改。提出问题Http的报文结构。Http request的几种类型。Http的状态码含义。Http1.1和Http1.0的区别,以及缓存原理Http长连接keep-alive。Cookie与Session的作用于原理。电脑上访问一个网页,整个过程是怎么样的:DNS、HTTP、TCP、OSPF、IP、ARP。解答1. Http的报文结构http协议的请求报文和响应报文都是由以下4部分组成:请求行请求头空行 CR + LF,回车 + 换行请求体2. Http request的几种类型请求行Request格式:【方法 URL HTTP版本】 例如: GET /csrfToken HTTP/1.1HTTP版本:目前有 HTTP/1.0、HTTP/1.1、HTTP/2.0 版本,其中 HTTP1.1 版本使用较广泛方法说明支持HTTP协议版本GET获取资源1.0 、1.1POST传输实体主体1.0、1.1PUT传输文件1.0、1.1HEAD获得报文首部1.0、1.1DELETE删除资源1.0、1.1OPTIONS询问支持的方法1.1TRACE追踪路径1.1CONNECT要求用隧道协议连接代理1.1LINK建立和资源之间的联系1.0UNLINK断开连接关系1.0Response格式:【HTTP版本 状态码 描述】 例如: HTTP/1.1 200 OK、HTTP/1.1 404 NOT FOUND 类别原因短语1xxInformational(信息性状态码)接收的请求正在处理2xxSuccess(成功状态码)请求正常处理完毕3xxRedirection(重定向状态码)需要进行附加操作以完成请求4xxClient Error(客户端错误状态码)服务器无法处理请求5xxServer Error(服务器错误状态码)服务器处理请求出错3. Http的状态码含义常用状态码200:OK,请求被正常处理204:No Content,请求被受理但没有资源可以返回,返回204响应,浏览器显示的页面不发生更新206:Partial Content,客户端进行范围请求,服务器成功执行了这部分的GET请求,响应报文中包含由Content-Range指定范围的实体内容301:Moved Permanently,永久性重定向,比如访问http://test.zhixue.com/zbptadmin,服务器会返回301,response的headers中会包含一个字段:Location: http://test.zhixue.com/zbptadmin/,浏览器会按照这个地址重新请求,并且如果用户保存了书签,浏览器会自动按照Location更新书签302:Found,临时性重定向,和301类似,但是浏览器不会更新书签303:See Other,和302类似,但303明确表示客户端应该使用GET方法获取Location资源备注:当301,302,303响应状态码返回时,几乎所有的浏览器都会把POST改成GET,并删除请求报文内的主体,之后请求会自动再次发送。301,302标准是禁止将POST方法改成GET方法的,但实际使用时浏览器厂商都会这么做。304:Not Modified,发送附带条件的请求时,(附带条件的请求是指采用GET方法的请求报文中包含If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since中任一首部),条件不满足返回304,可直接使用客户端缓存,与重定向无关307:Temporary Redirect,临时重定向,与302类似,只是强制要求使用POST方法400:Bad Request,请求报文中存在语法错误,服务器无法识别401:Unauthorized,请求需要认证403:Forbidden,请求对应的资源禁止被访问404:Not Found,服务器无法找到对应资源500:Internal Server Error,服务器内部错误503:Service Unavailable,服务器正忙常见HTTP首部字段通用首部字段(请求报文与响应报文都会使用的首部字段)Date:创建报文的时间Connection:连接的管理Cache-Control:缓存的控制Transfer-Encoding:报文主题的传输编码方式请求首部字段(请求报文会使用的首部字段)Host:请求资源所在的服务器Accept:可处理的媒体类型Accept-Charset:可接收的字符集Accept-Encoding:可接收的内容编码Accept-Language:可接收的自然语言响应首部字段(响应报文会使用的首部字段)Accept-Range:可接收的字节范围Location:让客户端重定向到的URIServer:HTTP服务器的安装信息实体首部字段(请求报文与响应报文的实体部分使用的首部字段)Allow:资源可支持的HTTP方法Content-Type:实体主类的类型Content-Encoding:实体主体适用的编码方式Content-Language:实体主体的自然语言Content-Length:实体主体的字节数Content-Range:实体主体的位置范围,一般用于发出部分请求时使用4. HTTP1.0、HTTP1.1、HTTP2.0区别HTTP1.0 和 HTTP1.1 主要区别长连接HTTP1.0需要使用keep-alive参数告知服务器要建立一个长连接,而HTTP1.1默认支持长连接HTTP是基于TCP/IP协议的,创建一个TCP连接是需要经过三次握手的,有一定的开销,如果每次通讯都要重新建立连接的话,对性能有影响。因此最好能维持一个长连接,可以用这个长连接来发送多个请求节约带宽HTTP1.1支持只发送header信息,也就是HTTP的HEAD Method,如果服务器认为客户端有权限请求服务器,则返回100,否则返回401。客户端如果接收到100,才开始把请求体body发送到服务器。这样,当服务器返回401的时候,客户端就可以不用发送请求体了,节约了带宽HTTP1.1支持分块传输,比如206状态码,由Content-Range指定传输内容,这是支持文件断点续传的基础。HOST域现在一台服务器上可以有多个虚拟主机,这些虚拟站点可以共享同一个ip和端口,HTTP1.0是没有host域的,HTTP1.1才支持这个参数HTTP1.1 和 HTTP2.0的区别多路复用HTTP2.0使用了多路复用的技术,做到同一个连接并发处理多个请求,而且并发请求的数量比HTTP1.1大了好几个数量级当然HTTP1.1也可以多建立几个TCP连接,来支持处理更多并发的请求,但是创建TCP连接本身也是有开销的TCP连接有一个预热和保护的过程,先检查数据是否传送成功,一旦成功过,则慢慢加大传输速度。因此对应瞬时并发的连接,服务器的响应就会变慢。所以最好能使用一个建立的连接,并且这个连接可以支持瞬时并发的请求HTTP/1.1,若干个请求排队串行化单线程处理,后面的请求等待前面请求的返回才能获得执行机会,一旦有某个请求超时,后续请求只能被阻塞,也就是人们常说的线头阻塞HTTP/2.0,多个请求可同时在一个连接上并行执行,某个任务耗时严重,不会影响到其他连接的正常执行数据压缩HTTP1.1不支持header数据的压缩,HTTP2.0使用HPACK算法对header的数据进行压缩,这样数据体积小了,在网络上传输就会更快服务器推送当我们对HTTP2.0的web server请求数据的时候,服务器会顺便把一些客户端需要的资源一起推送到客户端,免得客户端再次创建连接发送请求到服务器获取。这种方式非常适合加载静态资源。服务器推送的这些资源其实存在客户端的某个地方,客户端直接从本地加载这些资源就可以了,不用走网络,速度自然快很多。HTTP缓存缓存分类强缓存浏览器在加载资源时,先根据这个资源的一些http header判断它是否命中强缓存,如果命中,浏览器直接从自己的缓存中读取资源,不会发请求到服务器,此时状态码是200,但是看Size项是from memory cache或from disk cache协商缓存当强缓存没有命中时,浏览器一定会发送一个请求到服务器,通过服务器端依据资源的另外一些http header验证这个资源是否命中协商缓存,如果命中,服务器会将这个请求返回304,但是不会返回这个资源的数据,而是告诉客户端可以直接从缓存中加载这个资源,于是浏览器就又会从自己的缓存中去加载这个资源;如果没有命中,则将资源返回客户端,状态为200,浏览器同时依据response header中的相关项更新本地缓存数据from memory cache 和 from disk cache区别from memory cache 是从内存中读取缓存资源,很快,关闭浏览器后,内存中的资源就消失了from disk cache 是从磁盘中读取缓存资源,要比 from memory cache 慢,但是持久化,关闭浏览器后仍然存在哪些资源存在memory,哪些资源存在disk看了一些文章,大部分观点是说:资源在disk和memory中都会存当关闭浏览器,再打开那个页面的时候,从disk cache中获取缓存资源,同时将缓存资源存在了内存中,当再次刷新页面的时候,就从memory cache中读取,因为这样会更快一些我自己试了一些页面,再次刷新还是有的from disk cache,有的from memory cache,所以这个持保留观点还有的文章说css文件存在disk中,js等脚本存在memory中,个人认为这个不太靠谱,因为memory中的缓存在关闭浏览器就消失了,如果js只存在memory,就起不到缓存的作用了强缓存相关http headerExpiresExpires的值是服务端返回的到期时间,用GMT格式的字符串表示,如:Expires: Thu, 31 Dec 2016 23:55:55 GMT。即下一次请求时,请求时间小于服务器返回的到期时间,直接使用缓存数据。不过Expires是HTTP1.0的东西,现在浏览器默认使用HTTP1.1,所以它的作用基本忽略。另一个问题是,到期时间是由服务器生成的,但是客户端时间可能和服务器时间有偏差,这就会导致缓存命中的误差。所以HTTP1.1的版本中,使用Cache-Control替代。Cache-ControlCache-Control是最重要的规则。常见的取值有:- private:客户端可以缓存- public:客户端和代理服务器都可以缓存- max-age=xxx:缓存的内容将在xxx秒后失效,单位是秒- no-cache:需要使用协商缓存来验证缓存数据- no-store:不缓存协商缓存相关http header第1组:Last-Modified/If-Modified—SinceLast-Modified:第一次请求资源时,服务器返回的http header,告诉浏览器资源的最后修改时间,为GMT格式,如Last-Modified: Thu, 24 Jan 2017 23:55:55 GMTIf-Modified-Since:再次请求服务器资源时,浏览器设置在请求header中,值 为该资源第一次请求时服务器设置的Last-Modified`值,如If-Modified-Since: Thu, 24 Jan 2017 23:55:55 GMT,服务器收到请求后发现request header中有If-Modified-Since,则与被请求资源的最后修改时间进行比对。若资源的最后修改时间大于If-Modified-Since,说明资源又被改动过,则返回资源内容,状态码200,同时浏览器依据相应response header更新缓存资源;若资源的最后修改时间小于或等于If-Modified-Since,说明资源无新修改,则返回状态码304,但是不返回资源,告知浏览器继续使用所保存的cache第2组:Etag/If-None-MatchEtag:服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器确定),如Etag: W/“5886c231-8d9"If-None-Match:再次请求服务器时,通过此字段告知服务器该资源的唯一标识,如If-None-Match: W/“5886c231-8d9”,服务器收到请求后发现request header中有If-None-Match,则与被请求资源的唯一标识进行比对,若不同,说明资源又被改动过,则返回资源内容,状态码200,同时浏览器依据相应response header更新缓存资源;若相同,则说明资源无更改,返回304,告知浏览器继续使用所保存的缓存资源为什么要有Etag?Last-Modified颗粒度是秒,只能记录秒级的修改,比如1s内修改了N次,If-Modified-Since就无法判断了,所以要引入Etag。总结先执行强缓存策略,服务器通知浏览器一个缓存有效时间,在有效时间内,下次请求时直接使用缓存,不发起http请求,缓存从from memory cache或from disk cache中读取,若超过了有效时间,则执行协商缓存策略对于协商缓存,将缓存信息中的Etag和Last-Modified的值通过If-None-Match和If-Modified-Since发送给服务器,由服务器进行校验,若资源无更改,返回304,浏览器继续使用缓存,若资源被更改,则返回资源,状态码200,同时浏览器更新缓存流程图浏览器第一次请求:浏览器第二次请求:5. Http长连接keep-alive三个概念短连接所谓短连接,就是每次请求一个资源就建立连接,请求完成后立马关闭。每次请求都经过“创建TCP连接 -> 请求资源 -> 响应资源 -> 释放连接”。长连接所谓长连接(persistent connection),就是只建立一次TCP连接,多次HTTP请求都复用该连接。并行连接所谓并行连接(multiple connection),其实就是并发的短连接。keep-alive在HTTP/1.0里,为了实现client到web-server能支持长连接,必须在HTTP请求头里显式指定Connection: keep-alive在HTTP/1.1里,就默认开启了keep-alive,要关闭keep-alive必须在HTTP请求头里显式指定Connection: close现在大多数浏览器都默认是使用HTTP/1.1,所以keep-alive都是默认打开的。一旦client和server达成协议,那么长连接就建立好了。keepalive_timeoutHttpd守护进程,一般都提供了keep-alive timeout时间设置参数。比如nginx的keepalive_timeout,和Apache的KeepAliveTimeout。这个keepalive_timout时间值意味着:一个http产生的tcp连接在传送完最后一个响应后,还需要hold住keepalive_timeout秒后,才开始关闭这个连接。Nginx配置中的keepalive_timeout默认为75s,6. cookie与Session这个重点在于理解,这里就不赘述了。7. 网页经历了什么这个东西很多,后面会专门写一篇文章来进行说明。参考文章:HTTP1.0、HTTP1.1 和 HTTP2.0 的区别彻底弄懂HTTP缓存机制及原理What is the difference between memory cache and disk cache in Chrome?理解HTTP之keep-alive ...

October 19, 2018 · 1 min · jiezi