受到很多引人入胜的标题党的影响,我终于决定,要起一个比他们还标题党的题目,打不过还不能加入吗,嘿嘿。
网络编程一直是我的弱项,其实归根结底还是我太懒了,一看到那个osi七层模型,TCP/IP模型还有那个来我往的TCP三次握手,四次挥手图,我就头疼,那么多参数,我咋记得住。唉,虽然平时用的少,但是作为逼格小王子,这装逼的基本功还是不能落下。既然记不住,那咋办呢,那就看看他们为啥要这么搞呢,这些层在干嘛,为啥要这么设计呢,接下来咱就一一分析。
说起网络,咱首先就不得不说计算机网络的体系结构->OSI七层模型和TCP/IP模型:
OSI七层模型:
百度上的介绍是这样的:参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系,一般称为OSI参考模型或七层模型。这七层分别为:应用层,表示层,会话层,传输层,网络层,数据链路层,物理层。更为详细的这里可以给个链接,我就不抄袭别人的劳动成果了:https://www.cnblogs.com/qishui/p/5428938.html。
但是由于ISO这个组织,逼格太高,设计出的七层模型虽然很牛逼,但是确实在实际使用时,不是那么的接地气,所以由IEEE(电气和电子工程师协会)提出的可行性更高的TCP/IP模型成为了事实上的标准。
TCP/IP模型:
TCP/IP模型分为应用层(对应osi的应,表,会三层),表传输层,网络层,链路层(对应osi数,物两层),这里我列了一下常见的协议对应关系:
除了链路层可能比较陌生一点,其他的基本上大家都听过,我们用一个可靠的http请求举例:
1.首先会在应用层将这个数据编码并决定建立会话,
2.然后在传输层附加TCP首部(包含序号和重传确认参数),
3.之后在网络层附加IP包(主要包含源ip和目标ip)
4.最后在数据链路层附加以太网首部(主要包含MAC地址),然后通过物理层传输出去
对端接受还是按这个顺序拆包,一一解析。
写到这里估计很多人还是不知道为啥要设计这么多层,我们带着上面的这些步骤来想一下,首先,http请求那必然是需要http协议,对端接收也会按照这个协议来解析,这点很简单,而传输层的TCP三次握手和四次挥手可以保证连接的可靠性,并且TCP这一层会包含序号和重传确认,可以保证对端即使没有顺序接收到请求报,但依然可以按照顺序接受并组装,而TCP包所包含的重传确认可以保证在一定时间内如果没有收到确认回复会再次发一个包,同时序号保证即便多发了包可以将多余的数据丢弃,保证数据的完整性和可靠性。网络层附加的目标ip通过参数路由表找到对端地址,源ip标识请求程序来源,我们经常会用来控制访问白名单限制,最后的链路层MAC地址判断是否发给自己的,若不是则丢弃。
什么是TCP
TCP是面向连接的通信协议,它通过三次握手建立连接,在传输完成后,需要通过四次挥手解除连接,上面也说到了,TCP会通过重传确认和序号保证数据的完整性和可靠性,同时TCP还可以通过滑动窗口控制每个包的大小,防止发送端发送的数据对端缓存不够大导致数据丢失。TCP还允许通信双方同时进行数据传输,因此我们说TCP是双全工的。
三次握手
tcp三次握手确实不是很好记,我们做业务的程序员一般也不会接触到这块,但是,理解了tcp三次握手的意义还是很重要的,不过我们还是要先结合图来看一下:
注:左边这张图是我联想到的便于理解,右边才是正经的三次握手
1.首先客户端会发一个请求,SYN=1,seq=J,SYN=1标识这是一个建立连接请求,seq=J是一个序列号随机数,标识这次请求,然后将客户端置为SYN_SENT状态,
2.之后服务端收到请求,如果没问题就给一个回复吧,ACK=1标识这次请求为应答连接请求,并回复ack=J+1表示当前是对seq=J的回复,并将状态置为SYN_RCVD,同时服务端也要发一个建立连接的请求,和之前意义SYN=1,seq=k , k又是一个随机数, 设计三次握手的大佬呢又觉得你一个人连续发两次有点小孤单,就把两次请求合并在一起了,即上面SYN=1,seq=k;ACK=1,ack=J+1。
3.最后客户端也要回复一下表示我也同意了啊,于是发了一个ACK=1,ack=k+1回去了,并将状态置为ESTABLISHED,服务端收到也将状态置为ESTABLISHED,表示双方建立连接成功了,可以发消息了。其实三次握手和普通请求一样的,就像武林高手过招前要相互试探一下,不怎么花费资源,如果有一方试探的时候嗝屁了,就没有继续比的必要了。我
为什么是三次握手
回答这个问题之前我们要知道的一件事是三次握手是为了干嘛,其实就是为了确认双方都能友好的建立一个相对稳定连接,就跟相亲一样,男方发一句“你好,约吗”,女方回一句“约啊,在北操场的小树林可以吗”,男方回:“不见不散”,这样才能进行后续的猛烈操作。中间有一个环节断了,就断了。回到正题,客户端发一次请求告诉服务端我要和你建立连接,服务端收到并回复好的,同时也要告诉客户端我要和你建立连接,然后客户端在回复好的,我想最初的模型可能就是和上面左边图一样(那么可能现在就叫四次握手,四次挥手了),不过握手算是将二三次合并为一次,也就是现在的三次握手。为啥三次呢,首先两次肯定是不行的,不能保证双方都建立通信,而目前的逻辑三次已经足够双方建立连接了,也就不需要更多了,资源毕竟是有限的嘛。
四次分手:
其实三次握手我联想到四次握手也是研究了四次分手之后想到的,我们也来看一下四次分手图,百度上copy过来的,懒得画了:
其实可以对照三次握手来看
1.首先客户端发送FIN断连请求,
2.服务端接收到请求后,判断可以断连则给客户端一个ACK应答
3.服务端发送一个FIN断连请求
4.客户端接收请求后,判断可以断连则给服务端一个ACK应答
相信看懂了三次握手的小伙伴对四次挥手理解起来就很容易了,但是有一个问题,为啥三次握手可以将二三次请求合并为一次,四次挥手咋就不行呢?原因在于客户端发起断连,说明客户端没有数据可以发送了,服务端响应只是表示服务端收到了断连请求,必须要等待服务端数据处理完毕才会发起断连请求,因此,四次挥手是不可以合并的。但三次握手不一样,他不用担心这些问题,毕竟还没开始呢,哪来的数据。
http请求完整过程
1.首先进行DNS域名解析:
1.1首先搜索浏览器DNS缓存,搜索不到的话会去操作系统DNS缓存找,找不到去host文件找,最后才会去域名服务器找
2.三次握手建立TCP连接
3.客户端正式发起http请求
4.服务端响应请求
5.客户端处理资源,如html则解析html代码,有js/css等去请求资源
6.渲染页面
7.关闭TCP连接
一般情况短连接到此就结束了,但我们所谓的长连接则会在3-6步骤重复执行,直到需要结束,再关闭TCP连接。
之前在了解http请求的时候,一直在想的一个问题就是:这一个请求如我的博客地址:https://www.cnblogs.com/gmt-hao/p/14502063.html,咋找到对方服务器并被对应程序接受到执行的?
首先https://表示网络中使用的协议是https,而www.cnblogs.com就是我们所说的域名,它会通过域名解析找到对应的ip和端口,ip可以对应找到指定服务器位置,而端口则可以找到当前服务器对应的程序,当然像博客园这样比较大的网站肯定是有网关的,或通过nginx等做路由转发到其他具体的服务器上。/gmt-hao/p/则是我们的虚拟目录,最后根据14502063.html找到目录下对应的资源。
总结:
这篇文章写的还是比较简单的,只是像简单介绍下网络编程的基础,以及我在学习的过程中思考的问题,希望能够帮助到正在学习或者想要学习的小伙伴吧!!!