三大通识知识:进程,线程,网络(四)

tech2024-11-06  20

三大通识知识(一) :进程,线程,网络之间的关系 三大通识知识(二):进程实现原理 三大通识知识(三):线程实现原理 三大通识知识(四):网络 三大通识知识(五):TCP服务器 进程,线程,网络视频连接

前言

这节课我们介绍网络部分,包括如何搭建网络服务器,以及如何使用多线程技术支持多客户端。

什么是网络

网络是一个很复杂的体系,这个体系有多复杂呢?我记得我们当时很流行看《TCP/IP详解》这套书有三本大部头,卷一,卷二,卷三,当当有卖:因为当年做路由器,交换机开发的人非常多(处于网络基建阶段),所以基本上有一半的程序员看过这本书。

整个体系是以TCP/IP展开的,我们不能在这里介绍整个体系知识,但是我会以最快,最佳的角度切入,让大家理解。

什么是TCP/IP

这里T是Transmission的意思,表示传输,C是 Control的意思,表示控制, P是Protocol的意思,表示协议。 I是 Internet 的意思,表示因特网,P是Protocol的意思,表示协议。所以,TCP是传输控制协议,IP是网络协议。 整个网络包括很多协议,UDP(用户报文协议,常用于游戏开发),HTTP(网页开发),SMTP(邮件协议),TELNET(远程登陆),ARP(ping一个电脑是否网络是通的常用到)。。。 这么多协议,为什么选TCP/IP来概况整个网络体系呢? 这涉及到整个网络的一个模型!——OSI

什么是OSI网络模型

这里O是Open的意思,意旨开放; S是system的意思,意旨系统; I是interface的意思,意旨接口,互联; 所以,OSI是开放系统互联模型。以上只是一个名词,那么这是一个什么模型呢,为什么要搞一个这样的模型呢? 我们来看一张图,首先说说七层和四层的区别 七层比四层多三层(想起了“五环之歌”),其实四层是七层的一个简化版,把应用,表示,会话合并成了应用;而把物理和数据链路层合并到了一起,所以叫四层。七层和四层两种划分中,最重要的就是传输层(TCP),网络层(IP)。 所以,我们把网络协议叫——TCP/IP协议。

为什么要搞一个模型

我平时喜欢琢磨这些东西,这部分是我的个人理解。 我们读大学的时候,有各种建模比赛,可知模型是理解,分析,研究一个实物最好的一种方法,很多模型做成三维的,可以输入各项参数,模型里面有各种公式,算法,会根据这些参数条件变化,模型好不好,就看算法是否科学,是否符合事件发展规律。 当然,我们这里的模型跟学校里面的建模有些区别,但是大体上是为了更好的理解,分析,传播这个知识。 更为简单的比喻是,有点像我们去买房子的时候,开发商房子都还没有做起来,就开卖了,然后大家围在一起,说我要这一栋,你要哪一栋,销售也在不停的解释每栋,每层的价格。我们这个模型就有点像这个楼盘模型,方便我们理解TCP/IP协议。 而且,这个模型把庞大的TCP/IP协议(代码量很多,而且是IEEE这些早期工程师写的,如果没有那三卷书,只看代码,是看不懂的,即使有这三本书,如果没有实际的设备给你运行代码,你也是很难懂的,我们当初就是通过抓包工具来分析来理解这里面的代码和理论)

如何理解这个OSI模型

这个模型花费了每一个程序员的精力去记忆理解,但是以前没有一个人能够采用比较容易理解的方式去讲解这个模型,直到有一天我搜到一篇博客: OSI七层模式简单通俗理解 我觉得这个人应该是一个理论和实际经验都非常丰富的人,才可以写出这么浅显移动的文章出来,好的文章不但能帮你理解,还能帮你记忆,而且是看一遍就记住了。 OSI七层模式简单通俗理解 这个模型学了好多次,总是记不住。今天又看了一遍,发现用历史推演的角度去看问题会更有逻辑,更好记。本文不一定严谨,可能有错漏,主要是抛砖引玉,帮助记性不好的人。总体来说,OSI模型是从底层往上层发展出来的。 这个模型推出的最开始,是是因为美国人有两台机器之间进行通信的需求。 需求1: 科学家要解决的第一个问题是,两个硬件之间怎么通信。具体就是一台发些比特流,然后另一台能收到。 于是,科学家发明了物理层: 主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后在转化为1、0,也就是我们常说的数模转换与模数转换)。这一层的数据叫做比特。 需求2: 现在通过电线我能发数据流了,但是,我还希望通过无线电波,通过其它介质来传输。然后我还要保证传输过去的比特流是正确的,要有纠错功能。 于是,发明了数据链路层: 定义了如何让格式化数据以进行传输,以及如何让控制对物理介质的访问。这一层通常还提供错误检测和纠正,以确保数据的可靠传输。 需求3: 现在我能发正确的发比特流数据到另一台计算机了,但是当我发大量数据时候,可能需要好长时间,例如一个视频格式的,网络会中断好多次(事实上,即使有了物理层和数据链路层,网络还是经常中断,只是中断的时间是毫秒级别的)。 那么,我还须要保证传输大量文件时的准确性。于是,我要对发出去的数据进行封装。就像发快递一样,一个个地发。 于是,先发明了传输层(传输层在OSI模型中,是在网络层上面) 例如TCP,是用于发大量数据的,我发了1万个包出去,另一台电脑就要告诉我是否接受到了1万个包,如果缺了3个包,就告诉我是第1001,234,8888个包丢了,那我再发一次。这样,就能保证对方把这个视频完整接收了。 例如UDP,是用于发送少量数据的。我发20个包出去,一般不会丢包,所以,我不管你收到多少个。在多人互动游戏,也经常用UDP协议,因为一般都是简单的信息,而且有广播的需求。如果用TCP,效率就很低,因为它会不停地告诉主机我收到了20个包,或者我收到了18个包,再发我两个!如果同时有1万台计算机都这样做,那么用TCP反而会降低效率,还不如用UDP,主机发出去就算了,丢几个包你就卡一下,算了,下次再发包你再更新。 TCP协议是会绑定IP和端口的协议,下面会介绍IP协议。 需求4: 传输层只是解决了打包的问题。但是如果我有多台计算机,怎么找到我要发的那台?或者,A要给F发信息,中间要经过B,C,D,E,但是中间还有好多节点如K.J.Z.Y。我怎么选择最佳路径?这就是路由要做的事。 于是,发明了网络层。即路由器,交换机那些具有寻址功能的设备所实现的功能。这一层定义的是IP地址,通过IP地址寻址。所以产生了IP协议。 需求5: 现在我们已经保证给正确的计算机,发送正确的封装过后的信息了。但是用户级别的体验好不好?难道我每次都要调用TCP去打包,然后调用IP协议去找路由,自己去发?当然不行,所以我们要建立一个自动收发包,自动寻址的功能。 于是,发明了会话层。会话层的作用就是建立和管理应用程序之间的通信。 需求6: 现在我能保证应用程序自动收发包和寻址了。但是我要用Linux给window发包,两个系统语法不一致,就像安装包一样,exe是不能在linux下用的,shell在window下也是不能直接运行的。于是需要表示层(presentation),帮我们解决不同系统之间的通信语法问题。 需求7: OK,现在所有必要条件都准备好了,我们可以写个android程序,web程序去实现需求把。 补充: Socket: 这不是一个协议,而是一个通信模型。其实它最初是伯克利加州分校软件研究所,简称BSD发明的,主要用来一台电脑的两个进程间通信,然后把它用到了两台电脑的进程间通信。所以,可以把它简单理解为进程间通信,不是什么高级的东西。主要做的事情不就是:

A发包:发请求包给某个已经绑定的端口(所以我们经常会访问这样的地址182.13.15.16:1235,1235就是端口);收到B的允许;然后正式发送;发送完了,告诉B要断开链接;收到断开允许,马上断开,然后发送已经断开信息给B。

B收包:绑定端口和IP;然后在这个端口监听;接收到A的请求,发允许给A,并做好接收准备,主要就是清理缓存等待接收新数据;然后正式接收;接受到断开请求,允许断开;确认断开后,继续监听其它请求。

可见,Socket其实就是I/O操作。Socket并不仅限于网络通信。在网络通信中,它涵盖了网络层、传输层、会话层、表示层、应用层——其实这都不需要记,因为Socket通信时候用到了IP和端口,仅这两个就表明了它用到了网络层和传输层;而且它无视多台电脑通信的系统差别,所以它涉及了表示层;一般Socket都是基于一个应用程序的,所以会涉及到会话层和应用层。

为什么说TCP是可靠的,UDP是不可靠的

很多人面试的时候介绍TCP和UDP的区别,一般都会说TCP是可靠的,UDP是不可靠的,更好一点的回答会加上,TCP每发一个包需要对方确认,而UDP不需要确认。但是,很多人并没有真正理解,我觉得要找到权威的说法,应该从协议本身去解释,我们看TCP和UDP协议规定 发现,TCP可靠是因为其协议规范本身决定,在TCP协议里面有顺序号和确认号机制,而UDP协议里面没有规定,这决定了TCP是可靠的,UDP是不可靠的。当然这个协议里面,你还有很多其他的看不懂,但是我觉得为了说明可靠性问题上,我们不需要去了解其他部分。 (顺序号是发送方每发一个包,都会给这个包编号,这个编号的长度是32位数,而且还有一个地方存放确认号,这个确认号是对方发过来的,对方每成功收到一个包,都要发送确认号给发送方)

为什么说TCP是面向连接的,UDP是无连接的

这个也是很多同学去面试的时候,别人喜欢问的,你怎么有效记住呢(有效的记忆是看一遍,理解一次就永远记住了,这是最好的方法) 如果你要写TCP程序,那么你会根据这个模型来写,这个模型给我们列出了,先调用哪个函数,后调用哪个函数,服务器该调用哪些函数,客户端该调用哪些函数。 我们发现,客户端连接服务器的时候,使用了connect函数,而UDP编程模型不需要connect函数。如果你动手写代码,会理解更深刻。 这个面向连接,就是说你会看到它有这个连接的动作,就是调用了connect函数。那有人就问了,UDP难道不连接吗? 接下来解释这个问题,注意理解: 玩过星际争霸的人知道探敌人的基地,常会派一个狗子或者农民,如果找到了对方,然后把做出来的兵直接A过去(attack)。此时,就像我们的TCP,TCP是先去连接一下,如果连成功了,那么后面派大部队过去。但是UDP不是这样的,它不探路,直接派大部队去找敌人基地。 还有一个好理解的解释是这样: TCP是先拿着信(信里面有地址)去找到目的地,找到目的地后,再把东西运过去;但是,UDP不是这样的,它是直接开着大卡车(同时带着信)去找。udp是在sendto这个函数里面去"连接"的,是带着数据去"连接"的。 所以说,TCP是面向连接的,UDP是无连接的。

END

好了,我们下一篇博客从代码的角度讲解网络。觉得本博客对你有帮助就收藏吧!

三大通识知识:进程,线程,网络(一) 三大通识知识:进程,线程,网络(二) 三大通识知识:进程,线程,网络(三) 三大通识知识:进程,线程,网络(四) 三大通识知识:进程,线程,网络(五) 想通过视频学习,轻点下面链接 进程,线程,网络视频连接

最新回复(0)