27.Linux网络编程socket变成 tcp 高并发 线程池 udp

好,咱们开始上课了,从今天开始咱们连续讲 8 天的,网络编程这个还是在linux环境下去讲,咱们先看一下咱们这 8 天都讲什么东西,跟大家一块来梳理一下,你先有个大概的印象,这些你也不要记,那么网络编程一共有 8 天的课,是吧?那么其中前 5 天咱们都讲 Linux 的网络编程的基础课程,基础大概前三天是概念加编程,那么概念会给大家每天都会提到一些,因为这个概念较多,一些理论性的东西比较多,所以咱们给它拆分开了,咱不能说这一天广讲概念是不是?那这样的话大家听到叫枯燥。

 那么看见每天都学什么啊?第一天讲一些基础的概念,比如说什么叫协议?有哪些常见的协议,以及比如说什么 7 层模型、 4 层模型,都在这一天跟大家说一下。第一天这是然后到后面的时候,最后咱们给大家讲一下socket 的 API 函数,然后咱们写一个客户端,写一个服务端来测试一下,那么就结束了。当然在第一天里面我们还讲到什么大端字节序、小端字节序等等这些概念,这些都是一些基础性的概念,要求你掌握。那么在讲的时候我给大家说的时候,嗯,有些东西我会让你理解,有东西让你了解,有东西的时务必掌握,这些要分清楚,因为你比如说有东西咱们写代码用不着,比如说协议,什么 TCP 协议、 UDP 协议,什么什么ARP、 RARP 等等。这些协议你写代码确实用不着,但是为什么还要说这些?一个是它这些基础的概念你需要掌握。

再一个你面试的时候人家可能会问,是不是你不能说光会调几个函数,然后概念你一点不知道,那也不行,是不是?那么第二天的时候给大家讲一下这个 3 次握手或 4 次挥手,那么什么是 3 次握手呢?就是建立链接的时候,咱们内核底层,哎,有一个 3 次握手的过程,在注意这个是底层实现的,不是你实现的。那么还有一个 4 字挥手,这个 4 字挥手是在断开链接的时候,有一个 4 字挥手过程。

讲完这个之后给大家讲一下高并发服务器,咱们讲高并发服器的时候,先从大家熟悉的入手,因为咱们前面是不是刚第一天的时候给大家讲过了基本的 socket API,这是基本的?然后第二天的时候给你讲一个高并发的,那么用什么模型,咱们有多进程版和多线程版,多进程咱们是不是前面讲过了?多线程咱们也提到过了,是不是也说过了?然后咱们做应用,

第三天的时候,给你讲一下 t c p 状态转换图,大家注意这一部分也主要是什么呀?比如说用于面试,或者是用于你排错的时候可能用得着,知道什么意思吗?这一块你需要理解一下,你也不用死记硬背你,那么你在这个面试之前,你把这个翻一翻看一看,是不是你面试的时候问得着你,你能够答出几条来就可以了,是不是?那讲完这个之后还有一个重要的是讲一下高并发服务器的另外几种模型,主要就是什么呢?多路 IO 复用、多路io用。

那么一共有 3 个模型,select-poll-epoll ,其中select 和epoll 是你需要重点掌握的,尤其是epoll ,尤其是当这个 pool 的话,你作为了解内容就可以了,因为它是借在这两个中间的,是不是你说它效率高它也不高,你说效率低跟它差不多。实际上实质上这个 pool 和这个 select 比较起来没有实质性的改变,本质上差不多。在咱们这个linux操作系台操作系统下面,我们都用这个epoll模型居多,因为这个效率高。

这个那么第四天的时候给大家讲一下这个怎么样,暂时给你介绍一下。第四天的时候给你讲一下这个 epoll怎么去用,以及咱们写一个案例来测一下是不是可以支持高并发,是否多客户端同时连,看看能不能处理过来。最后面的第四天,最后的时候给你讲一下epoll反应堆,这一块是咱玩讲的时候我估计有一半以上的人应该会听着模糊,因为这块难度越大,那么你听的时候这一块听的时候重点听他的思想,而不是去抠细节,听了吗?要记搞清楚,这个策略是有区别的,有些是你需要务必掌握的你能写出来,有的是你只要读它的思想就可以了。

那么第五天的时候给你讲一下线程池,那么这个线程池得注意线程池,咱们是不是前面讲过了这个多线程编程了,是吧?那这一块的时候你有些基础的话,你听这线程池就听着比较省劲。这一部分主要用的就是互斥锁加条件量。我问大家那么多线程的话,是不是要操作共享资源?操作共享资源是不是要使用到互斥锁啊?是不是那么多个线程之间?他们通信的时候,那么有的时候是不是我们需要这个让某一个线程等待某一个条件成熟以后才去执行啊?这个时候用到了什么呀?条件变量是不是?这个现在我先不细说,后面接着讲的时候是讲这个 UDP 以及本地套接字通信,这个词是不是在前面跟你说过?在哪说过?在哪张通信方进城前通信的时候是不是跟你说过这个?好,第六天的时候给你讲一下 libevent,这个 libevent它是一个第三方的网络框架,这个只要学会用就 OK 了,学会用就可以了。

那咱讲的时候讲一些常用的API,以及把它的思想给你说一下,这代码咱们写一个,写代码咱们分析两个就可以了。这是libevent,

第七第八天的时候,咱们讲一个项目,一个小的项目,那么这个项目一共是两天,咱们主要编写一个web服务器,大家想一下web服务器是干什么的?接收web请求的是不是并处理请求吗?那么咱们用 IE 浏览器访问的是不是就是web服务器?对,是吧?那么这个浏览器你不只是可以用IE,火狐什么 360 等等都可以,只要是浏览器,那么它其实都可以和 web 服务器进行通信的。当然这个 IE 浏览器也好,还有其他浏览器也好,那么用的都是什么协议?与服务器通信的话,什么协议? HTTP 协议,这个属于应用层的一协议。

好,这是咱们给大家讲一下这个 8 天的课程安排,那咱们看一下今天都讲什么?今天都讲什么?这个你先有个大概的了解,不用死硬背的,咱们一天天讲。好,看一下今天的数据目标,先给你讲一下 o s i 七层模型和 t c p /ip 四层模型结构,大家注意这两个模型要求,你这个还是需要记一下的。为什么需要记下?面试的时候问,清楚了吗?只要你这个做网络服务端开发的话,像这样的基础知识有可能会问到你,现在你也不用 死记硬背,怎么办?你投面试之前,比如说你面试公司是做这个,想做一个后台服务开发的这种,你需要把这看一看,如果你找工作的是,做游戏开发的,而且是用 q t 的这个你可看可不看,知道什么意思。那么你面试之前是不是你要针对你的这个找到这工作的这个性质,是不是要做针对性复习?是不是你本来你就做 q t 开发,那么你把 linux复习再透彻是不是也没多大意义?知道什么意思,要有针对性的去复习。

 那第二个给你讲一下什么叫协议,协议以及常见了常见的网络协议的格式,比如说 TCP 协议、 UDP 协议、 ARP 协议等等,这些大家注意这些要求你也得了解为什么,因为比如说你面试的人问你,那么你了解几种协议,每种协议干什么的?是不是你说出几个来就可以了?别到时候一个说不出来是不是?起码咱们讲完这 8 天之后,你至少得知道两个,哪两个 TCP UDP 是不是?当然知道,两个还不够是吧?好,后面讲一下这个网络字节序和主机字节序之间的转化,这个咱们有一些常见的函数,你把这些函数掌握了。

再者你得明白什么叫网络字节序,什么叫主机字节序这个概念得清楚后面一直到后面这 4 部分,先跟你说一下 TCP 和 UDP 的通信流程,那么讲完这个流程之后,咱们就给大家编编代码,写一代码,看看我们写的这个服务端、客户端的能不能通信。当然在这个讲代码之前,咱们肯定会给你介绍一些什么呀?常用的api函数。这些函数一开始的时候你可能记不住,没关系,因为每咱们每天都在用它,是不是一旦一遍记不住,没事,两遍记不住也没事?因为咱们这个从第一天到第八天的时候,这个代这样代码咱们大概至少会写 10 遍以上,你还记不住,那不可能,是不是?除非你跟真的就没写,也没听过,是不是?同学?这个大家不用担心,因为函数也比较多,你不用担心,每天咱们都用,你怎么可能记不住?好好,那么这个 8 天的课程安排和咱们今天的这个学习目标,我就先跟你说到这

看一下,就给你介绍第一个网络基础概念,第一个协议,协议。

 首先看一下协议的概念,这东西是我自己总结出来的,你也不用背,你先理解理解,看能不能理解。协议什么意思?就是说协议是事先约定好,注意看,事先约定好,大家共同遵守的一组规则,这里面关键字,第一是 事先 事先约定好。第二个规则是不是共同遵守的一个规则?其实这样的东西在现实生活中很常见,信这个交通信号灯是不是规则?什么规则?红灯干什么呀?停下来,绿灯先走,黄灯是不是?中间状态?是不是?你可以迅速传过去是不是?当然不建议,不建议好,那么从应用程序的角度来看,协议可理解为数据传输和数据解释的规则,这句话能理解吗?这从应用程序的角度来看,协议可理解为数据传输和数据解释的规则。

那么我为大家,那么你说这个两方双方在进行通信的时候,那么你说这个服务器a,它给服务器 b 发了有 10 个字节数据,是吧?那么如果服务器 b 只接收 5 个,那么他能不能把这全部内容给读出来?不行,那么人家发了 10 个,你接 10 个,人发 20 个,你接 20 个,那么而且发的这些数据里面每一部分代表什么意思?那么需要事先约定好,能理解吗?需要事件约定好,那我如果不事先约定好的话,对方是不知道你什么意思。

在这我给你举个简最简单例子,看这个同学们,比如说这个是 a 机器发给 b 机器的一个图片,可以咱们以最简单的例子为例。好,那么 a 要给 b 发,是不是 a 得告诉 b 这个字符串有多长?不告诉他知道多收多少吗?是不是?好,那比如说他规定了前四字 前四个字节,表示后面这个的长度,可以吗?好,比如说我这儿来了个10,那么这个 10 的话,占四字节是不是010?嗯,好,这边就是十字节数据,十字节数据,那么首先它是不是可以把这四个字节,或者当然你把这个整个发给它也行?对方 b 在收的时候,他是不是可以先收前 4 个字节,知道什么意思?这个叫包头。

 后面咱们还有这个概念,他先收 4 个字节,那么他收了 4 个字节以后,然后他把这个长度算出来,他是不是就知道后面说多少个了?这块能理解什么意思吗?这就这意思啊,事先约定好。那么而且这 10 个字节数据里面它还可以再细分。好,还可以再细分。比如说举个例子,4个字节里面它可以有 4 个字节表示,用户id, 4 个字节表示优惠码,后面表示其他信息等等。能不能那么对方收到这 10 个字以后,它是不是就可以拆分?这些是经常使用的方法,这是一个从应用程序的角度来说。那么什么叫协议?其实就是什么呀?数据传输和数据解释的规则,这个你如果理解不了的话,咱们后面这个逐步的哎,讲的时候你会慢慢就体悟到了。那么这关于这个在日常生活当中,除了这个交通信号灯,你还能想到什么呀?在日常生活当中是不非常多?那么我问大家,咱们上课的话,约定好 9 点上课, 12 点下课,下午 2 点半上课, 5 点半下课,是不是?规则?是不是?那么老师和学生是不是都需要工作分手是吧?包括小学生他是不是都一样的?都这个意思,是不是都这意思啊?这些都叫什么呀?都叫协议,其实说白了就是规则,是不规则。

我问一大家,我再问一大家,你说这个协议的话,遵守方的话是不是至少是两方以上的?对,是不是?那么如果说你就是就一个人,所以你给自己定这个规则,比如说你约定,比如说早上我 8 点起来,然后我这个 8 点半吃饭,然后 9 点出门,是吧?然后 12 点回家,这些是不是也是你自个给自个定的一个规,这叫什么呀?类似纪律,我给自己定了一套规则,说这个规则的话,你是不是只会给自己试用?别人会用一套规则吗?是不用。

大家注意这个协议一定要是什么呀?至少是双方以上,对于这个咱们这个上课来说,这个规则来说, 这个协议来说,是不是这个老师和学生双方都得遵守?当然学生的话是不是有好多人等等,这些都叫协议,清楚了吗?同学们不要把这个协议的概念理解的复杂了,就这么简单,那么还可以理解为什么各个主机间,各个主机之间进行通讯使用的共同语言。

我在这给大家举一个例子,什么意思?那么你比如说你在这个上网的时候有没有遇到过这样的情况?这个你这个神经的书网页显示的都是一些乱码,或是一些你看不懂的,知道什么意思吗?你比如说你这个,你这边的机器,你这边的浏览器显示的时候,你只能显示什么呀?这个英文或者中文的,但是对方服务端给你发过来的数据,它是你这边的这个浏览器是看不懂的。这些的话是不是相对协议不配套?协议不匹配。

但是一般情况下我们这个这种现象,这个发生的时候比较少,是不是发生的时候比较少,肯定是没有说你这个,你这个比如说你ie浏览器,你这个访问web服务器的时候,这个显示不正常,是不是有这样的?比如一堆乱码,这往往的可能是协议有问题,当然这个协议不是说的什么呀?不是说的是 ATP 协议问题,你们双方使用的语言不一样,人家给你发的是英文,你这儿解释法文能看吗?是不?,那么你还举个最简的例子,你比如说这个,这个各国政要出访的话,是不是要带一个翻译?是不是?那这个翻译是不是至少得等两方语言?你得懂中语、中文,而且你还得懂什么呀?比如说英语,那这样的话你才能够把英语是不是翻译成中文等等,这些都属于什么呀?都是协议的例子,那么协议的例子在日常生活中很常见,你可以想一想有多少,是不是你能够举出哪些来?咱们给你举一个。

什么什么例子?给你举一个这样例子,双方 a b 服务器, a b 机器要发送文件,要发的文件。这个咱们就一会画一个图看一下。这个我直接给你画一图。这个什么?这个是 a 机器。同学们,这个是 a 机器。

好,再来一个,这个是 b 机器,这个给咱们这个上面举的例子一样差不多,你听一下,什么能看?能不能听懂?好,现在有我有一个这样需求。什么要求?什么需求?我想把 a 机器的文件上传到 b 机器,这个在咱们这个真正使用的是不是使用的就是 f tp服务,是不是 f tp朋友们还记得吗?你看这个是怎么回事?它的雏形是这样的,a机器要把这个文件发送 b机器,它首先发送一个这样的,发送什么呢?他先告诉B机器,他要发送哪个文件。

第一步,发送一个什么呢?文件名可以吗?这你自己定,没有关系,是不是你不发文件名,你发其他类型是吧?这文件名第一步,那么这个 b 机器收到这个文件名以后,他要告诉 a 机器,他收到了,知道什么意思吗?你没好,他要告诉他,所以这再给他回一个,是吧?这个什么呀?这个是回了一个什么呀?回什么你自己定在这,咱们给他回个这个,回一个OK,可以吗?不回ok行不行?你回一个好了,这你自己定啊,回,OK。

第一次,也就是说现在 b 级是不是就知道 a 级想给他传哪个文件了?实际上传文件是这样的,那么对方收知道你这个文件名以后,他想在本地建一个文件,那么你再发数据之后,他往文件里面写,写完之后这个文件是不是相当于发完了?这么来的。好,这是第一次,好看,

第二次你说该传什么了?该传什么了?是不是你要告诉对方你这个文件有多大,是吧?好,

第二次是传文件大小。好,那为大小传给他以后,比如说你规定了我给你传四个字节文件大小,可以吗?可以,你自己定就可以了,这个双方要协商好。那么这个 b 机器 收到这个 a 机器 发过来的这个文件大小以后呢,他就知道了我接下来要连续收多少个数据了吧?他就知道了。然后他也给他回一个什么呀?OK,我知道了,你要给我传多少个我清楚了,是不是了?好,这儿也给他来一个什么呀?OK,这是什么呀?这是第二次传输,第二次传输。好,这个时候那句这个时候这个 b 机器就已经知道这个 a 机器要给他传多少个数据了。好,加上第三次机,第三次的时候 a 要真的给他传数据了。

这个是传的什么呀?同学们,实际上传的什么?是不是文件内容?第三次,传文件内容,兄弟们,那么你传文件内容的时候是不是实际上是在一个while循环里面不停的传呐?不停的传,他肯定是把这个文件是不是传完之后他就结束了?这个是什么呀?传完之后,传完之后干什么呀?是不是结束了?是吧?传完之后结束了。

当然我跟大家这个 b 怎么知道这个 a 已经传完了,怎么知道?因为他因为第二步已经把这个文件大小告诉他了,是不是?比如说我给你传 1 k,他收到 1 k 的时候,他是不是就把这个链接关掉就可以了?整个是不是结束了?兄弟们,我们这个例子,这个例子就是一个文件传输的一个典型例子,这个能看懂吗?同学们,这种在a、 b 之间传递文件的,这种通过 3 次,第一次传送文件名,第二次传送这个文件大小,第三次传送文件内容,这种我们就说什么呀?这是一种简单的文件传输协议,可以吗?是不是这是第三次

这个协议?这个协议是我们自己定的吗?这个协议是我们自己定的,后来这个协议在注意,后来这个协议经过了不断的完善、改进、优化,就形成了咱们今天使用的ftp 协议了。

清楚了吗?同学,这个协议就这么来的,这一步一步的,什么升级、改造、优化等等这么来的,那么这个等于说这个刚才我跟大家说的,你把它理解成一个文件传输的一个雏形协议,是不是应该是最初级的一个版本?你这么理解就行了。 这个从a 传送或上传文件,上传文件到服务器b,那么需要什么呀?需要在 a 和 b 之间看见没?同学是不是要规定协议之间?规定或叫制定,一个双方再注意要双方都什么呀?都认可的什么呀?规则,那么这个规则,就什么呀,就称为文件传输协议,这个协议在于这个协议是 FTP 协议的一个初级版本,该协议是文件传输出哪个协议?同学是 ftp, ftp协议的一个初级版本,大家注意,后经过什么呀?不断的完善是吧?优化,最终形成了一个什么?形成了一个完善的什么ftp协议,我刚才说的这是什么呀?是一个 ftp 协议,一个初级版本,是一个文件传输的一个初级版本
 

那么我问一下大家,我这三个协议能不能再进行优化?这三步,我,第一步和第二步能不能合成一步?可以的,这个你随你怎么定?总之你定的这个协议一定要让 b 机器知道。如果你定的这个协议是按两次传输,那么 b 机器是按照三次接收,能接收到吗?是不是有问题?同学们,那总之你这个 a 和 b 之间一定要有一个什么呀?协商的一个机制,两者之间有一个协商,总之他们两个要共同遵守同一个规则,是不是?一定这样的,这个关于这个咱们这个讲义给大家说的。给我讲的差不多,你呢?这个理解一下就可以了,是吧?这是一个什么呀?原始版本,原始协议,那么后来这个经过不断的完善、改进、加工,最后形成一个稳定的、完善的,什么呀?文件传输协议就是现在用的 f t p 协议。

 

 好,那我再问下大家,那么你说如果我这个 a 机器,我装的是linux,我 b 机器装的是 windows

a 和 b a 能不能把文件传给b,可不可以?可以,这个协议和和系统无关,知道什么意思吗?和系统无关。那你不信你,我举个例子,你使用 Linux 能上网吗?能不能?你访问的web服务器有可能,比如说人是unix 或者是什么,这个其他版本的linux或者是 windows 都有可能。是不是我们的 windows 访问的这个比如说阿里巴巴的服务器人,有可能就是unix或Linux,这都可以的,这个没有关系,这个协议和具体的操作系统无关,和平台没有关系。

搞清这个我给你补一句,注意,协议和什么呀?和具体平台无关,能理解什么意思吗?咱我举个最简的例子,这个 c 语言能在windows下写吗? 能在 Linux 上写吗?是不是都可以?那么 c 语言是跨平台的是不是?但是有的语言它只能在 Linux 上,那么它就不是跨平台的,是吧?这代码一执行就不行了吧?

好,关于这个协议的概念咱们就说这么多,那么还有是几种常见的协议,这个咱们看讲义,这看讲义,那大家的讲义,大家打开了吗?这个大讲义咱们给你找几个,那么几个常见的协议,这些都需要你了解,你得知道一个,比如说咱们这个有这么几层,一共 4 层,什么传输层、应用层、网络层、网络接口层。

 

 那每一层有什么协议?这个跟你说可能不知道,先不说好,看一下这些都是常见的协议,这是网络当中的一些协议,这一段比较常见,就是 TCP 协议,是网络传输控制协议。那叫什么呀?传输控制,那这个协议是我们用的非常多的一个协议,咱们socket 编程的话,是不是就用在这个协议之上?叫传输控制协议?那是一种面向链接,可靠什么呀?安全的字节流传输,它是安全可靠的。

那么还有一个是 UDP 协议,这叫用户数据报协议,这个它是不面向链接不安全不可靠的协议,这俩是不是正好是一对了?那么这个你选这个的话tcp,是不是因为这个安全可靠?选这个话udp是有可能不安全不可靠,是不是?还有是 h t tp 协议这个协议,这个咱们应该知道,是吧? web 服务器和这个浏览器之间同信的时候,用的就是这个 HTTP 协议,它的英文是这样的,叫超文本传输协议,这个你得知道啊?你得知道啊?这用的比较多,还有ftp 协议,这个咱们是不是说过了,是吧?这叫文件传输协议,从把一个文件从 a 机器拿到 b 机上用的就是一个协议,清楚了吗?还有这个 IP 协议,这个协议什么意思?叫 因特网互联协议,这个协议咱们会说

还有 i c m p 协议,叫什么?控制报文协议,这你都看一看,这两个协议,arp 协议,rarp协议,这个咱会讲arp 协议,叫正向地址解析协议。

什么意思?我举个例子,这个咱们在进行数据传输的时候,都要需要知道对方的mac地址,那么如果不知道对方的mac地址是无法进行数据传输的。这样咱们讲协议的时候,咱们数这个协议的格式里面有这么一项你就知道了,那么如果说你仅仅知道对方的IP,怎么知道他Mac? Mac 是不是物理地址?是不是?同学们,你的 ip 地址可以变,你的 Mac 地址能变吗?是不是不能变?是不是出厂的时候你的网卡就给你定好了?是不是?那么 ARP 干什么呢?就是通过 ip 地址找到对方的 Mac 地址,就这么来的,清楚了吗?你就干这个来的。

还有一个 r a r p,正好跟这相反,通过Mac 找到什么呀?找到ip,这是这个,这些协议你都看一看,你都看一看。这 4 层咱们稍后会说,你都看一看,你起码你你你,咱们讲过一段课程以后,这里面你得知道什么呀? TCP UDP,HTTP, FDP 是吧? IP 协议,什么 ARP 协议等等,你只要能够说出五六个来,你别到时候只能说出。我就知道 TCP UDP,人家怀疑你到底有没有学过网络编程

你不会说只懂那几个函数吧,是不是?那就有点太浅了,兄弟们, 4 层模型,刚才我讲的是协议,是不是概念什么?

 同学们,协议是双方共同制定的一组规则,是吧?那么在网络通信当中,网络通信中表示什么呀?表示通信双方,通信双方什么呀?叫传递数据,叫发送数据和接收数据啊,

叫传递数据,传递数据和解释数据的一组规则。一组规则。你可以按照自己的话去写也行,总之你心里也能说得出来。好,这个没有死答案,没死答案,

接下来咱们讲一下这个osi 7层模型, 咱们看一下这个模型是这样的,看这个图,同学们,我给大家在那在这总结的很详细,你这个 7 层模型也好, 4 层模型也好,这个为什么要跟你讲这个主要是面试的时候问的比较多,再的时候人家有的时候考这个网络的题也会考这些。

 

 你要不懂的话就不行了,是不是?咱们看一下这个网络,大家注意这个网络的 7 层模型也叫 o s i 模型,它叫什么?它的中文是开放式系统互联,英文是 open system interconnection,是吧?英特尔 connection 是不是互联的意思?这个英特尔在哪?大家在哪还见过 英特尔 communication 什么意思?通信的意思,互相通信。大家记得那 IPC 什么意思吗?IPC。

Inter process communication. 是不是进程间通信的意思?英特尔process?还记得吧?在这是interconnection,是不是互联的意思?那么既然说互联是不是肯定,至少双方是不是?当然也有可能是多方,是不是?那么国际标准化组织制定了 o s i 模型,大家想一下这个,你说这个国际标准化组织,这个制定 o s i 模型是不是中国制定的?不是,现在这个国际上这些很多大的这个规则都没有中国的事,是不是?当然现在中国是不是制定开始参与制定 5G 标准,还遭到澳大利亚的反对了,听说过没有?华为那个是吧?这个 5G 好多城市开始布局了,好多开始城市开始布局了,从 4 G 到5G ,这个是不是变化?眼看没有几年时间,没有几年时间,那么该模型定义了不同计算机互联的标准是设计和描述计算机网络通信的基本框架在于这个 7 层模型,它只是一个理想模型,真正用的时候用的并不是这个 7 层模型,是哪个模型、 4 层模型、 是4 层模型。但是这个七层模型虽然说是一个理想的模型,但是我们还是要了解一下,你就这样想就完了,反正你把这个学会之后,面试的时候你就不用怕了,是不是?知道什么意思?你要有这个动力,咱们看一下每一次模型都是什么意思。

第一个物理层,物理层主要制定了很多的通信的怎么样?物理的一些通信设备,比如说大家知道这个猫,嗯,是不是那个调制解调器,还有双绞线,这个叫什么呀?这叫通讯介质,还有这光纤是不是也是光纤?什么什么双绞线,咱们用的是不是双绞线?同学们,现在是不是还有光纤什么的?还有这个猫德姆等等,这些都属于包括什么呀?除这个之外,我记得这个电,这个,你去电信那边申请这个网络的话,是不是还给你一个那个东西啊? 还给你一个东西那叫什么来着,是吧?是不是接往下的时候,你如果你是接电信的或移动的话,是不是他给一套设备知道什么意思?那忘记了什么名了,那些设备什么的,那设备最常见就是猫德姆。

猫德姆是干什么的?干什么的?朋友们,猫德姆是进行模数转换和数模转换用的,那么我问一下大家,你说你这个数据往这个通过这个网线也好,通过这个光线也好,把这个数据发送出去,它发送的就是 01 吗?还能是 01 吗?是不是01,高低电平,人家问你的话,你,你这样的话千万不要说错了,如果你发送的,你说就是发送01,人家 01 怎么表示的你不知道,那完了是不是?为什么呀?高代表1,是不是一样?就这意思是这个同学们是不是这个?有高,什么意思?同学们,这是1,这是0,这就是1,这是0,是发的这个,那 8 个 8 个这种 10 是不是一个比特位啊? 8 个位是不是表示一个字节?嗯,清楚了吗?这个你千万不要说错了,什么双绞线也好,光纤也好,还有猫德姆等等,这些都什么呀?都叫在都处在物理层这个这一层上,那么特别是这个猫德姆,你要知道它的功能,你这个要,你要是这个什么接移动和电信也好,你如果没有这个猫德姆的话,你这肯定上不了网。

连想都不用想,没想是不是,肯定是不行?猫德姆,后面再接什么呀?同学们,你的这个通过这个移动或电信的这个光纤进来以后,是吧?这个线进来以后先接猫德姆,再往后接什么接路由器,如果不接路由器是不是你可以直接插在你电脑上?也行,但是那样的话是不是只能插一个电脑?你接上这个路由器之后是不是就可以好多人可以一块来使用了?明白什么意思?你把这路由器是不是可以?是免费wifi啊?是不是你直接插的这个你用网线插是不是也行?等等这些大家应该上学的时候,这个宿舍里面,如果是一个宿舍里面有 8 个人或 4 个人用的都是这种方式吧?是不是都是一种方式?好,那么这个数据在往这个网络当中传输的时候,它是将什么转化成什么?是将模拟信号转换成,是将数字信号转化成模拟信号,模拟号是不是就是 0101这样的 代码啊?其实在这个网线当中传出的就是高电平,这个叫什么呀?模拟信号是不是0101?这叫什么呀?数字信号。好,那么从这个外边传到这个猫德姆这边传进来的时候,他是不是进行模数转换,要把这种模拟信号转换成数字信号,是不是这样的?肯定是这样的。

你说这个我再问大家,你说这个你电脑上网的时候,最终你的这个外边发给你的数据,最后有谁接收了?你电脑上哪个设备?是不是网卡?这你这个你得说明白。好,看一下这第一个,这叫物理层,物理层看第二个数据链路层,那么数据链层有一个很重要的词,叫什么呀?数据校验,这个咱们后面讲这个以太网帧格式的时候,你就会看到这个了,有数据校验这一层,那么数据校验的目的什么呀?可以想一下,是不是为了看一下这个数据有没有问题,是不是?好这个定义了网络传输的基本档位帧,大家注意这个帧是一种网络报文格式,只要是从你在网卡上发出去的,都是以太网帧的格式。这个后面咱们讲这个以太网帧格式,我会给你细说,看后面这个网络层定义了网络,定义了网络。

我再问大家,你说这个网络从里面你知道这里面有什么东西吗? ip 地址在哪?是不是就在这个网络层啊?,是不是?那么两台,这两台主机之间传输的路径以及点到点的传输,这个里面有一个重的协议叫 IP 协议, IP 协议里面是不是有这个 ip 地址啊?是不是?咱们后面讲这个 IP 协议格式的时候,我给你再细说叫网络层。

那么我再问一下大家,这个网络层里面有一个设备,大家知道什么设备吗?网络层里面有一个设备或者叫什么,这个设备它只解析网络层的数据,大家想一下这个路由选择靠的什么设备?什么设备啊?路由器选择是不是路由器?谁读的路由表啊?你电脑,你自己脑也可以当做一个小型路器来用,但是你这个复杂了就不行了,简单的还行。

在咱们这个进行网络通信的时候,那么往往这个从 a 机器发到把数据发到 b 机器,往往中间是不是经历了好多层啊?是不是那么往往经历了好多个路由器?路由器是连接两个不同网段的一个桥梁,知道什么意思吗?我问,我再问大家一个问题,咱们这个一个,咱们一个班里面,咱们相互通信的话用了用路由器吗?为什么呀?因为你们在同一个网段,清楚了码?,因为你们在同一网段,是不是这样的?这个,那传输层有个叫 TCP 或 UDP 协议,这两个协议咱们讲编程的时候会给你讲这个,这两个叫什么呀?在传输层,这一层主要是传递数据,那么这个呢?定义了端到端的传输,那么这个呢?网络同事定义了点到点的传输,那么有同学问了,什么首页点到点,什么叫端到端?我在这给你解释一下,这是我机器a,同学们,这是我机器b,是吧?中间是不是经历了好多同学们,反正有 n 多个,反正具体咱就不说多少个了,知道什么意思吗?这每个值,每个都称之为一个节点,清楚吗?一个节点,那么其中端到端指的是 a 到b, a 和b,叫端到端是不是两端啊?是不是点到点啊?a到这个路由器,这叫点,这个路由器到这个路由器叫也叫点,这叫点到点,清楚了码?端到端和点到点就这意思。

其实你看这个字面意思是不是能看得出来?点是不是端?端是不是两端?是吧? 起始端和什么呀?终止端吧?这个数据从 a 端发到b,这个 b 端, a 和 b 叫两端,那么中间是不是会经历很多节点?每一个节点叫点是不是这样的?

还有呢 会话层?那通过传输层建立数据传输的通道,这叫会话层。这些东西有,因为咱们是直接感知不到的。为什么呀?因为这都是什么呀?都是内核帮你实现的,是你做的吗?不是你做的。咱们编程的时候是站在哪一层上?站在传输层这个协议上,就是咱们讲的这个,后面讲的这 socket a 的 编程主要就这一块,还有应用层,表示层是编解码翻译工作。

我举个例子, web 浏览器访问这个 web 浏览器访问 web 服务器的话,我他们之间是经过了这个翻译的,知道什么意思吧?是已经翻译的,举个例子,你这个服务器,你web服务器,你发送给浏览器用的是什么呀? UTF 8 编码,那么对话说到之后,他如果说他先显示中文,是不是还得使用 UTF 8呀?那么如果说这个浏览器给你发送数据的时候用的什么呀?GBK,你说你这个浏览器这边你不能支持 UTF 8这种格式的话,你能显示中文吗?是不是显示不了?显示不了,明白什么意思?这个双方的话需要一个编码,一个翻译的工作,关于这个编码,咱们讲项目1的时候还会给你提到,到底什么叫编码,到底什么叫编码?好,后面那个应用层是提供各种服务,那么这个ftp服务,它就是一个应用层的一个程序,还有后面什么 s s h,什么 email 等等,这都什么呀?都是应用层协议。

你看一下你们电脑上有没有装这个ftp?同学们, ,这个是不是ftp服务啊?这个在这个服务其实就在哪一层?应用层,那么大家想一下,你们写程序是写把程序写在哪一层?是不是应用层?是不是?后面这东西用你开发吗?同学们,什么物理层、数据量层,这东西用你开发吗?都已经是成型的了,清楚了吗?你用的时候你是直接使用应用层协议或者什么呀?开发一个应用层,一个服务程序,一般这么这么回事,这么回事。

 好,这是 7 层模型,这 7 层模型一块梳理一遍给你。这有一个顺口溜,我给大家编起来了,你直接记一下就可以了。怎么样?物是哪层?物哪层?数 网呢?传会表,还有什么物数?网传会表,应用什么呀?应用层,应用是 7 层,咱们给你细化一下物理层,物理层都有什么东西?通信介质,比如说什么呀?双绞线,双绞线 还有什么呀?光纤是不是?嗯,还有什么什么什么他调,,调节器 modemen 是不?这个modemen 它是干什么用的?模数转化,和数模转换,明白了吗?这是物理层第二层,大家注意这个物理层是不是应该处在最底层?我倒着写,知道什么好,这层叫什么层?数据链路层。那这一层提供了什么服务?数据校验是不是有啊?给你听一听,你先不用死记硬背,至少来说你把 7 层先记住。

物数网传会表应,数据链路层定义了什么?数据格式,什么?帧,数据帧格式,也就是说从网卡当中发出去的都叫帧,帧,其实就是一个有格式的字符串。这么理解就可以了,不要把它想的太复杂。这里头有一个协议叫什么协议? a r p 协议,还有什么呀? r a r p 协议。这个你每一层记住这么一两个清楚了,不要一个也不知道再往上,再往上什么是网络层是吧?这个定义了什么到什么的传输?点子点还是端到端啊?定义了,点到点的传输是吧?这一层有一个重要的协议,叫什么协议? IP 协议。搞清楚,人家问你 IP 在哪一层,你得知道,ip协议,是吧?那么有一个设备叫什么设备?路由器,别搞混了。好,再往上。兄弟们,传输层,传输层定义了什么呀?同学们,定义了端到端的什么呀?传输,端到端传输。那有一个重要的协议叫什么协议?叫 t c p,还有什么协议? u d p 协议是吧?你把这常见的记住就可以了

好,这传层咱们后面讲这个 socket a 编程的时候,主要就是在这个传输层协议上写东西清楚了吗?好,再往上。会话层。那这一层主要是干什么呀?什么建立会话和什么保持会话?建立会话和保持会话?什么叫会话?同学们,那么两双方这个 a机器和 b 机器之间要通信,是不是首先有个会话,你把它理解成什么呀?相对建立一个信道,你能理解吗?你们相当于建立信道,就说你要想给别人同学,是不是你首先得给别人建立一个联系?那么你想给别人打电话干什么呀?想给他拨通这个之前这个传输,这个性能保持,就是会话所做的事情。

那再往上兄弟们表示层吧?主要干什么呀?主要是进行什么工作?进行编码、编解码和翻译工作,每一层都有每一层的事情要做好,再往上什么?应用层 应用层主要就这些什么呀?应用程序有哪些?因为你常见的 f d p是不是明白? s s h是不是 e mail 是不是? email 也是,那个 email 是一个服务, email 是一个服务,还有什么呀? http 是不是?也是 http也是?你像这个http协议是不是我们可以直接拿来用啊?咱们后边讲这个,那两条案例的时候用的就是这个协议,叫 http协议。

好,是这个,这是 7 层模型。 7 层模型这个大家这每一层模型都代表什么意思?你大致读一读,如果说你这个每一层代表什么意思,你实在先记不住,你先不要记它,你先把每一层叫什么名儿先记住,知道吗?每一层有什么协议?你得知道,好,咱们接下来再看一下这个四层模型是我们真正的在网络过程当中使用的这个四层模型,咱们看一下它怎么回事?看一下第一层叫网络结果层,那么这个网络结构层,它对应于 7 层模型的下两层,是不是就是物理层和数据链路层?对应这两层能理解吗?好,那么再看网络层,它对应于 7 层模型就是网络层,那这层有什么协议?是不是 ip 协议?有什么设备?这一层上工作的设备有路由器,再往上传输层,那么对应的 7 层模型就是什么呀?传输层, 7 层模型里面传输层。

 好,这这个传输层有哪两个协议? TCP 和UDP,这两个是用的比较多的两个协议。再往上是不是上3层?对应应用层吧?这 7 层模型的最上面三层对应的就是,应用层,那么这应用层有哪一些服务?这个有哪些服务? email 也好,是吧? ftp 也好,ssh ,http这些都叫服务,好,我问一下这个服务会退出吗?那么服务应该是一个什么样的进程啊?是不是守护进程?兄弟们,你看一下我们这个 http 服务,我们现在是不没用过他呀?同学们,没用,他是不是一直开着呀?邮件服务是不是也这样了?还有什么什么ssh,那么我们这个连的话大家注意,我用终端设备,我用终端这个secureCrt 这个终端的话,我连这个 Linux 虚拟机的话,我用的是不是 s s h?怎么看?同学们,这些是不是??同学们,这就是,能理解吗?这里面都什么呀?都是 s s h。

 好,这个是不是 ssh 那个服务,你把这个杀死之后,你的东西立刻就全部关掉了,这个自己试在这,咱就不耽误时间了。自己试好,我记得有一个学生是这个,这个用这个终端,用它这个终端工具连不上虚拟机,后来它装这个 s s h 就好使了。是不是有的人这个上面这个虚机没有装,你得装一个,不装不行,是吧?这个,但是我们说这个东西,看过这个玩意,同学们,这个是不是我也可以连这个?我的这个服务器啊?

这个用的不是 ssh,用哪个?ftp,搞清楚,这是不一样的。好,那么这是这 4 层里面每一层有什么协议?那么应用层级什么?

Telnet,FTP, email 。Telnet也是一个协议啊

也是一个协议,什么传输层有 TCP UDP,网络层有什么?IP,ICMP,IGMP,什么什么链路层有这些,这你看一看是吧?每一种东西大致说一说就可以了。好,咱们给你捋一捋,看那四层模型有什么模型?同学们,嗯,四层模型,这,这个叫什么呀?这个叫 TCP 四次模型。有什么有什么?同学们,第一个什么呀?最底下网络接口是网络接口层,或者叫数据链路层也行,网络接口层再往上,网络层再往上,传输层,再往上,应用层,这个应用层对应每一个对应关系。

跟你说一下这个网络层对应于什么呀?对应于 7 层模型的什么层?物理层 是不是物理层和数据链路层,再往上这个网络层,网络层是不是对应?是不是对应的就是网络层,这个对应指的是 7 模型,这个你看清楚就可以了。对应传输层,再往上,是不是后三层,上三层是不是?会话表现意吗?会话层,表示层 应用层。好吧,这是这个 7 层模型和 4层模型

,那么这一块要求给大家的要求是这样的,你把这7层模型每一层叫什么名字搞清楚,再一个呢,每一层大概要干的什么事情也搞清楚,有什么协议是不是搞清楚就可以了?这个咱们写代码的时候我跟你说一下,你用不着它,清楚吗?这个主要是让你去应付什么呀?面试的是不是?或者说咱们说的这怎么说?这个你学这个网络编程上是不是这几个知识你得知道吧?你不能光懂那几个函数,是不是?对,咱说到这,好,朋友们都安静一下。

行,同学们安静一下,咱们接下来讲什么呢?讲一下这个数据通信的过程。举个例子,看这个图里面,这图是我们的一台电脑 a 要将数据发送到PC机B,兄弟们,这两个中间是不是跨网段了?同学们看一下,是不是网络当中很复杂?这个你也别管他有没有跨网段,在这个有没有跨网站也没有关系,都是这样的,都是这样的。咱们就比如说还是不在一个网络,可以不在一个网络,那么这个 a 是如何将数据发送到 b 的?那把这个过程给你说一下。首先你看一下,那么是不是你要对外发送数据?是不是你?肯定得有一段数据吧?有这么点数据,看一下,这是数据部分。这数据接着看。那么我问一下大家同学们,你说我们这个数据发的话,是吧?咱们这个是不是刚刚讲了 4 个模型了? 

那么这 4 层它一步一步是谁有谁先,谁在前,谁在后,你的数据是不被应用程序发出去?对,是不是这样的?第一层是什么?是不是应用层?这个数据是谁准备的?同学,数据相当于用户程序准备的?是不是?肯定是这样的 ,好,这数据部分。那么接下来那么数据要往外发的话,它是不是经过 4 层,从上往下,最后由网卡是发出去?你搞清楚,不要搞反了,但是结束的过程是不是正好相反的啊?从用网卡发出来是不是?然后一点点往上是不是?好,咱们先说这个数据发送的过程。好,这数据部分有了以后,那么接下来是不是你要进行发送了?往外发的话要经过 4 层,这 4 层是怎么一步一步加上去的?好,第一步是这么来的,先用数据,这个事情要发送数据,这数据。同学们,好,那么接下来在数据前面要拼上一个什么呀?拼什么?是不是要经过 4 层啊?先拼什么?要先拼应用层、数据,应用层头部或者叫,第五层,知道什么意思吗?我是不是跟你说 4 层了?那 4 层怎么个意思呢?你这个数据部分是核心,那前面那几层是一点点给你拼上去的。

我再问一下,这个拼的过程是你做的吗?不是谁做的?内核帮你做的。你搞清楚你做的事情只是准备这个数据,这是你的程序需要做的事情,其他事情你不用管,包括这个发送出去也不是你也不要你管,是不是网卡给你发送出去是不是?好,这是应用层,咱们给你写清楚这是数据部分,这什么部分?同学,这是应用层,你要知道这经过了哪几层,接下来再看。

那么如果说从应用层再往下走什么层?接下来就传输层了,这个是不是传输层 好?那么有传层,是不是接下来你应该把这个传输层的这个首部给加上去?头部信息 传输层,好,那么也就是说应用层再往下是不是应该是传输层了?那么好,他怎么做的?内核会将这个传输层的这部分信息给你拼接到应用层的前面去,就成这样子了。

这是传输层,能看到什么意思吗?同学们是不是又加了一层啊?好?再往下走,那再往下的话是不是成了网络层了?

那么也就是说这个传输层的前面是不是再加上一层?是不是再加一层?

这叫什么层?网络层,这一层你看看我给你分析这个过程,是不是一层?好,现在是不是到网络层了?那么到网络层,这你的数据能发出去吗?兄弟们,我大家是不是上节课说过了,你的数据要发送出去,必须是从网卡发送出去的。数据的格式是什么呀?同学们,是不是帧的?那是数据帧格式。好,这是网络层,

那么网络层再往下到哪了?是不是最接近物理层了?同学们,接近物理层了,再往下就成了什么了?网络层再往下叫网络接口层,你可以把他称为什么什么 数据量层也行,这个没有关系的,这个叫,网络接口层。数据链层也可以,说法不一样而已。

好,那么前面是不是再拼上一层?这叫网络接口层。兄弟们,好,那么这 5 层现在是不是有了? 那么这 5 层都有了,那么接下来你说你的数据该干什么了?是不是数据都备齐了?备齐之后,这个数据最后由网卡发送出去了?你的网卡,你说网卡在外面直接接的谁啊?接的是不是你跟网卡通过双截?你是不是接到路由器上去了?或者接到哪去了?猫德姆上面是吧?是不是? 那个是叫猫德姆是不是接那了?好,你的网卡出来之后,你的网卡数据,这个数据从你的网卡出来的时候,这个数据是什么数据?同学们,是不是数据信号是不是?是不是 0101 这东西,然后接这个猫德姆,把这个 01 转换成什么呀?高低电平通过网线发送出去,是这么回事,能理解吗?那么所以说通过这个图来,通过这个图我们能够想到的什么呀?这个数据部分,同学们,数据部分,应该是我们的整个核心,知道什么意思吗?你这个网络传输,这最终是不是传输的是数据部分?那么前面这些东西是不是都相当于控制信息?这里面是不是什么应用层、传输层、网络层、网络接口层,这些是不是都是协议?同学们,是不是都是协议?好,那么你比如说应用层用的有什么协议?比如说你用的是ftp,那它是不是就是 FTP 协议?那么好,你传入层你用的是 TCP方式,那么它是不是用的就是 TCP协议?好在网络层肯定是有什么协议, IP 协议,再往下是不是这个?最终你这个网络接口层,你这个数据是不是要封装成帧  数据帧格式吧?最后由网卡经过网线,发送数据,是这么回事,那所以咱们这个数据从上往下它的过程是不是一个层层打包的过程?对,是不是?好,我给你画一下,往下的在这,这个是不是层层打包过程?同学们,是吧?我给你写一下,

从上往下是什么呀?其实就是发送过程,是吧?同学们,发送端发送方。这个是什么呀?是不是层层打包过程?是不?这个过程。同学们,这个过程好,那么我问大家,那么如果说接收方呢?对方接收到对方的网卡,接收到你的数据,是不是这个?最下面这个是不是一个?好,接着看他接收到你的数据,这个是,这是 PC机 a,后边的是什么呀?PC机B,他先收到的是什么东西?是不是这个?是不这个?注意看是这个,再往上,兄弟们,再往上。

那么他收到你的数据之后,你的网卡收到数据之后,他是不是要做一些工作?什么工作?比如校验是不是等等?同时他还要干什么?他是不是解包把谁解掉?是不是要把这个网络接口层这一层给你去掉?能理解吗?给你去掉,去掉之后就剩下什么了,是不是就这一层了?是吧?我给你放这来,说到这,同学们,你的这个,嗯,我看这样画不好,就这样画吧。

现在这个是不是网络层了?网络层通过这个你的网卡,是不是同学们通过这个网络接口层,他给你把这个他网络这个网卡接收到的数据一定是帧格式,一定是帧格式,他首先给你把这个网络接口层这个头部信息给你去掉,那去掉之后是不是接下来到网络层了?在网络层这个网络层这边是不是只有网络层、传层、应用层和数据?兄弟们,再往上网络层,再往上,是不是这层?注意看是不是这层?这一层,那么通过网络层的解包之后,他是把网络层这一层给去掉了,去掉之后是不是就剩下上面人了?是不是?传层、应用层和数据,是不是同学们,看,是不是到这一层了吧?好,再往上是不是就剩下这两层了?是不是,直接给你扒出来了,是吧?是这个,当然传送在往上什么什么层?同学们,是应用层,这个时候相当于你的应用程序是不是收到数据了,是吧?比如说你ftp,ftp,这个服务端是不是收到数据了?他是不是要把这个应用层的数据这个包给解掉啊?解掉之后最后只剩下的数据是不是才是你真正想发的东西?是不是同学们,这个才是你真正想发的东西?这是数据部分。那么这儿我给大家出一个思考题。

什么思考题?那么你的网,你的这个手机在记流量的时候,同学们,是吧?你比如说你只发了一个字,好发给对方了,是吧?一个字一个汉字,比如说占两个字节。是吧同学们,那么你说你这个,实际上你这个你的流量走的是两个字节吗?为什么呀? ,因为你的程序是不是要经过好多打包啊?打包之后肯定有些控制信息夹在里面了,对,那么对方说的时候他被解包了,是不是这样的?那么这些控制信息也占流量的,否则话人家服务商是不亏大了,是不是人肯定把这个部分也给你记下来了,知道什么意思?那么这个刚才我们讲这个过程,什么过程的同学们想一下,这接收方应该是一个什么过程?接收方层层,是不是接收方是层层解包的过程啊?是吧同学们?这接收方,这是层层解包过程,能理解吗?同学们,这个数据的这个传送过程就这样的,这是发送方,那么从应用层的往下是不是层层打包啊?好?那么接收方是从下往上是不是?当然你得知道收到你数据的肯定什么呀?肯定先是网卡吧?然后再往上是层层解包。

如果这个你不十分理解,那我给你举一个现实生活中的例子,你就理解了。那你比如说你要发送发信了,现在,当然现在已经不写信了,是吧?同学,现在有微信了吗?还写信干什么呀?是吧?你要发信了,那么你要发一封信。举个例子,有老板要发信,那么老板要发信的话,是不是他可能要这个?他把信,他首先是不是要把信写好?这是他必须要做的,他需要这封信。以后他叫秘书,他说小郭这个叫个快递员把信给我发出去。

反正信写好他不管吧?反正他就把信给谁了?给这个他的秘书了,是不是?他秘书之后拿到这个信之后,他是不是首先要把这个信放在信封里?是不是相当于干什么呢?是不是打包的过程啊?放在信封里去了?那么放在信封里以后,他是不是要把这个收件人的这个收信人地址和姓名电话写在这信封上?对,那么写这信封之后,他是不是要把这封信交给快递员?快递员收到这信封之后干什么呀?他是不是要装在他的包裹里?比如他有一个箱子放在箱子里面去了,然后他把这封信,最终这个快递员收到这些信息以后,他是不要拿走去,他是不要拿到快递中心,快那个发送快件那个地方那去拿,那以后把这所有的信息是不是打包?打包以后这是不是又是一个打包的过程?然后打包以后他要放在车上去,放在车上去把门一锁,是不是也相当于一个打包过程啊?这是层层打包过程吧?那么这个货运司机把这个把这些货送到对方以后,也就送到一个城市以后,比如说要发到北京去,是吧?同学们?那么到了北京之后,那首先干的是什么呀?同学们,把这个门打开是不是相当于开始解包了?把门打开,又拿出包裹来,然后再把包裹解开,解开之后可能这个包裹里面还有小包没有关系,还打开,打开之后一层一层打开,最后拿出来那封信来,拿出信来以后是不是交给快递员,然后送到接线人的手上就可以了。

那么整个过程是不是就是一个层层打包和层层解包过程了?能理解吗?同学们,就是这么一个过程, 那么你如果这个理解不了,我再给你举个你们感兴趣的,你中午吃饭的时候,你是不是要在网上订饭?好美团,比如说美团外卖你订好了,那么这个首先这个对方收到你的单子了,从那开始说收到你单子之后,他就知道了这个有人要吃饭,是吧?订好了,然后他是不是这个厨师先把菜给你炒出来?炒菜的过程或者炒饭的过程,是不是想得准备数据的过程?嗯,准备好了,然后放到盒饭里面,是不是相当于打包了?然后放到盒饭里以后,然后他又放到塑料袋里面,是不是又给你包一层了?包一层以后要交给什么呀?这个送外卖的人,送外卖的人拿到你这个饭以后,他是不是要放到他那个电车那个后面的箱子里面去?是不是放在箱子里面以后,咱们这个整个过程是不是从这个炒饭准备菜到打到这个,装到盒饭,然后到装到塑料袋里面,要装交给快递员,整个过程是不是相当于层层打包过程?能理解?好,那么这个快递员,这个送到这个,把这个发拿出来以后要送到哪?送到这个定饭的人手上?他首先是不是第一步应该是从这个箱子里面把这饭拿出来,是不是开始解包了?好,那么拿出来之后他要送给这个订饭的人,订饭的人拿到这个饭以后他是不是要把这塑料袋解开?解开之后他看看是不是我的饭,他把这个盒饭一打开,噢,的确是我的饭,那么是不是一个解包的过程?整个过程就这样子,能理解吗?那关于这例子,我在这个,我这个也给大家准备了一个什么呀?一个这个生活的实例,这个就送快件的实例,这个你有兴趣自己看一看 这就觉得快递的那个例子?快递的例子,也就是说有些东西你是不关心的。

 我问大家,那么你说你吃饭的人,你订饭的人,你关心谁给你送的吗?你关心谁给你做的吗?这些什么呀?相当于都是后台做的,是吧?那么对于我们这来说,我们这来说,我们这个从这个数据这一部分是我们自己的数据,下面什么应用层、传层、网络接口层,以及这个数据发送出去这些过程你关心吗?用你管吗?如果你写代码连这些关心的话呢,我给你讲一个月给你3万都不多,是不是?为什么呀?这个工作量太大了,而且很难完成这些,是不是在底层已经完全实现好了,你要做的事情就什么呀?在传输层之上写程序,那么传层在哪?是不是这一层上你用的协议就是 TCP UDP 协议,咱们后面讲的 socket a 编程就是在这一层上去写的,你只要在这写就可以了。

那么在下面什么网络层?网络接口层就你管吗?难道你还去研究一下这个模拟信号吗?数字信号吗?这些不是你研究的范畴,知道什么意思吗?,你关心你该关心的事情就可以了。好,那么这个整个过程咱们最后给你总结,只有一句话,总结出来就可以了。数据通信过程。总结一句话怎么说?在发送方什么呀?在发送方是什么呀?是数据层层干什么?打包的过程,在接收方,是层层解包的过程,你把这句话理解了就可以了,清楚了吗?那我讲的话,这个图从头到尾给你画了一遍,你应该能够理解了,能理解同学们这两个过程。

好,这整个过程是不是把这 4 个模型我给你说了一下,每一层,什么应用层、传输层、网络层,什么网络接口层,是不是都给你说了一遍?我们真正用的时候是用的 4 层,而不是 7 层。搞清楚,但是你这个 4 层和 7 层的对应关系你心里得清楚,你心里清楚,其实这个,嗯,这个你看多了之后,其实也并不难记忆。怎么说?你看一下,看我这个层数怎么说的?

这是第一层,是不是对应两层,这是不都是 1 层啊?后面是 3 层,你只要记住这第七层了,这也能记下来。 2113  2 + 1 + 1 + 3 是不正好 7 层,那么它是不是正好对应这顺序对应下来就是网络接口层,网络层,传输层,应用层啊?这不是这样的?你反正你不管你怎么记,你反正你自己得有窍门,清楚得有窍门。

好,这个说到这,你们这个看一看就行了。咱们简单给你说一下,咱们经常见到的这种网络通信模式有几种设计模式?其实你们可能有的人知道,但是不知道怎么说,是不是一个叫CS,一个叫BS,这是网络运营程序的常见的两种设计模式,是不是?常见的设计模式?那么什么叫 CS 模式?就是客户端服务器模式,那么这个需要在通信两端各自部署客户端和服务器,知道什么意思吗?这很明显的一个我这个东西SecureCRT,同学们,我这个什么同学,这是不是客户端服务端?是不是?我那个 Linux 操作系统啊?是不是虚拟机?那叫服务端,这叫客户端,这叫 CS 模式。

 好,再看,那么我用浏览器访问 web 服务器,比如说百度也好,什么什么淘,什么淘宝京东等等,这些属于什么呀?叫 b s 模式。 b 什么意思? browser 叫浏览器服务器模式,用的协议是什么呀? h t tp 协议,这叫 b s 模式,是吧?咱我这没联网,是吧?好,这个你们知道这个回事就可以了,叫 b s 模式,这是两种常见的模式,一个叫 c s,一个叫 b s,那么咱看一下,那么这两种模式那么比较一下有什么优缺点呢?这个你了解一下就可以了,不用死记硬背,不用死硬背。

那么你比如说这种对于 CS 模式来说,咱想一下这个 CS 模式来说,那么你这个本地的话必须装一个什么呀?客户端是不装客户端,那么你要装客户端的话,那么这个客户端如果说有这个恶意程序或者有绑定的东西的话,你知道吗?不知道。那么这种对用户概率,对用户的安全性造成影响。

当然你比如说你要是玩这个微信的话,你是不是也可以装这个电脑版?也可以装什么呀?手机版这个这些都叫什么呀?都叫客户端,你的手机号 APP 也叫客户端,不要搞混了,是不是都叫客户端?那么这些的话是不是你首先要装在本地上,是吧?本机,那么装本机之后你是不是就可以和这个远程的服务器进行通讯了?比如说微信聊天、 QQ 聊天等等都可以了吧?

那么它的一个不好的地方在于什么呢?首先你得需要安装,是不是你得需要安装?再一个这个客户端有没有恶意程序,或者有没有病毒你知道吗?不知道,但它有好处。嗯,好在哪?他稳定快,但稳定前提是没有毒,是不是没病毒,是不是快?还有它本地是不是可以缓存数据?那么你可以想一下 QQ 聊天,还有微信聊天,包括你看那图片,你下载文件是不是都会给你缓存本地了?是不是?这是它的优势,可以缓存本地速度快。

那么这个还有一个什么呀?你客户端的这个客户端这个界面的话,做得好的话是我们用起来很方便,是不是?这样的?那么大家再想一下,不好的地方,不好地方,你耗费本地资源多是肯定的,这不用说这个是不是这肯定的。再有一个的话再想,那么你这客户端需不需要你开发?我举个例子,比如说你开发了一套软件,比如说腾讯公司,你说他直接他直把他这个服务端开发出来,他不提供客户端能行吗?行不行?知道什么意思吗?因为你自己写个服务端,你是用 CS 模式,你只提供你直接弄一个服务端出来,你不给对方提供客户端,谁知道怎么用这个客户端,服务端是不是都得需要你开,你来开发?嗯,是不是这样的?再想一下,那么这个 b s 模式, b s 模式这个客户端用你开发吗?不用,你只需要使用浏览器就可以了。至于说你使用是 IE 浏览器也好,什么火狐,什么什么306 百度等等,是不是都可以?是不是他们都遵循同一个协议?什么协议叫 HTTP 协议?清楚了吗?只要有这协议就可以了。

在想,那么你说这个,我们在这个浏览器上访问的话,这个效率上是不是要低一些?为什么呀?因为有些数据它缓存不了,是不是每次都需要你输?有的时候是不是缓存不了?当然也有些是不是也能缓存的,但是它缓存东西一定比这个在本地安装客户端要差一些,是不是?而且大家再想一下,当这个协议的话是不是定死了?是不是都是http 协议啊?能换其他协议吗?换不了 大家注意换不了,因为这个,因为这个浏览器不是你开发的,当然你这个 web 服务端的话,是不是也必须要遵守这个怎么样 HTTP 协议才行?不遵守这个的话web浏览器能访问吗?访问不了,知道什么意思吗?还不了那关这个关于这个它的优缺点,你就我就大家跟他说这么多,那么另外的话大家还想一下这个http协议,还有一个优点,什么优点?那你开发的时候是不是不用开发这个?是不是工作量小,你只要开发服务端就可以了,是不是只叫开发服务端就可以了?再有这个,那么你说这个浏览器的话,它受平台限制吗?受不受?那么你说你能不能在 linux上访问百度啊?

当然可以,windows是不是也可以?苹果本上是不是都可以?是吧?同学们,反过来同一款客户端是吧?同学们,你能装在windows下,能装在 linux上吗?能不能?肯定不能,这连想都不用想,一般你下载客户端的话,后面写着 for windows、 for Linux、 for Mac OS 等等,是不是说的你清楚没有?是不是包括什么呀? 64 位、 30 位都给你说得很清楚,你不要乱下,你在你的这个,你比如你是 30 位系统,你下来个 64 位的能装上吗?装不上。

是不是装不上? 30 位的应用程序能装在 64 位的系统上吗?可以,反过来不行,清楚吗?反过来不行,你 64 位的应用程序不能装在 30 位操作系统上,但是 64 位的操作系统可以装 32 位的应用程序,是不是?向下兼容啊?同学们?向下兼容好,这是这个客户端浏览器这种 b s 模式或 c s 模式,它的优先点分析咱们大致说一下就可以了。这个你把这段话自己读一读。

好。这个网络应用程序常见的两种设计模式,第一个 C/S 吗?第二个 B/S 模式,是吧?那就给你写两句,优缺,其实优缺点是不是它俩是相对来说的?兄弟们,先看 CS 模式的优点什么呀?同学们,是不是速度快,效率高,可以安装在本地,可以安装在本地,可以缓存数据,是不是了?可以缓存数据,另外这个,可以选择的什么呀?协议叫叫协议选择灵活是吧?协议的选择灵活,兄弟们,这个你大致看一看,还有什么呀?优点是吧?嗯,这个当然显示效果是不是要好一些?因为你这个界面开发的话,要开发好一点的话,是不是我们用户使用起来是不是比较友好,用户使用起来比较友好?这个缺点你总结两点怎么样?当然这个客户端是不是需要也需要由你来开发?客户端工具需要由程序员开发,是不是开发周期长?工作量大,是不是同学们,你想一下,嗯,大家可以试一下。

你说开发一个服务端周期长,还是说开发一个客户端周期长,大家注意有的时候开发一个服务端周期并不长,清楚了,真正开发周期长。有的时候客户端你可以看一下你那个淘宝那个客户端,你看一下里面有多少东西,你再看一下你那个支付宝那个里面是不是好多?是他们好多。

当然你这个客户端的开发量大了,服务端肯定相应延长,是不是因为他们之间要协商很多东西要一块来开发?你在你的支付宝的客户端上,如果说你开发了一个租房的这么一套一个软件的话,一个应用的话,那么你服务端那边是不是也要做相应的调整?是不是这样的?肯定这样的,就这个开发的周期长,工作量大,是不是?那么还有什么缺点是不对?它需要安装啊?嗯,需要本地安装,那么对对客户的,电脑安全有一定影响。因为你装的时候你并不知道有没有毒,万一有毒呢?,万一正好监控你的个人隐私,是不是?你比如说你装置这个软件他正好有这样的功能,它可以读你某些目录里面的什么呀,文件信息,然后给你上传到哪了?上传到他自己的服务器上,这是有可能的。知道什么意思吧?是可以的。比如说每天你只要一开,然后就给你传他在后台做的事,你能看到吗?是不是看不到?也没有任何日志?你是看不到的,好,看下这个 b s 模式。

BS 模式是不是就是浏览器?什么模式?浏览器 web 服务器模式。好,那么优点,缺点什么优点?同学们,首先你知道最大的优点什么呀?这个浏览器不用你开发,浏览器不用程序员开发,不用开发是吧?那么还有什么呀?开发周期,当然你这个不用开发的话,当然这个开发周期是不短了。开发周期短,是不?工作量小是不是你相对的,你这比较下说就可以了。

那么,那么,那么缺点兄弟们,缺点什么呀?是不是协议选择只能选择什么呀?只能选择,http 协议是吧?协议选择受限,还有没有缺点什么呀?嗯,不能缓存数据,不能缓存数据,然后是吧?这个影响客户使用,或者叫不能缓存数据,效率受影响。行,这个你自己列着写就可以了。

好吧,大致上就这么个意思,能理解吗?同学们,肯定是什么呀?有优点也有缺点,是吧?当然我们这个访问web服务器的话,是不是都得使用什么呀? b s模式吧?咱们第七、第八天的时候,咱们会讲一个这个,嗯, web 服务端开发这个会给你说这个,到时候咱们就用什么呀?当然浏览器是不是咱就不用写了?用浏览器访问他,访问一个目录读数据这么回事?好,这个就说到这。

好,大家把这个讲义打开,咱们看讲义部分,这个先来给大家说一个这个前面咱们是不是给大家讲过这个协议的基本概念了,是吧?好,那咱们就开始讲一些经常用到的协议,当然这协议不是说你在写代码的时候让你用得着,而是你需要对这协议进行理解。清楚了吗?咱们先讲一个最重要的协议,叫以太网帧,那么什么叫以太网帧?同学们从网卡当中发出去的都是以太网帧格式,清楚了吗?都是以太网帧格式,那么这以太网帧是包装在网络接口层的协议,网络接口层是不是跟大家说过了,也叫数据链路层,都是一个意思,你不要记混了。咱们看一下这个以太网帧是怎么样的一种格式呢?看能不能看懂。

 

 

 好,前面是这些叫以太网头,这叫以太网头,这些,后面那些叫数据部分。是不是一共分两部分的,同学们看一下每一部分代表什么意思?每一部分代表什么意思?其中头部信息一共有 14 个字节,大家注意在这是按字节来说的,这前 14 个字节分别代表什么意思?其中前 6 个字节代表目的地址,想一下目的地址到底在这指的是 ip 地址还是Mac? ip 地址应该是几个字节?几个192168,什么什么零点几?是不是点分十进制这种是四组数据,那个是四个字节,那个是四个字节,那么四个字节一定是 ip 地址。

那么在网络当中它指的是什么呀?实际上指的是整型值,后面你知道了,那么好,如果你如果说你看到这 6 个字节的一定是 Mac 地址,那是不是 Mac 地址?你看一下你的系统上这个 Mac 是不是 6 个字节的,怎么看?兄弟们,怎么看ip地址,是不是ifconfig?看这个,同学们,哪呢?这个是不是一个硬件地址?mac地址是,就是指的硬件地址,别搞混了,好,00 :0c :29 :7 F :37 :1 B 这些有同学说了,这不是,一共是这么 12 个字母,怎么是六个字节?什么意思? 00 是几个字节? 00 是一个字节,大家注意00,这个 00 是十六进制的两个数,十六进制两个是不是主要是一个字节?嗯,其实就是前面是有0x,同学们,是不是 0x00 是不是一个字节? 0x0c 是不是也是一个字节?好,那么一共是 6 个字节, 0C 297 F 1B 是吧?你们好,那么1B,你说转化成十进制多少?多少? 1 这个 1 指的16吧? b 指的是多少?是不是 11 加多少? 11 + 16=27,你得会算,你得会算,这是当然。我们一般情况下不会算硬件地址,但是这个inet会算。嗯,跟这个道理是一样的跟这个道理是一样的。这是不是 6 个字?那所以说咱们前面那个目的地址,它是指的是 6 个字节,指的是 Mac 地址,不要搞混了。

 好,原地址也是 6 个字节,很显然是不是也是Mac?嗯,那么什么叫目的?什么叫源呢?目的就是什么呀?你这个数据要发送到谁那去?目的主机的 Mac 地址就是指的是目的地址吧?也就是数据最终到什么地方,是不是这样的?那么原地址?很显然,这个数据是不是从哪发出去?比如说我这个数据从 a 主机发过去, a 主机的 Mac 地址是不是就指的是原地址?嗯,好。

类型分好多种,在这呢我跟你讲几种比较常见的,那么其中类型长两个字节。看类型,如果是 0800 0800 是几个字节?看清楚,这是 16 进制, 0800  08 是不是一个字节? 00 是不是也是一个字节?所以它是两个字节?如果这个类型是0800,它表示的是 i p 数据段, i p 是不是一个协议?大家记得同学我们讲这个数据打包的过程,是不是讲到了,是不是有一个什么呀?网络层嘛?嗯,网络层这些是不是都是 IP 层的数据?都是 i p 层的数据?好,那么如果是0800表示 i p 层,那么这个 i p 层的数据它尝试四十六到一千五,其实不止的是不只是一个。

什么呀? i p 数据报的长度,那么这个以太网帧格式呢?它的数据长度是 46- 1500,知道什么意思吗?最大是不超过1500。嗯,这个值怎么来的?据说是一个经验值,知道什么意思?什么叫经验值?是不是通过好多实验得出来一个比较合适的值?这个你也不用管它,反正有这么一个值就完了。但是最小这个值是规定好的,最小是 6 字节,最低的就是不能低于46。

那么后面还有一个四个字节的CRC,什么意思? CRC 校验,那么校验的是什么?校验的是你前面数据,对不对?是这意思吗?好,这是 0800 IP 数据段,它的数据长度是 46- 1500。跟你说过了,接下来看一下,如果是0806,它表示 a r p 请求 a r p 请求和应答,他用的协议是 a r p啊? a r p协议干什么的?是不是通过 i p 地址获得对方的 Mac 地址啊?待会我跟你说一下怎么获得的。那么这个它的长度是 28 个字节,大家注意 arp 请求和应答的数据长度是 28 个字节,很显然他是不够 46 个字节啊?那么后面补全啊?还差多少就补多少,现在还差多少?是不是还差 18 个?那么至于说补什么也是不用你关心的,这个反正你知道补就可以了,补空格行吗?可以,当然是你补的吗?同学们,是不是你补的?搞清楚,不是你补的 再接着看。

那么如果是 8035 是 r a r p 请求和应答, r a r p,那么这个它是不是也是 28 字节,后面也需要补齐?好,那么这是这个,这是我给大家刚才讲的什么呀?以太网帧格式,那么这个是不是真正你需要理解的?是不是需要理解?,你得知道这个以太网帧格式它大致是什么样的?比如说是你到前面 14 个字节分别代表什么呀?662,代表是目的地址、原地址和类型。那接下来后面有 46- 1500 是吧?同学们,那么这时候这个数据到底有多长?是不是你要看它的类型啊?如果是 a r p,请求它的数据类型,是不是它的长度是最长是 46 啊?当然它这是补齐了,后面是吧?如果是 IP 数据报的话,它是不是最长 1500啊? 等等,这些你得清楚。

后面还有一个什么呀? CRC 校验,还有 CRC 校验这个。那么下面咱们就以一个具体的例子跟你说一下。哪个例子?以 a r p 请求和应答为例,来给你讲一下这个以太网帧格式它到底是怎么回事?那么这个等于这个是以太网帧格式的具体协议,当然这个是以这个 arp 协议为例给你讲的。这个。同学们,这个整个这个东西(红色部分 )是不是一个以太网帧格式,是吧?同学们,当然这个以太网帧是一个 a r p请求或应答的。清楚什么意思吗?是 a r p 请求或应答的一个数据格式  那行,咱们就以这个为例跟你说一下。这儿我已经给你准备好这个图了,准备好图了。嗯,这个我直接先把这两个给你删掉。这个先,这是之前弄好的,然后我把这两个给你往上放,这个数据往下移一下,这样咱们说看着方便一些。

 

 

 看来这个线得重画了,那你知道怎么回事?就我大致给你画一画。那么什么意思?就是说我这个主机 a 是不是要给这个主机 b 发送数据 啊?

那么现在的数据是怎么样?数据是从这个 a 发到b,兄弟们,那么发到 b 呢?他想干什么呀?他想发送arp 请求和应答,当然应答是不是 b 发给 a 的?是不是同学们?好,咱们看一下这个格式,看看你能不能看懂,先给你讲这个格式。好,前面662不用讲了吧?,是不是同学们?现在有硬件类型,什么硬件协议,还有什么协议地址长度 ip地址长度,这东西也不是说哪个人你都需要记 这个里面,你只要能够查照这个格式说出来就可以了,不用背 清楚了吗?这东西不用背,而且因为这东西是不是也是不是我们写代码用不着,但是给你这么个东西你能看懂就可以了。

是不是同学们?好,那我问大家,如果说让你解析这个协议的话,给了你一个报文,给了一段数据,这个这段数据就是这个格式的,让你去解析,你能解析出来吗?怎么解?是不是按位截取就可以了?懂什么意思吗?比如说你前面 6 个,那么我直接读出 6 个来是不是就知道他的 Mac 地址了?我再读 6 个是不是就知道什么了?我自己的什么呀?原地址的那个地址吧。实际上这个用哪函数可以做到?同学们,哪函数了?这个是这个数据,比如是 s t r,兄弟们, s t r。

那么如果说我让你把这个前面这 3 个给你截出来,以太网目的地址、原地址和类型截出来,你怎么截?怎么截?mamcopy不就完了吗?同学们怎么不敢说话?mamcopy  st r 是吧? 6, 截前 6 个是不是就截出来了?然后呢?我这 S2 再加6,再截 6 个,是不是就把中间这个截出来了?是不是再加12?是不是再截 2 个?是把这个截出来了?是不是 3 个都有了?清楚了吗?这么来的,你能够把这个看这个协议,能够把这个数据给截出来就可以了。

一般这么做,为什么要讲这个?你们参加工作以后,如果说你看到这种协议类型的时候,这种协议式你只要能会这个的话,其他的都会,知道什么意思吗?那个的话只是什么呀?字段名不一样,什么什么?长度不一样,是不是意思都一样?好,都看一下,帮我看一下,这里边有些值我给你填好了,你就不用关心了,你就不关心了,其实我这个整个这个长的格是不是和这个完全一样?是不是还是一样?再看一下,首先你得知道这个 ARP 你到底是干什么的?我举个例子,同学们看一下你看一下,兄弟们,我跟你说一下,这是我的一个主机,是吧?是吧?同学,这是个主机,想给另外一个人发发消息,这是一个 这是一个 好多个。同学们,是不是好多个?他要给这好,他要给其中某一个主机发送数据,但是他并不知道这是a,其他的都是最这个其他的机子。那么这个 a 想给其他的这个主机发送数据,他只知道对方的 ip 地址,但是他不知道对方的 Mac 地址。

你看一下我刚才给大家介绍这个以太网链接的时候,是不是有一个目的,什么呀? Mac 地址,嗯,他并不知道这个,他怎么办?这个时候他需要发送 a r p 请求给所有的主机,知道什么意思?比如说我要给你某一个人发送数据了,但是一开始的时候我并不知道你们的 Mac 地址,怎么呢?相当于先行先群发,那么群发之后,那么只有一个人的 IP 和这个你发送的这个数据里面这个 IP 一样,是不是只有一个人?一个子网段里面有没有这个?有没有两个人有相同的ip啊?那是不可能,是不是你们来了以后,你给一个人故意弄一个一样的,他那个上不去,你也上不去,是不是?明白什么意思吗?有两个主机不可能有相同的 ip 地址,是不是?那么也就是说这个 a 给所有的主机发那种发广播,什么知道什么叫广播?是不是全发?相当于群发知道吗?相当于群发,那么这所有的主机收到这个 a r p 请求包以后,那么他会比较一下他自己的 IP 和这个 a r p 请求包里面这个 IP 是不是一样,如果一样就接受,如果不一样就丢弃,知道什么意思吗?就丢弃。

那么这个主机把这个a r p 请求包收到以后,它接收以后,它把自己的mac地址填到这应答包里以后让发给谁?发给 a ,a 收到这应答之后,他是不是就可以知道?对方的 Mac 地址已经告诉我了,是不是就知道了?就这么来的清楚了吗?就有点类似于什么呀?我现在我不知一个人的姓名,我不知道我喊了一下,是不是咱们个人只有一个人答应了,他答应以后是否就知道谁是他了?是不是跟这道理是一样的?好,那么咱就给大家来把这个过程来分析一下是不是这样的。

首先看一下,这是我们的两个主机,主a,主机b,是吧? IP 和 Mac 都有,都有了。好,那么看一下这个 ARP 请求,首先目的地址,这填什么?目的地址是不是应该填这个呀?一开始你知道吗?不知道填什么?填 f 清楚了吗?全填f,这是你不知道的情况下,四个字节 5 个, 6 个,这是123456,这是不知道的情况。好,原地址 Max 地址你知道吗?是不是你知道吗?你肯定知道自己地址,是不是这个,嗯,我这就直接扒出来了,咱就省得去这个随便弄一个去了,这是不是原地址啊?好,类型的话,咱们很明确,咱们是不是要进行arp请求啊?所以我们填0806,这个 0806 是不是刚才讲这个?嗯,是不是这个 0806 就这个清楚了吗?这几个字节,同学们,两个字节,这是两个字节0806,接着我们接着看,硬件类型001,你不用管这是写死的清楚吗?还有一个什么呀?还有这个协议类型0800,这个你也不用管

这四个好,硬件地址长度多长,那么你说这个硬件地址长度指的是 Mac 地址吧? Mac 地址多长? 6 个字节,是不是 6 字节?那么这个硬件地址长度一共扎几个字节?同学看是不是一个字节,所以在这你填 06 就可以了。 06 是不是 0X 06啊?,是不是十六进制的 06 对不对?十六进制的 06 就是 6 字节,是不是?好,再看这个协议的长度,那么协议的长度想一下 04 指的是什么地址? ip 地址,这是 ip 地址。好,这是04,那么好,还有一个是 o p, o p 什么意思?你看一下我们这个,我们这个整个这个这个里面,这个整个里面是不是既可以表示 a r p 请求,也可以表示 a r p 应答,它怎么区分的?就是给你这 o p 来的, o p 为 1 表示请求,这个占几个字节?两个字节,所以填的时候是填0001,言外之意这是不是 0X001啊 ?是不是两个字节? 01 表的请求, 01 表示请求。

好,接下来看原 Mac 地址的指的谁,是不是你自己,所以这个直接复制一份出来,是不是填这? 好,原Mac 的地址。好,接下来继续看原 ip 地址,你知道吗?你肯定知道自己的 IP 也不知道吗?是不是好哪个?这个,填这来

?因为实际上在网络通信过程当中,你这个 IP地址填的时候不是这么填的,应该把这个字符串 192.168.10. 143 转化成什么啊?转化成高端字节序,也就是网络字节序的大端模式之后放这,那转弯之后它其实是一个 4 字节的整形值,清楚吗?在这你不用管那个,后面咱会说,放这是占 4 个字节。接下来继续往上看,那么还有一个目的 Mac地址你知道吗?目的 Mac不知道填什么?不知道填 f f,然后他这填 f f 是你填的吗?

,这些东西都不是你做的,谁做的?内核帮你做的?清楚,咱们现在是给你分析一下内部到底怎么做的?后面目的 ip 地址你知道吗?知道,你要连这个不知道没法通信了,是不是?192.168.10.149,好,把这个填过来,兄弟们,好,这个现在来说这个 a r p 请求是不是有了? a r p 请求有了以后他要进行广播了,他广播完以后,那么如果说那么接收到这个消息的主机认为这个不是他自己的IP,他干什么呀?丢弃了就不要了,那么这个广播的时候肯定有一个 IP 是不是这个?那么他一看这个是自己的IP,他就把这个包留下了,留下来之后他一看是 a r p 请求,所以他要回一个什么 a r p 应答,那咱们看一下这应答怎么回的?重新看一下目的地址。那么这应答谁回的?是不是 b 给 a 回的?别搞混了。好的,往下。那么你们这个目的地址怎么填?就刚才的那个发送是不是填应该填这个 a 的地址?对,所以这应该填这个原地址,是不是这个?是不是同学?不要搞混了。

好,原呢? 原是不是 b 的这个mac地址啊?嗯,所以应该是这个。这放过来,这些你不用管,这都是写死的。清楚,都是固定的是吧? 0806 是不是都是固定的,是吧? 0001 这个也是固定的,这也是固定的,这都是固定的,不用说了。好,这儿变了, o p 变了,如果不变,它能分得清楚。是,请求应答吗?分不清楚。好,这儿改成 02 了,是不是还是两个字节?嗯,是0002。就是什么呀?就是到底是请求还是应答,用这个来区分的。

 好,接着看好原mac地址指的谁?原mac自己是不是指的 b 的兄弟们是不是指的这个?嗯,接着看原 i p 地址呢?是谁,是不是还是指的 b 的 i p 地址,这个是不?这个,是不是这个?好看,后面这个,目的IP地址呢?谁的是不是就指的这个?对,好,放这来。

好,目的i p 呢?目的IP 是不是就指这个吗?好,现在我问一下大家现在这个 b 把这个 arp应答 包给 a 了, a 拿到之后能不能找到 b 的mac地址,能不能找到它?是不是从这个图当中就可以解析出来?第二个就是不是这个就是,明白了吗?那么通过 ip 地址获取对方的mac地址就这么来的,这里面有东西,像这些东西记不住也不用记?没有必要去记它,为什么我们一,我们不用。

 第二,面试的时候也不可能说人问你这个协议类型怎么填的,因为他也不知道是不是也没有问你这样的,就是说你得知道什么呀?通过这个例子我们给你讲了一些什么呀?这个以太网帧的这个 a r p 请求的格式,这个以太网帧是不是包含很多种?我跟你讲这arp只是其中一种,但是不管是有多少种,它一定遵循这个格式,是不是这格式同学们,目的是原地址类型,兄弟们,后面是不是还有 46- 1500 的这个数据啊?一定是遵循这个格式是吧?当然这个如果说小于 46 怎么样?是不是要补齐?补齐,这所有的操作都不是你干的。

 

 我刚才给大家讲究过程是什么呀?内核在这个做这个过程当中怎么做的?是不是这样的?如果说人家给你一个这样的报文,给你一个这样报文,你能不能参照这个图,这个格式把这个每一部分拆出来?能拆出来吗?很简单,就是mamcopy,是不是拷贝字段就可以了?是不是因为每一个长的数据你都知道?是不是知道这 6 个 6 个、 2 个、 2 个、 2 个,是不是按位截取就可以了?就这么简单?好,这个过程我就说这么多,行,我给你说一句话,说给你写上一句话,这个你得知道以太网帧格式,我跟你讲是 a r p 协议,关键协议你要知道这个协议的用处什么?干什么呀?同学们,这个用处是干什么的?是不是通过什么呀?通过对方的 ip 地址获取什么呀?获取 Mac 地址,干这用就可以了是吧?是不是还有一个反的是吧?那个自己看一看, r a r t 是逆向地址解析协议,通过 Mac 地址获取对方的,什么呀?ip地址。

 好,那么接下来咱们讲一下这个其他的几个协议,那么其他几个协议咱们就不再像 ARP 协议这么讲这么详细跟你说了,但是套路都是一样的,明白了吗?你只要把这个 a r p协议,哎,怎么知道怎么解析了?那么下面这些是不是都知道了,都类似的,咱们看一下这个 i p 协议, i p 协议,那么这个 i p 协议呢?是这么一个类型啊,看看这个讲义啊,4位版本,4位首部长度,这些是不是也是给你规定好了,每一部分都给你写好了,用记吗?同学,这东西不用记,你也记不住,你也记不住,你也不要去记它,咱们一个一个可以看一下,4位版本是什么意思,你看一下你用的是 ipv 4 还是 ipv 6?现在来说大多数情况下我们还是使用 ipv 4,那为什么有一个 ipv 6?朋友们为什么要提出这个?万一以后这ip地址不够用怎么办?是不是这个能扩充了?同学们,能扩充干这个用的,这是为了将来扩充用的,但是目前来说好长时间了,我们一直是使用 ipv4,清楚了吗?还有一个4位首部长度,这个咱不用关心,看这个8位生存时间ttl,这个是你需要知道的。

 那么什么叫 t t l?它的中文解释是下一跳的意思,咱这个跳的话不是这个那个那个,这个下不是下吓人的吓,是下面的下,那这怎么看?怎么看?我给你找一下啊, p ing一下就知道了。

local,看这个同学们,这是不是有 tt l 了?这个tt l是不是等于64?那言外之意是什么意思?那么我们在进行,比如说在进行网络数据传输的时候,那么它走过的节点如果说超过了 64 个,还没找到目的地址的,这个包就被丢弃了,明白什么意思吗?只要超过了,那什么叫超过了64?这是我服务器a,同学们,是不是那么中间是不是经历过很多节点,经过了很多节点,最后到达b,这b,是吧?同学们,好,如果说中间经历的节点超过 64 个了,还没找到这个b,是不是这个b就被丢弃了?为什么要这样做? 如果你不这样做,朋友们,那有没有可能他就找不到?那找不到是不是在网络一直传输,一直跳来跳去?那么是不是影响这个网络的传输,会引起网络阻塞?知道什么意思吗?会引起网络阻塞,主要干这个用的这个你得知道了解一下。得看后面这个 32 位原 ip 地址,这个很明显知道什么意思。

30 位源 ip 地址什么意思?30 位源 ip地址 是多少个字节?同学,是不是 4 个字节? 4 个字节? 4 个字节指的什么?是不是就这个,这个就是什么呀?点分十进制那个 IP 值吧?当然在这个这里面,它其实是一个 4 字节整形值, 4 字节的整形值,后面咱们会跟你说的。

还有 30 位的目的IP,这个不用说了。嗯,还有个8位协议。8位协议,这个是用来区分上次协议用的是哪个协议。那么我问一下大家这个 IP 协议的上一层是什么层? i p 协议的上一层 i p 在哪一层?同学们, i p 是不是在网络层?网络层的上一层是不是什么呀?传输层?传输层是不是有好多种啊?包括这种什么TCP、UDP、ICMP、IGMP,它是用来区分这个的,知道什么意思吗?你这个不懂,我给你看一个图,我看看那个图在哪?就这个有一个图,这个你们有预习的时候应该看到了吧?看到了,同学们,在哪?我看看。

那个二叉树,那个图类似于二叉树似的分叉那个,这个图,看一下这个是不是四层模型?同学们,应用应用程序出出哪?出在哪一层?是不是应用层?应用层是不是既然是TCP、UDP 这些是哪一层的?同学们,这些是不是在传输层?你看传输层一共有传输层的协议,一共有几种?是不是好几种?那么下面是不是IP 层啊?是吧?这些是不是处在同一层?最下面是什么层?是网络接口层?是不是一层、二层、三层、四层?是不是到 c 到这是不是就成了数据帧了?数据帧是这么来的,这么来的,这图你得看能看懂什么意思?那么也就是说这个 IP 层再往上什么层,它有一个区分得,是吧?如果说,比如说这个 0 代表 SMP1 代表这个, 2 代表这个 3 代表这个是不是你可以区分啊?这这么来的,这么来的你得能看懂啊,那么还有一个 16 位首部校验和这个是对数据进行校验的,当然这个里边他说了是只校验 IP 首部,是吧?只校验 IP 首部,那么这个是不是就是 IP 首挂,是吧?那么后面的话还有数据,如果有的话有没有的话就没有,这个有没有是不是看具体需求?具体需求好,这个里面要求你掌握的是哪个?这个8位生存时间,这个务必知道啊,这知道怎么回事就可以了,什么 32位源IP地址,目地址,还有8位协议是吧?好,你看这个有一个 16 位总长度。

 那么问一下大家, 16 位指的是什么呀?同学们指的几个字节是不是两个字节? 16 除以 8 等于两个字节是吧?两个字节最大可以表示多少数? 2 的 16 方减 1,0- 2 的 16 方减1,是不是65535啊?是吧?这么来的,是吧?那么也就是说实际上你这个数据的部分是不是最长可以有这么长?因为它是什么呀? 16 位总长度指的什么呀?指的数据部分的长度,清楚数据部分的长度,那么其他的话就没有什么了,没有什么了,这个还是那句话,不要背这个图也没有必要清楚吗?那么你给你一个这东西,你能够自己照着这个图能够把这个什么呀?数据给它拆分开就可以了。

给我们前面讲的 arp是不是类似?朋友们给那个是类似的。好看这个UDP,那么 UDP 就比较简单了。 UDP 比较简单,那么 UDP 有哪些?有 16 位源端口号,那么这个源端口号是 16 位,那么你说这个端口号最大表示范围是多少?是不是就是 0- 65535啊? 2的 16方减1,是不是这样的?那么其中有些端口你是不能用的, 1024 以前可能是那一些端口你不要用。为什么呀?那些是系统预留的端口,你要用不得了,你用一个是你的也用不了,你的服务起不来。你用的什么呀?用后面的清了吗?用后面的,比如说 8000 以外的, 9000 以外都可以,就你的服务不就那么几个吗?你随便分配几个,你肯定够用,是不是?这个不用担心,还有 16 位目的端口,目的端口,这是谁?朋友们,是不是对方的,你要把数据发给谁?对方的那个端口号知道什么意思吗?还有一个 16 位 UDP 长度, 16 位 UDP 和 UDP 长度是不是也是 2的 16方减1啊?最大长度。 16位计算和呢?它这样的是不是就是前面这些数据的?这个有没有被篡改过?有没有修改过?或者是吧?还有数据,如果有的话有这个

 前面这部分一共是 8 个字节吧?,是不是一共是8 个字节?这时候我跟讲的是UDP,待会你看 TCP 比这个复杂。好,那这里面红色标记的是你务必掌握的哪句话?通过IP 地址可以确定网络环境中唯一的一台主机?知道什么意思吗?那么咱们这个班里面是不是有这个 50 多个人哪? 50 多个人?每一个人是不是有一个IP?那么这个 IP 是不是就标识了它的唯一的一台主机?是不是?比如你们某一个人给我发一个消息,我一定能看到你们是谁?为什么?我知道你 IP 是不是就找到这个人了?对吧?这样的,那么第二句话,主机上用端口来区分不同的应用程序,那么咱们这个主机上是不是有很多个服务?服务就是后台进程不要搞混了,就是说白了就是守护进程,是不是?那么只要是网络服务都会对外提供服务吧?那么他要对外提供服务,那么对方怎么访问他必须要知道他端口。那么所以说在我们这个服务器里面使用的是端口来区分不同的应用程序。好,举个例子,最常见的几个 21 端口,什么端口?20号端口是ftp, 22 呢s s h ,23呢,这几个是比较常见的,这个怎么看?这怎么看,那么我们有一个文件保存了这个端口对应的服务,也就是说每一个服务它使用的是哪个端口?有一个文件保存的这个,怎么看呢?

  

 看一下同学们,我跟你说的那个是不是这样的呢? f tb,看一下同学们是哪个?是不是 21 号端口啊?这个是他用的是哪个协议?这是不是 UDP 协议啊?这是 TCP 协议是吧?看看 22 谁啊?是不是 s s h啊?它有 TCP 协议的,也有 UDP 协议的。

兄弟们,23呢?是不是telnet啊?telnet是不是远程登录呀 同学们?知道这个telnet是干什么用的吗?我用本机可以登录远程电脑,是不是可以登录远程电脑?那举个例子,比如说你这个一个老板这个出门了,出门之后他电脑上有这个有信息,他目前需要知道这个时候他可以通过远程通路的方式登录到他远程电脑上,然后把电脑的信息把某些信息获取到就可以了,都可以,使用telnet远程登录

其实你的windows是不是也有远程登录呀?你比如说有的时候一个同学一个操作不会让你去指导他一下,是不是你可以远程是获取它远程录权限的,你就可以操作它了?这个就是用的远程录,后面什么什么,有一些其他的,看看有没有咱们明白的,看这个 HTTP 是不是也有啊?是不是用的 80 端口?同学,这像这些东西你得知道这些什么 21 23 80 这些常见是就属于常识了,是不是只要你见多了之后,这些东西很多都知道了,后面就不再说了,也就是说这两句话你得知道什么呀?通过 ip 地址可以唯一的确定一台主机,当然是网络环境中的一台主机,通过端口号可以确定一台主机上的一个服务。好, IP 加端口是不是就可以确定一台主机一个服务了?是不是这样的?这你得知道。这是这个,看看这个 TCP 协议, TCP 数据流格式这样的。首先前面是 16 位源端口号,这个知道什么意思?和咱们前面说过的是不一样了,最大是不是65535啊?好,还有 16 位目的端口号是不是表示对方的端口号,对方端口号还有 32 位序号和 32 位确认序号,这个务必掌握。

 

 什么意思? 32 位序号什么意思?我们这个数据在发送的时候,我们肯定是不是一点点往外发,那么在发送的时候会对某一个数据,每次发送数据给它来一个编号,给他来一编号,那这编号到底是几呢?这个你也不用管,反正这个序号是连续的。你比如你从 0 开始,那么发送,把 0 号发出去了,接下来 123一直往后排,这个这个,序号是干这个用的好,那么这序号有什么用?对方收到你的数据之后,他可以按照序号把这个数据重新给你拼起来,能理解吗?就是干这个用的,我举例子,举个例子,那假如说我们要给对方发一个文件,这个文件很大,兄弟们很大,那么如果说你用多线程接收的,知道什么意思吗?用多线程接收的,那比如说我这个文件分成了 100 份,我只有 5 个线程,每个线程是不是大概接收 20 份啊?你怎么把最后这个文件拼接在一起?是不是你可以给它来一个序号了?那么最后收到之后有一个进程,是不是整个把这 20 块?是不是把这一把这 20 块是不是一拼接就可以了啊?这序号可以干这个用。

好,那这确认序号有什么用呢?那么你每次对方发送数据,他有没有收到?他给你回一个什么呀?回,有一个应答,应答里面就告诉你了,我这个到底收到没收到,如果没收到会怎么样?会重传,你说这个安全吗同学们?这样是不是很安全了?那么 u d p 有这个吗? u d p 是不是告诉你不管了,这个有点类似于什么呀?有点类似于这个,你寄信的时候,寄信的时候你把这个 u d p 比成平信,什么意思?是不是发回去之后是不管了?是不有可能会丢?   同学们,这个 u d p会丢失吧?会,可能有可能会丢失。

那么你把这个 TCB 协议比作成另外一个挂号信,或叫快递挂号信,是不是每个都有记录?每走到一个接点都有记录?那么你这个信到底在哪丢的?他知道,那么那个平信知道吗?平信丢了就丢了,是不是?你们,你们有没有去过废品站呢?废片站里面有的那个信呢?那个废品站的那信一大堆一大堆的,怎么来的?是不是丢失的?有的邮局呢?比如说你邮局的发信的时候,有的是忘了发了。

有的什么呀?这个快递员去发的时候找不到人,他是不是就把这信拿回来了?好,这个确认序号,关于这一块你可能还不太清楚,咱们后面,后面会跟你说,那么确认序号是对刚刚你发送给对方的数据,他给你做一个回应,那么回应就在这个 32 位确认序号里面,这个序号里面就告诉你了他这个数据到底有没有收到?要重传,确保你发的数据对方能收到,干这个用的。

那后面的4位长度你不用管了,什么?还有保 6 位也不用管,这里面还有两个你需要重点知道的, ACK,这个得知道,还有这个SYN,还有个FIN。一个一个给你说一下,ACK 就指的是什么呀?确认,确认包里面的有一个确认,这个 ACK 大家注意 ACK 只有说你把数据发给对方了,对方给你回的时候才这个 ACK 呢,清楚了吗?你直接给对方发的时候没有这个 ACK 我是第一次,第一次的时候没有,清楚吗?好,那么这个SYN是什么意思呢?SYN 是在建立请求的时候,有三次握手过程会有这个SYN,这我先给你打个招呼,后面咱会有的,后面会有的,会这个SYN,这叫请求标识。

好看后面这个FIN 指的什么呀? 4 次挥手关闭链接的时候,会有这么一个东西叫FIN,其实就是叫fihish,fihish前面三个字母,就是关闭结束的意思,是吧?结束意思。那么后面还有一个什么什么 16 位窗口大小,这个咱们讲滑动窗口的时候,我跟你说这个,这什么意思?大家想一下,你说 a 给 b 发送数据,有没有可能会造成这种情况?你发的快,收的慢,有没有可能?那如果说对方还没收完,你又发了,有可能会造成数据丢失,那么他怎么办?他通过这个 16 位窗口大小来控制这个发送的这个量,知道什么意思吗?我让你发,你再发,我让你发多少你就发多少,那这样的话保证数据不会丢失,是不是这样的?看后面这个还有什么 16 位检验和 16 位紧急指针,这个检验和是不是跟那前面讲的 CS 校验是类似的?还是对前面数据是不是有没有丢失,有没有篡改过做校验的等等。

因为什么呀?大家想一下,这个实际上我们在传送数据的时候,在发送数据的时候,这个数据在网线当中或在光线当中传输,是不是高电平啊?那么这个电平有可能会被外部的这个信号干扰,知道什么意思吗?恢复干扰。我举个例子,有的时候你打电话的时候,或者你电脑如果是收到信号,电脑有的时候会有声音,是被信号干扰了,清楚了吗?有,是不是有呲了的声音?我反正我听耳机的时候,只要手机有信号,有人来电话就呲呲响,是吧?怎么来的?这信号就被干扰了?知道什么意思吗?被干扰之后,你说你的这个信号有可能是不是被篡改?嗯,会被改掉了吗?就不真实了吗?是这意思。 16 位紧急指针,你也不用管。好这个,里边为大家这个列出来这些数是需要你这个了解的,我们都知道这个 TCP协议是不是稳定、安全、可靠的?

 是面线链接的,刚才我们刚才讲的 UDP 是什么呀?不稳定、不可靠、无链接的,和这个是不是正好相反的?这里边有什么序号确认序号,还有这个 16 位窗户大小是需要你重点关注的,需要你重点关注,那序号是TCP,安全可靠。每一个数据包都有序号,那么对方收到这个序号之后,当有很多个数据过来,它最后拼包的时候,拼接在一起的时候,它用的就是这个序号,不然的话他怎么知道谁先谁后啊?是吧同学们,我举个例子,那么先发送出去的数据包有可能会后到,有没有可能?这是有可能的,但是不管,没有关系,这个事没事。

为什么呢?因为你有一个序号,它最后拼的时候还是按照这个序号来拼接的,这样的话我们这个最后的数据还是一个有序的数据,是不是这样的?那么这个确认序号是什么呀?使用确认序号可以知道对方是否已经收到了,我给你发送那个数据过去了,你会告诉我你是不是收到了?那么你怎么告诉我?你会给我回一个确认序号?比如说我给你发的 1 号数据,你又回了 1 号,那表明你收到了,是不是这样的?还有 16 位窗口大小,这个就是什么呀?进行流量控制,那么避免发送端发送的过快,接收端接收的太慢,造成数据丢失。

好,这个,嗯,关于这几个协议你就了解一下就可以了。刚才咱们讲什么协议?同学们, i p 协议还有什么? t c p 协议,还有这个什么呀? u d p 协议,

i p 协议。首先你得知道这个 i p 协议是在哪一层?在网络层,关于他这个协议的格式你也不用记,你只要能参照着那个格式能说出来就可以了。明白了吗?或者人家给你个包,你给我解析一下可以,那解析的话是不是你得给我格式?我要不然的话我怎么知道怎么解析,你只要参照那个协议解析出来就可以了。

UTP协议是什么呀?面向链接的,对,安全的,可靠的数据流传输。格式自己看好吧?格式不用记。 UDP 是什么呀?面相无链接的,不安全的,怎么样?不可靠的数据报,所谓的数据报传输是什么意思?这个东西要传一下,传完不能像TCP。这个什么呀?分块开。嗯,明白了,这个必须这样的,就必须一次性就发完,为什么?为什么要一次性发完?因为你是什么呀?没有序号,没序号无链接的是不是?那么你发两次,他怎么知道谁在前谁在后?是不是?这个就说到这。

好的,接下来咱们讲一下这个,给大家说一下这个socket的编程的简单介绍。先给你简单说一下,咱们看来上午的时候这个大小端这个可能说不完了,咱就不说了。行吧?咱就不说,下午再说。这一块就给你提一下。那么这个 socket 编程呢?它本质上也属于什么呀?也属于进程间通信。为什么这么说?为什么这么说?你想一下,如果这个进程间通讯是不是至少有两个进程啊?那么我这个我数据从 a 服务器发到 b 服务器,是不是也是两个进程间在通信的?当然这个地方是不是跨机了,中间通过网络?那么前面咱们跟大家就说过另外一句话,还记得吗?两个进程要通信必须要通过什么内核?通过内核是不是?当然我们的话这个网络,我们网络这个编程这一块呢?socket的编程,它确实也通过内核了,但是他还得通过网络,是不是多一个啊?本机的话用通过网络吗同学们,本机不用,你在一个机器上吗?是不用,那么但是是跨网络的,跨网络以后它不但使用了内核,而且还使用了网络,是不是还是网络?那么既然说这个刚才说过了,这个要通信的话,两个进程间通信必须要通过内核,那所以我们这个 soccer 的编程里面也有内核,哪个呢?看一下?这个你现在还可能还不清楚,我们要想通讯必须要有一个文件描述符,是吧?必须有一个文件描述,这个文件描述怎么建立?是调用一个函数,叫 socket 函数,那么这个建立 socket 以后,内核当中给你维护了两个缓冲区,一个叫发送缓冲区,一个叫接收缓冲区。你先听一听,那么对方的话是不是也得和你通讯啊?通讯是双方的事,对方也有一个文件描述符 ,这个文件描述符也有两个缓冲区,也是接收端和发送端,那么发送端左边这个发送端,右边接收端。

 

 

 看一下左边这个文件描述它对应的缓冲区 这个发送端对应的就是对方的接收端,也就是说你这个发送数据实际是发送到了他的接收端了。那么好,那右侧这个它的发送是对应的是左侧的这个接收端,是这么一回事,大家看一下,那么你说我这个里面链接有几个链接?其实是两个链接,叫 socket pair 叫链接对,那么有两个链接。那么是不是咱们后面会讲什么呀?半链接 半关闭,那也就说你只关闭一种是可以的,是可以做到的。就是说我,比如我这个服务器光收不发是可以吗?是可以的,或者怎么样?比如说你发送掉,发完之后你把链接关掉了,是不是这侧就关了?但是你能收也行,有一个叫半关闭,有这么一个函数咱们会给你说,好再看。

那么既然说有这个文件描述符,那咱们想一下,咱们前面讲这个文件描述符的时候,那么你说操作这个文件描述用什么函数了?哪个?咱们讲了好几个了 那就想一下这个文件描述一开始从哪说的?一开始讲文件描述时的时候,是不是文件IO啊?还记得吗?文件IO,那么 open 一个文件,它返回的就是文件描述符,那么我们操作这个文件描述就是用的read,write、close,是不是这些?再想管道的话,一个管道,这个管道是不是对应于内核的一块缓存区,那么这一块缓存有几个文件描述啊?管道有几个?管道是不是有两个?一个是读端,一个写端,那个叫一块缓存区,对应两个文件描述符。

但是你看一下我们这个 socket 文件描述,在于这个叫socket 的文件描述,这个 socket 文件描述的话,是不是一个文件描述符对应两个缓冲区啊?嗯,一个文件描述符对应读写两个缓冲区,是不是这样的?或叫发送和接收缓冲区都行,那么发送缓冲区,你说是是是写还是读?是不是写写数据?其实写到这个发送端了,那读是从这个接收端来读,是这么一回事,这么一回事。

好,关于这一块为什么人家起这个名叫socket? socket 它的英文意思是什么呀?不知道。插座你可以查一下吗?插座的意思是不是插座?那么插座有个什么特点?是不是有插口?兄弟们,好,那你想一下,那我们这个插座用的时候,你说这个口用你自己去弄啊?是不是你只要把这个公用这个插座拿回来,直接插到电源上是不是就能用了?然后把电扇一插,是不是一开关电扇就能转了?我们这个也是一样的,那么这一块的东西不需要你来做,这些东西内核的帮你做好了,清楚了吗?那么你用的时候怎么办?你只要调 socket 建立一个什么呀?得到一个文件描述分,然后你接下来操作的时候直接操作这个文件描述符就可以了。

是这么回事,那所以我们开发我们 socket API 编程其实就是站在哪个层上?同学们,叫传输层 TCP UDB 这个协议上去开发的,下层用你管吗?不用,你管清楚吗?下层是不用你管的,怎么了?听不懂这个同学们?嗯,听不懂别说一下,这个咱们下午才要讲具体函数怎么用我再跟你说。

 那么这说我现在先简单给你介绍一下,就说你要想进行socket的编程,我们得知道一个文件描述符,是吧?我们有了这个文件描述符是不是就得到两个缓存区?读写缓冲区 清楚了吗?读写缓冲区 对方是不是也得有一个缓存区?有一个文件描述啊 是不是?那么这样的话我们就其实链接建立以后,我们是建立了一个什么 socket 片。这个我也给你,我下午的时候咱们写代码的时候给你验证一下是不是socket 片是可以验证的,那么包括这个后面咱们讲这个 a p i 函数有哪些?创建 socket 通过这个函数我们就可以得到一个什么文件描述符。文件描述符这是操作,我简单给你提,给你捋一遍,绑定。

 

 什么意思?大家想一下,我们访问这个 web 服务器,访问这个对方的服务器是不是要知道对方的端口?嗯,比如说这个,我刚才跟你说那四个它是不是固定的? 21 23 80 什么的是不是都固定的?你自己开发一个服务端也一样的,你要绑定一个端口清楚吗?你不绑定行吗?同学们?没问题也行,但是对方不知道你端口是谁,不知道你是哪一个,他无法访问你,你不绑定,那么你这个服务每次启动的时候,这个端口都随机的,谁知道你是哪个端口?今天是,比如说是8000,明天也就重启 8001 了,后面8005,那么这个客户端能找到你吗?是不是找不到啊?找不到啊,这 bind 干这个事的。

将 IP 端口和文件描述做一个绑定,看第三个 listen 是监听是不?你们什么意思?我们这个文件描述符,你要把这个文件描述调用listen函数,把它设置为被动监听?大家想一下,我们访问这个客户端访问服务器,你说谁主动谁被动,是不是客户端主动,然后服务器被动,说这个服务器要调用 listen 时候,将这个文件描述符由主动变为被动,它只是处于被动监听状态。那么调这个函数以后,你的进程就处于监听状态了,那么客户端就可以什么呀?就可以连接它 清楚了吗?就可以连接它了。

 好,这是listen,后面accept。什么呀?是接收一个新的链接,接收一新的链接,这个函数会返回一个新的文件描述符,这个文件描述符就用于和客户端通信。这个函数的调用,包括上面的 listen,还有bind这几个函数调用都在哪?在服务端,在客户端啊?在服务端去调用,在服务端调用,后边什么什么connect,这个函数你想一下谁去调用?你说客户端是不是?咱们刚才说了客户端是不是主动连服务端的?这个函数就是客户端去主动调用的,那么你要连对方的服务器,那么你应该知道什么信息?你得知道连谁吧?这个谁怎么标识啊? IP 端口,你得知道,我是不是说了 IP 加端口,是不是就可以确定一个网络中的一台服务器的一个服务啊?是不是这样的?这你得知道这是connect,

那么连接好以后,接下来就开始什么呀?通信了,无非就是什么呀,读数据,发数据,是不是这样的?这两个函数咱们都见过了吧?咱们今天就要给你把这两行介绍一下,本质 两个函数差不多,只是多一个参数而已,这个参数我们一般填0。

 

 好,这个这一个模型,这下午再说。好,那么上午的时候给大家讲了一些这个理论上的东西,是吧?一些基本概念,比如协议,什么 7 层模型、 4 层模型,数据通讯过程以及协议分析,是吧?然后最后的时候给大家把这个 socket api 编程 给简单介绍了一下,那么接下来我就给大家讲一下这个编程相关的东西了。

 

 在这个讲 socket 的api 之前,先讲一个知识,哪个呢?字节序的问题,这个的话大家学 c 语言的时候应该接触过,对吧?应该接触过,那么这个字节序一共有两个吧?一个是大端字节序,一个是什么呀?小端字节序,或者称之为高端字节序或低端字节序也行。什么意思?看一下咱们这个概念这么说的,看大端低位地址存放高位数据,高位地址存放低位数据,能理解什么意思吗?看看这小端什么意思?低位地址存放低位数据,高位地址存放高位数据,这个小端是不是正常的,是吧?正常的顺序,关于这个咱们也不用过多的去说,因为咱们这个一个是接触过,再一个本身没有什么太难的,特别是需要你注意一点,是什么呢?这个网络上传输数据的时候,它用的是高端字节序,那所以这高端字节序也叫网络字节序,清楚吗?也叫网络字节序,这个你得知道,这儿我有一个例子,咱们直接把例子看一下就知道了。

如果让你写一个程序,让你测试一下你的主机是高端字节序还是低端字节序,你能写吗?能不能?大家注意这个?考试的时候有可能会出到。  这个你得会,我直接给你打开一个例子,咱们看程序可以了,因为这个程序很简单, Day 10,这两个程序基本一样的,随便看一个就行了。看这个程序,这个就专门用来测试什么呢?高端字节序还是低端字节序的?看一下我们用的什么呀?用的union是不是共用体啊?或叫联合体。

 

 这里边我定义一个short类型,然后定义这个c,是吧? c 这个数组的长度和这个是不是一样?这个是不是两个字节6?,嗯,这个 c 是不是也是两个字节?嗯,是吧?好,这是个Int  10,这俩是不是一样的?那一样的。接着看,我给它去赋一下值,我给这个 s 赋一个值,叫 0x0102,能看出什么意思来?这个是几个字节?同学们,是不是两个字节啊?好,然后呢,咱们打印一下这个 c 的值,打印一下 c 的值,那么我先问一下,先问一下这个,你先别看了,其实这两个你看懂应该就知道什么意思了。

那么你说如果说是低端字节序,那么 C0 应该打印成是几?低端?这个是C0,是不低端的。低端地址存放在什么呀?存放的是低端的数据是 02 了,所以这个的话是不是应该是01啊?那反过来,如果是高端字节序,是不是存放和这个正好相反的,是吧?同学们?好,这个你心里清楚就行了。然后 u n 2 点s,它的这个值打印出来,是不是和这个存放的顺序也有这个影响?嗯,咱们看是不是这样的?这个是不是和这个一样0x01020304?这个是不是多一些而已?是不一样了,这个是 4 个字节,嗯,这四个字节,这个 01 02 03 04 高端字节序和低端字节序,它这个最后的显示结果应该是不一样的。这个程序你把它看明白以后,你晚上敲一遍。为什么这么说?这个考试的时候,我当时刚刚毕业的时候,这个我面试公司的时候考的,的确是考过这个题,明白了吗,的确是考过,没玩过的没,就是没动过。这个东西他肯定不知道,他想不到这一层,清楚了吧?他想不到,我给你验,我给你看看这个结果。

 这不用管它warning 不用管它,看一下,一个是248,这个打的是这个 sizeof(long int),这个你不用管,是不?248,再看这个,咱存的是 0102 是吧?同学们,让他这个 un2.c[0]  un2.c[1]  0打印的是哪个值啊?看见了没? 2吧? 是不是这个? 1 呢?打的是哪个? 1吧 是这个吧?,很显然这个你说是一个高端字节序还是低端字节序?是不是低端字节序?那么低位地址存放低位数据,高位地址存放高位数据,很显然是一个低端字节序。

那么再看一下这个 U2 点 s 对吗? s代表 258,这个值是不是258?是吧?同学们?这个是 2 吧?这个是 2 的多少次方啊?  2 的 4 次方, 2 的 8 次方,这应该 2- 8 次方吧? 2. 8 次方加 2 是多少?是不是256?这个如果说你不会算怎么办?把计算器打开,计算器可以算,那么你在用这个计算器的时候,你应该用哪个?程序员 然后你看见这 16 进制,点这个是不是 16进制,然后你是不是 102 相当于是吧?102,看看十进制是不是258,这是八进制,这是二进制,是不是这你都会用好,那么下面那个对吗?下面这个和那个是不是类似啊?同学们 01020304,那么 1234 是分别是 4321 是不是同学们?反过来吗?这个是低端的吗?是不?这个 4321 最后这个值算出来是多少?是这个数1020304,这数对不对?拿出来,是不是还是 16 进制?

看没?同学们,实际是16909160,没问题吧?,这个程序我也到时候发给大家。一是你要看明白它,一定要看清楚原理,为什么?在这儿咱们想一下,有没有想过这问题,为什么我打印出来这个值,这个是这么显示或者那样显示呢?为什么呀?因为你这个是不是共用体啊?同学们,共用体也就是这两个变量,是不是应该是占用的是同一块内存啊?如果是,一开始你对它进行了赋值,然后你再用它去显示,这可以显示的。但如果你一开始用它赋值了,后来又用它又进行复制,是不是会把它的值覆盖啊?是的,这清楚吗?同学们,这个务必清楚这些,这个一定要明白。

这个字节序列问题基本的概念。我跟你说了,总结一句话给你, 4 字节序问题。第一个,什么叫大端字节序,第二叫小端字节序 是吧?先看一下这个小端是不是也叫什么呀?什么也叫低端字节序吧?低端字节序序什么意思?是什么呀?低地址存放低位数据吧?然后高地址存放高位数据,是吧?同学们,好,那么这个大端呢 ?也叫什么呀?也叫什么高端字节序,再给你起个名,或者什么呀?网络字节序,明白了吗?同学们,也叫网络字节序,是吧?那什么呀?是高端地址存放什么?存放低位数据,然后低端地址存放高位数据,意思明白就可以了,那个程序你得看明白了这个,这是这个字节序的问题。

 那么讲完这个字节序之后,我给大家说一下这个,在我们的网络传输当中一定要注意,网络传输当中用的是高端字节序,也叫网络字节序,那么这个在什么情况下才用得着这个?大端或小端,或者叫网络字节序和小端字节序呢?一定要注意,如果是一个字符串的话,用转吗?你的数据类型里面,大家注意,数据类型里面只要是没有超过一个字节的,char 是不是没有超过一个字节?不用 int用吗?short用吗?结构体用吗?你的结构体里面如果是有什么 Int short,只要超过一个字节了,是不是要用?当然结构体本身是不是也会超过一个字节,他也会用,一般情况下,我们弄的时候会把这个结构体里面的每一个什么呀?数据类型,比如说你这个是int类型,转一下,short类型转一下,chart不用转,咱们后边马上用到,这是应用场合,这个不说了。

好,咱们看一下这个相关的函数有哪些?这相关的函数其实也非常简单,你看他的名字看出来了。好,咱们看一下这个名字里面有h,是不是有 n 是不是有,是不是也有l?同学们是不是有l?那么这个记都是怎么记啊?看下我给大家说一下这接口怎么记?这个里面? h 表主机的意思, host 是不是主机的意思啊?同学, n 表示 network 网络, s 表示short, l 表示long。你这 4 个搞清楚之后,这个函数一眼就看出来了。

看第一个 htonl什么意思? h 主机 to 是到哪边的意思,到哪了?到网络字节序的长整形是不是?这个是不是往往是转这个long类型的时候可以啊? long it 是吧?同学,看第二个htons是反是?正好是跟那个一样,但是数据类型是不变成 short 了是吧?主机自序转换网络字节序短整形 是不这样的?你看它这它的参数是不是 short的?这个是long类型的吧?,你看,这uint32,这个是无符号 32位是吧?你们这个是不是无符号 16 位整数啊?是吧?看这个ntohl网络什么呀?由网络的数据转换成什么呀?主机字节序的长整形吧?这个ntohs 是网络字节序转化为怎么样?主机字节序短整形

这个你只要把 4 个字母代表什么意思,是不是就看出来了? to 是不是到哪意思是吧?同学们, from 是从哪? to 是到哪是吧?好,这个,那么这个你先知道,有这么回事,咱们这个写代码的时候再给你用。好,咱们再讲另外两个用的比较多的函数, i p 地址转化函数,看下这个函数叫 inet_pton,大家注意这个 p 指的是点分十进制字符串形式的 i p 地址。 to 是转化到什么?转化到什么呢?网络字节序。

 那么这个整形是几个字节?同学们,是不是 4 个字节?同学们,大家注意 ip 地址是 4 个字节的。什么呀?端口是 2 个字节的, ip 地址是不是 4 个字节? 这个函数的意思是将字符串形式的点分十进制的 ip 地址转化为大端模式。大端模式是不是网络字节序啊?这种IP?那么整形用 4 字也来表示这个,咱们在写代码的时候给你验证验证,是不是这样的好看看他的参数,第一个参数,a f 这个 af 用的时候用AF_INET这什么意思?是不是协议图啊?

同学们,第一个,是不是AF_INET,那么看这

其实就是 i p v 4 和 i p v 6 的意思,是吧?同学们,目前来说我们都用 i p v 4,所以这个我们填AF_INET明白了吧?填AF_INET第二个,那么你说这个 const char *是一个什么参数了?传入参数,传输参数了,看也看得出来,为什么呀?因为你家 const 了不能修改,所以只能传入。后面这个是猜一下,void *肯定传出,是不是肯定传出,这个,那也就是说你最后转换完那个什么由字符串形式的 ip 地址转化为 4 字节的网络字节序的 ip 地址,就给你保存到哪个里面是不dst里面,兄弟们保存在这个里面。

好,这几个我举例举了一个例子,比如说我用这个 ,这个是 inet_pton 第一参数没问题吧,第二我要把这个 127.0.0.1转化为什么呀? 4 字节的网络字节序的ip地址,怎么转化的呢?我们手工可以计算,手工也可以算,要比如说这个给你说举了一个,这是它的用法,这是怎么用?最后这个 127.0.0.1是不是保存到这个地址里面来了serv.sin_addr.s_addr,是吧?当然这个地址什么什么类型的?同学们是不是整型了? 4 字节整型值,那比如说你手工也可以 192.168.232.145,那么这转化能怎么转?你先把这个点分十进制这四个数字是不是先给分开,是不?192.168.232.145?嗯,先分头计算出来,那么把它转化成 16 进制,那这 192转化成十六进制是C0,是不是C0?我给研究一下,这是十进制时间制是吧? 19是不是C0?嗯,是吧?再来一个 168 是不是 A8 啊?232? 232 多少是不是 e 8 也没问题,还有145, 145 是不是91?现在是不是?我相当于挨个的转换过来了?转换过来以后,然后你再按照网络字节序进行存放就可以了。

那么你看一下,按照正常情况下,我们认为192.168.232.145,你说谁在低端呢?谁在高端呢?是不是右边在低端,左边在高端,是这样的吗?所以存放的是 145 朝前存,是不是这个 91 是放最前面了?嗯,然后是不是倒过来就行了?0x91E8A8C0是不是这种情况?这个就是最后,实际上这个数保存那个值能理解吗?这个能不能自个设?同学们可以试的,到时候你调这个函数试一下不就知道了吗?是不是?好,再看另外一个函数,刚才那个是点分十进制的转换成了整型的 4 字节整型值。

 好,接下来反过来行不行?能不能把一个 4 字节整形值转换成一个点分十进制的 ip 地址呢?是可以的,叫哪个函数呢?叫inet_ntop 是不是正好反过来了?看没,是不是前面都一样,朋友们,是吧,所以这个还是记的时候其实有技巧的。 p 什么意思?是 IP 说对吧? IP 是不是点分十进制字符串形式的 ip 地址,是吧对吧?n呢是不是 4 字节的大端字节序的网络地址是不是这样的?好,所以看看怎么用。第一个 a f   很显然和那个是不是一样的?是吧,是不是也是 AF_INET 表示我们用的是 i p v 4吧? 好看第二个 s r c 很显然这个一定是一个什么参数?是不是输入参数了?输入参数,也就是说你想把哪个转化成什么呀?这种字符串形式的 ip 地址,那么这个就是什么呀?同学们很想这个应该填一个 4 字节的整型值,是不是这样的?然后转换成什么样?转换成点分十进制的字符串形成的 ip 地址。

所以最后是不是这个地 ip 地址是不保存到这个里面来了 dst?那么保存成这种这个点分 十进制的,是不是方便我们看啊?这种整型的,你方便看吗?是不是不太方便的?然后后边一个长度,这个长度指的谁长度,谁的长度,是他的长度src还是他的长度dst?记住是这个长度dst,明白了吗?是他的长度。

所以你在存放的时候,你说给这个 IP 值分配内存的时候,这个数组的话至少长多少啊?多少,是不是三四乘以三 加 3 个点是不是15?给他分 16 是不是够了?知道什么意思吗?你分的多了没用,

为什么你像这种话,你看没 192.168.232.145 是不是占满了,就最大是25吧?每一个是吧?所以三四乘以 12 加 3 个点是不是就15,再加 1- 0 就够了?所以一般情况下你弄的时候弄 16 就够了,也没有必要弄什么1024,什么256,是不是浪费没用,没有那个意义?好,这个函数成功返回,这是指向dst的指针,知道什么意思吗?这个指针是不是指向他呀?知道什么意思吗?大家想一下这种,这如果这样做的目的是什么呀?这个指针指向这个,这样做的目的什么呀?有什么好处?那么你写代码的时候是不是可以连着写?明白了吗?可以连着,写好失败返回呢?并设置errorno,


这儿人家你举个例子,比如说咱们刚才上面那个,比如说这个 010aa8C 0,这个是不是一个 4 字节整型值?但是前面是不应该加 0x  表示16进制吧?是不是先转化成点分 十进制,让你转化成点分十进制的格式,那么 01 是不是1呀?所以你会你先转化 0a 是不是转换成10进制?a嘛 a是不是10啊?然后 A8 转化成 16 进制式168?这个东西给你算过了,我看是不是这个是吧? 168  
C0是192,这个是不是在上面刚刚给你算过?那么然后你转换回来以后是不是你要倒过来?为什么呀?因为这个是个什么呀?这个是高端字节序是吧?好,倒过来,怎么倒过来?是不是这个值是不是在最左边? 192.168.10.1 是不是算出来了?能理解什么意思?也就是最后你转发完以后,是不是这个 C0 应该是跑到最左边来,是不是这个?然后这个是A8,是168,
10,是不是这个啊?应该这样算,这个能看懂吗?同学,能看懂吗?你一定要搞,心里一定要明白什么叫高端字节序,什么叫低端字节序。

你这个不明白的话,你这个东西看不懂,知道什么意思?这个数字里面,对这个数字里面两个才表示一个字节,看清楚是不是这样的?为什么?因为是 16 进制, 16 进制好,这是这一个。

那么关于这个高端字节序和低端字节序以及这两个函数,我先给你介绍到这个,现在你不会也没有关系,因为后面咱们会一直在用它,是吧?一遍不行两遍,两遍不行三遍,我不相信你,你弄他个十遍八遍你还记不住,是不是?这个没有关系,别着急。

现在给大家讲一个非常重要的结构体,也是在咱们这个 API 编程里面经常用到的一个结构体,叫哪个?叫struct sockaddr,这个就是存放ip地址的那个结构体,是吧?咱们要进行通信的话,是不是要知道对方的ip端口是不是所以有这么一个结构体专门存放这个的?咱们看一下这个结构体,那么咱们这个接口里面用的结构体是 struck sockaddr  这个结构体,那么与这个结构体对应的还有一个结构体,是这个 struck  sockaddr_in,那我问一大家这个结构体里面,在这个结构体里面,那么前 16 位地址类型是不是就是两个字节的一个整型值?兄弟们,两个字节的一个整型值,这个用什么呢?这个非常的固定,就是用 AF_INET,关于这个我可以给你打开一个,man 7 socket
,这是不是有socket啊?我们看下面有没有这个结构体,如果没有的话咱们就搜一个别的。man bind

 这么一个函数,是不是有这么一个结构体啊?这个叫sa_family,sa_family,这个用法非常的固定,用哪呢?这个这没有,就用 AF_INET,咱们看man 7 ip,你看他是不是用法给你写好了,看没?不会有关系吗?是不是直接照抄就可以了?看后面是不是结构体啊?同学们,这个结构体,

 这是另外的一个结构体。

 这个 结构体sockaddr_in和这个结构体sockaddr什么关系?大家注意在早期的时候用的是这个 struck sockaddr这个结构体,但是这个结构体有一个弊端。什么弊端?我们在进行赋值的时候往往不太方便,你看一下这个方便吗?这是,这个倒好说,都是AF_INET吧?但是下面那个 14 个字节的这个如果让你赋什么 IP 端口啊,你赋值方便吗?方便吗?同学们,不方便,这个并不方便。当然你如果说能够掌握内存对齐也行,知道什么是内存内齐吧?那么这 14 个字节里面,实际上它是这么来分的,其中有 2 个字节来存放,端口号有 4 个字节能够存放什么呀? ip 地址,剩下还有 8 个字也是空闲的,空闲就不使用,那么如果你能够掌握内存内齐呢,你这样赋值也没有关系,但实际上我们有更好的方法用这个结构体叫 struct sockaddr_in,那么这个结构体里面就给我们把端口号 IP地址给你弄好了,你直接赋值就可以了。

然后在用的时候我们再进行转化,看一下,man 2 bind 在这个函数里面,比如bind这个函数,比如bind函数,

那么这个函数里面是不是有个结构体叫 cost struct sockaddr啊?,兄弟们,这个是不是一个指针?那么也就是说我们正常情况下,我们看到这种函数用的话,是不是先定义一个这个类型的结构体啊?然后在赋好值之后把地址传过来就可以,但是你看一下这个,你看这个结构体你赋值方便吗? 14 个字节,你知道赋什么吗?你知道怎么填充吗?是比较烦,比较麻烦一些,那么很显然这样的话就不太方便。

 

 那为此后来又经过改进,大家注意,又经过改进,又提出了一个这样的结构体,这个结构体和这个结构体大小一模一样,知道什么意思?嗯,大小一模一样,那么这个给你分开了什么端口和什么 ip 地址怎么填充的,给你填好了,你填的时候只要进行结构体赋值就可以了,是不是?是不是给这个结体的这个成员赋值就可以了?给端口和 ip 的赋值就可以了。

那么咱们看一下这个结构体啊,这儿有一个这样的一个这样的结构体叫struct sockaddr_in,那这个结构体里面有三个成员是吧?兄弟们,好看。第一个叫 sa_family_t是吧?那么叫  sa_family,这个addres family  :    AF_INET 是不是告诉你了是不是?我们是不是用的是 i p v 4,你直接用就可以了。看第二个什么    sin_port什么意思?

pot in network best order。

是不是告诉你了?是不是网络字节序的端口号?你说这个端口你需要转吗?同学们 我举个例子,如果你端口号用的是 9898 这个端口,那么你是不是得需要转化成网络字节序啊?对,我是不是跟你说过了,那么什么情况下不需要转呢?它的数据类型长度是 1 的,不需要转,只要是高于 1 了就需要转,那么sort是不是高于 1 是不同学们?其实这个端口就是sort类型的,long是不是也高于1啊?是吧。那么char

如果说举个例子,比如说我char a100 这个需要转换吗?大家注意不需要说的是这个最小的数据类型,最小数据是不是char c 啊? 
 

char就是一个,就是其实就是char类型的,你不要搞错了,char是不需要转的,就是说你发字符串是不需要转,但是你要发什么,里面有什么什么short类型的,int类型你就需要转。切记这一点,切记一点,到时候咱们写代码的时候会有所体现。那后面还有一个什么什么 struct in_address  sin_addr  是 Internet  address 是不是 ip地址啊?那么这个是不是也是一个结构体啊?看没?嗯,好,这 个结构体在这给你定义了,他弄得比较怪,他这就一个成员在这也给他弄了个结构体。

 如果我设计的话,如果说我设计的话就可以直接把这个放这,但是这样设计有一个好处,什么好处?扩展方面,明白了吗?如果你下边比如说你又多那个东西,你是不是在这直接填就可以了 sockaddr_in?是不是原有的东西不用修改啊?,是吧?记住这一点。好,那么他怎么设,他怎么用,怎么设计,你怎么用就可以了,这个你不用管,那么你用的时候怎么用?同学,是不是第一个角体,比如说叫这个结构体叫addr.sin_addr.s_addr是不是这么用?好,这个这结构体,那这结构体我就给你说到这,那后面这两个咱们后面再说。

 这个是本地与socket通讯使用的什么呀?结构体,这个先不用管它。好,这是结构体,这都有,是吧?都有。那下面我就给大家把这个socket 的 API 函数给你介绍一下。先介绍函数,那么介绍函数以后,咱们给你介绍一下服务端的开发流程,然后再给你介绍一下客户端的开发流程。然后呢咱们再写一些代码测试一下就知道了。好吧,今天晚上一个作业就是什么呀?你自己编写一个 server 客户端,一个 server 服务端,一个客户端,然后通信一下。好,这个这个服务端和客户端之间通信的这个协议你自己定,可以了,兄弟们,你自己定啊,你是发一个结构体也好,你发一个串,然后再加一个包图也好,等等你自己随便定,记住了吗?我们看一下这个,把相关的 socket 函数给你介绍一下。

 

 那么第一个是这个socket,上午的时候是不是咱也说过一次了,这个函数是不是相当于叫创建一个socket?创建一个socket 得到一个什么呀?得到一个文件描述吧?那这个文件描述符的话,它内核是不是对应两个缓存区?嗯,哪两个缓存区,发送缓存区和接收缓存区是不是?好,那么这个结构体咱们看这个函数咱们看一下。那么第一个参数叫domain,这是协议版本的意思,很显然我们都知道现在我们是不是经常用的,一个是 i p v 4啊?所以在这你填AF_INET就可以了。这个写法很固定,就这么写就可以了。

 好,第二个 type 是什么意思?是协议类型,那么这个经常用到的有两个,一个叫 soft stream, sock stream,一个叫 sock dgram。看看这个 sock stream是流式的,那么使用的协议是 TCP 协议,是不是就是他建链接的时候是面向链接安全可靠的字节流传输啊?对,是吧?那么还有一个是 sock dgram 是报式的,是不是数据报协议叫用的协议是 UDP 协议,用的是不安全不可靠,无链接的数据报传输。是这样的,那么还有一个是叫第三个是protocal,这通常我们传 0 就可以了,表示使用的类型是默认协议。其实这个协议不只是有两种,还有很多,只不过是我们用的非常少。好,这个函数成功,很显然,是不是返回一个大于 0 的文件描述了?嗯,是吧?失败。返回- 1 并设置errno

 那想一下,我们是不是就可以通过使用 perror 函数把这个错也给你打出来啊?这个咱们前面用过好多次了吗?用过好多次了,线程里面是不是我们不要打印这个?errno这个值啊?是不是?这个咱们说过了。好,当你调用socket函数以后,是不是我们得到了一个文件描述符了?这个文件描述符对应的两个缓冲区在内核当中就给你建好了,是不是就你建好了?我再问大家,你能直接操作内核吗?不能,是吧?那么接下来后续的一系列操作,你都是在操作文件描述分,那么是文件描述符的话,咱们前面讲文件描述符,跟你说过了,文件描述能够操作函数有什么?read,write, close 在这也同样适用。

 好这个函数函数讲完了,那么这个红色标记的简单给大家提一下。简单给你提一下,就是说你创建了socket的以后,我们得到了一个文件描述吧?这个文件描述分除了对应的这个读写缓存器以外,其实还有什么呀?两个队列,这个队列分为什么意思叫请求链接队列和已链接队列,这两个队列往往是在什么情况下才会有呢?大家注意一下,你的这个文件描述分是监听文件描述符通信了没有?通信用不着它。

这个后面咱们讲的acresies函数,跟你说一下,这个你了解一下有两个队列什么意思?就是说我给大家举个例子,当然现在举不太合适,后面再说,后面再说。第二函数bind,咱们都知道这个服务端是不是对外提供服务,它需要对外提供端口,是不是一个固定端口?同学们,大家注意,每一个服务都为都对外提供服务的时候有一个固定端口,那么这个团口一般情况下是不允许随便动的,一旦动的话是不是客户端就连不上他了?你要动的话你得对外是不是说明一下,看见有哪些?嗯,第一个函数socketfd 还显示这个的话,是不是应该是咱们前面创建socket返回来的文件描述符啊?是吧?就放这就可以了。

第二个是struct sockaddr *addr 这个是不是指针啊同学们?嗯,这个,大家注意这个里面存放的就是什么呀? IP 端口这些信息后面。后面是addrlen是不这个addr的长度,这个长度好,这么这个结构体是不是咱们刚刚说过了,这个结构体是不是有 3 个重要的成员?一个叫family,是不是这个天 AF_INET 就可以了?那么这个还有一个端口的话我给大家说过了,端口的话是不是一般是这个 16 个 位的也就两个字节的长度吧?两个字节的长度超过了 1干什么呀?是不是要进行转换?要由主机自解序转回网络自己去短整型吧?是不是?短整形所以用的函数是哪个函数啊?叫htons 能理解吧?那么转换为以后呢 你这个8888是不是就转换了高端字节序了?

但是这种的话不转型吧?8888是不是不转型吧?,是不是?那你正好对称了,是不是?你要别的不行吧?不管这个情况是8888,还是9999 你该转还是转,好吧?好,后面这个,这个是不是IP INADDR_ANY ?同学们, IP 在这跟你说一个宏,这个宏叫INADDR_ANY 。

这什么意思?表示使用本机任意可用IP。我问大家,这个好多服务器是不是它在 ip 地址不止一个呀?,你们可能没接触服务器,服务器上可以插好多网卡,有的至少 2 个,有 3 个, 4 个的知道什么意思?他这 4 个网卡,那么比如说你对外提供服务的时候,你这 4 个网卡都可以接入数据,是不是也都可以发送数据?你用这个INADDR_ANY就指的是用任意可用IP。

明白了,当然你对外提供服务的时候是不要告诉人家啊?这四个,你用哪个都行,是吧?他这个,那如果你有一个固定IP,你在这写固定 IP 就行了。127.0.0.1指的是本机是吧? 指的是本机的意思,那么如果不是本期的话你写成。当然你这个地址是不是肯定是本机地址?这127.0.0.1指的什么意思?这本地回环地址,这个地址往往是测试来用,对外提供服务,用这个行吗?不行,对外提供服务不行,你自己的主机自己测行清楚了吗?这叫本地回环地址。

好,那么用的时候咱们是不是用的是inet_pton呐?兄弟们,inet_pton呐什么意思?是不是将点分 10进制?这种地址转换什么呀?转化为网络字节序的高端模式是吧? 4 字节整形保存到哪里面去了?是不是这个里面&serv.sin_addr.s_addr?那我们这个主机的ip地址是不是这个?这个结构体下面是不是还有一个小结构体?是不是这里面有成员?叫 s_addr。

你现在记不住,你可以翻笔记或查文档都行清了吗?这个成功返回0,失败返回-1,并设置errno  第三个参数, listen 刚才的bind,他做的事情什么?同学们, bind是将 IP 端口和文件描述进行了绑定,是不是因为你后续在操作的时候呢,一直是在操作这个文件描述符,知道什么意思吗?操作就是文件描述,read,write, close 等等,这些都是和文件描述分有关系的。

好,看,后面这个listen 是将套接字由主动变为被动。咱们上午是不是说过这个?正常情况下,如果你是一个客户端的话,你是不是要应该是主动连接服务端?服务端知道你什么时候连他吗?不知道,他是被动的,你是主动的。是不是这样的?就像咱们上网一样,是不是也这样的?我敲百度一回车就连上了。好,这是listen由主动变为被动。

 那么这个 f d 很显然是什么呀?这个 f d 是哪个? f d?是,就是创建socket返回的文件描述符吧?这还有一个 backlog 这个参数,那么讲义上或者这个帮助手上说的什么呀?同时连接的最大个数,其实相关的这个做过相关测试,说这个参数基本上没什么,没什么用了,但是你填的时候你不能填0,知道什么意思?这个是最大是128,最大是128,你填一个大于0的数,这什么意思?我举个例子,比如说这个原意是这样的,这个backlog 这样的,假如说我们这个服务端我最大,就是比如说这个参数你填10,它的原因是这样的,一次性可以连接有 10 个客户端,那么再来了以后怎么办?需要等待,知道什么意思?也就是这 10 个已经进入到连接队列当中去了,这个连接队列一满,那么接下来再有连接到来的话,它只能放在哪了?等待链接队列当中。

那么链接成功的放哪?放在已链接队列当中?我是不是刚前面跟你说了 有两个队列啊?是哪?我看说这个同学们,一个是请求链接队列,这个是不是相当于没有建立链接?这个是已经建立好链接了清楚了吗?这个你了解一下就可以了,因为这个参数已经没有多大意义了,没多大意义了,但是你填的时候你不要填0清楚了吗?你填 5  10  128 都行,都可以。

后面看一下accept,那么这个 accept 什么意思?是获得一个链接,那么好获得链接从哪获得的?大家注意是从以链接队列当中获得一个链接,拿出一链接来,言外之意,调用accept 之前有可能链接已经建立了,能不能这样说?这个咱们可以试,到底我没有调用的这个链接,是不是已经建立了?这个咱们是可以写代码测试的。好,那么你认为我们就这样认为就可以了?就说我调用accept以后呢,我就能够拿到一个链接,那我拿到链接之后我就可以通信了,就完了

 服务端 大家注意注意服务端一共有两种文件描述符,我刚才说的是第二种。第一种是哪个?前面是不是咱们已经 调用shocket?是不是已经返回一个文件描述符了?是不是那个文件描述符?是不是我们调listen是不是已经设置为被动监听状态啊?那个叫监听文件描述符,记住啊,服务端有两种类型的文件描述,一种是监听文件描述,一种是通信文件描述。当我们调用accept之后返回一个文件描述,大家注意这个文件描述是用来通信的。

什么叫通讯啊?是不是就收发数据的?那个文件描述符指什么呀?只是接收链接的,有客户端去连,他就接收链接,那最后的这链接,最后我们又得到一个新的链接,也就是调用assept,这个返回的值用于和客户端进行通信。啊,你先大致听一遍,咱们写代码的时候还跟你说的好,第一个很显然是不是就是调用socket返回的文件描述了。第二个参数,大家看一下这写 const了吗?写没写 const的没有吧?大家注意这一个是一个什么呀?传出参数,传出参数是没写,没写 const传出,这什么意思?我服务端怎么知道谁连我了?怎么知道的?保存在这个结构体里面了,谁连的是吧?这个结构体里面是不是有两个啊?朋友们,一个是 IP 的端口啊?,谁连的就记录在这个结构体里面,清楚了吗?看第三个参数,是特别重要的一个参数,很多人在这上面,这个踩雷了。

这个参数是一个传入参数,传入指的是什么?传入指的是告诉accept函数这个结构体它占用多少内存传出的意思什么?这个函数调完以后,这一块内存是不是被填充了?被填充了多少啊?他又通过这个返回值告诉你了,所以这个参数是一个传入传出参数。切记,这个是你需要注意的地方,这函数成功返回一个新的文件描述符,用于和客户端通信,失败返回- 1 并设置errno,能理解吗?这个 accept的是一个阻塞函数,什么意思?那么假如说没有客户端链接到来的话,这个accept是会阻塞,直到由客户端去联系他,他就立刻返回,然后返回一个文件描述,这个文件描述就是用于通信的 这意思。

但是实际上这个函数内核在调这个函数的时候,是将请求队列中的链接拿到以链队列,以链接队列,是不是相对之链接建好了?嗯,是不是这样的已经建好了?好了,看看这个函数叫connect, connect 这个函数想一下谁用的?我问大家,是客户端先主动联系服务端还是服务端主联系客户端的,客户端联系服务端,这个函数是在客户端领域去调用的,清楚了吗?第一个参数 f d 怎么来的?这个大家注意这个 f d 怎么来的?文件描述就是调用socket来的,没有别的,注意。

 还有一类是调用assept返回的吧,但是自己客户端来说它只有一类文件描述符,就什么呀?就是用于通信的,因为它不监听,知道什么意思?客户端并不监听,这个文件描述符就是你调用操作的返回的一个文件描述符。好第二个参数,猜一下什么意思?你是不是连接对方?你是不是连接服务器?那么你连接服务器是不是你得知道 iP端口就放在这个里面,你看它是不是有一个const?什么意思?这个是一个传输参数,看看第三个参数,第三个是一个addrlen,这个的长度是不是就指的它的长度?是吧?你们一般你说这长度我们怎么填?是不?sizeof(addr)他就可以了是吧?sizeof(addr)他就可以了。

好,那么这些函数介绍完以后,接下来就开始是不是通信了?那么你客户端,你调用 connect 已经和服务端建好链接了,接下来你是不是出客户端就可以发送数据了?发送数据,接收数据,用哪个函数呢?就用 read 和write。清楚了吗,就这两个。这几个,这两个字大家是不是当时说过了?在这不啰嗦了。

 

 好,你没见过的是这两个,一个叫 recv  一个叫send,他们的这个参数基本上是一样的,就是最后一个多了一个参数,这个值我们一般传 0 就可以了 flags =0。那么你用的时候,你用这 4 个当中哪个都行。但是我建议你用的时候你不要交叉着用,你不要用read。然后你用个什么send,不要用write,你要用的recv,知道什么意思吗?这俩是一对是不是 read write?这俩是不是也是一对了 recv  send? 但是交叉行不行?也行,我觉得可读性差,知道什么意思吗?用的时候你不要交叉着用,就不要交叉着用。

好这个,那么基本上咱们这个函数给介绍完了,接下来我给你讲一下这个通信的流程,把这流程讲完之后,咱们给你写一个,用文字描述一下,最后咱们写个代码给你测试一下就知道了。你先把这几个函数先大体听一遍,有同学可能听了一遍,就老师我一点没听明白,是不是?别着急别着急,一会让你不这个不模糊,可以让你逐渐清晰起来。

好,咱们这,咱们起码得把这一张蓝图绘到底。这句话在哪听说过?哈哈,看来大家不太关注这个城市当中那个大蓝图,那个有的是这个标签写的,一张蓝图绘到底,是吧是吧?撸起袖子加油干,还有别的吗?是吧?新民是不是说过很多名言,这个鞋子合适不合适,只有脚穿上才知道是不是?好,咱们函数先给你介绍一遍,然后咱们接下来给他把这流。好,接下来我给大家把这个流程,整个流程给你捋一遍。

看到图,同学们看看这个图,你只要把这个图看明白了,我想的话,写个程序出来应该是不算什么难事。先看客户端,先看客户端第一步,首先是不是我们要调用 socket 创建一个什么呀?是不是先得到一个文件描述符啊?嗯,要创建socket,那么创建 socket 以后,那么是不是在内核当中又有了两个缓冲区?嗯,哪两缓区?发送缓冲区和接收缓冲区。那么我们操作这两个缓冲区是不是操作那个文件描述符就可以了? read 和write 是不是就可以了?好,也就是说你得知道什么? read 和write 在这写的缓冲区,它不是一个 read 读的是不是读缓冲区啊?嗯,write 是不是写的是写缓冲区啊?嗯,好。

 第二个函数 connect 创建socket以后是不是得到了一个文件描述符了?接下来第二步connect 连接谁?是不是连接服务端的?兄弟们?当时连接过程有一个3次握手过程,这个你不用管,这现在先不用管,这个是建立连接  3次握手,好,那么这个可connect 连接成功之后,客户端和服务端就建立好链接了,链接建好之后,接下来该干什么了?是不是你就可以发收数据了? send  recv,兄弟们, send 或者是你叫 write和 read 都行, write read,这是写和读吧,或者是 send recv 都行,清楚吗?好, send recv。

那么实际上大家注意,实际上 send 和 recv这一块是不是应该是一个循环的啊?这一块?喂,懂了,当然你是也有可能说你发一次立刻结束了,是不是也有可能?是吧,同学们,这一块是不是可以是循环的?我收,我发过一个,那么服务端收的时候之后回一个,我再给他发一个,是不是来回发,知道什么意思吗?好,最后你不用了,要记得调用 close 关闭吧。

这个和咱们前面讲这个 open 一个文件的时候是不是一样?嗯, open 打开一个文件,然后不用了, close 是不是这样的?这是客户端编写,是不是相对简单的?相对简单,咱们看一下服务端好,服务端第一步它也是调用 socket 创建套接字,那么这个函数返回一个什么值?是不是文件描述了?是吧?同学们,返回文件描述是不是也可以得到两个缓冲区啊?得到两个缓冲区,当然这一步,这一步按理说也会有两个队列,为什么?因为你这个文件描述是不是用于监听的好。

 第二步,调用bind函数进行绑定,那么谁和谁绑定?同学们 IP 端口和文件描述时进行绑定,因为你后续是不是一直在操作文件描述啊?你并没有显示的去操作 IP 地址,搞清楚是不是这样的好。第三步, listen 是干什么的?是不是监听调用这个函数以后,你的进程,你的这个程序就处于监听状态了?这个咱们可以用命令来看。那么这个 list 是不是将我们这个文件描述由主动变为被动,是不是因为服务端一定是被动的,是吧?对,没好。接下来继续,到这以后,调用 accept函数, accept是一个阻塞函数吧?如果没有客户端链接到来,这个accept的一直阻塞,大家注意一直阻塞,但是在accept之前 有可能连接已经建立了,

 我举个例子,比如说在accept之前,你加个 sleep 100,然后你客户端直接连他,其实 sleep 100 以前那个链接已经有了,只不过是你还没调用 accept,把这个链接拿出来,是不是这样的?好,那个accept拿出一个新的链接来,那么这个新的链接干什么的?干什么的?用于和客户端进行通信的,大家注意用于和客户端进行通信的。

那么到这个accept 这以后,我们是不是得到了两类文件描述符了?一类是不是这个函数返回的?嗯,对,这个叫什么文件描述符啊?这个叫监听文件描述符,搞清楚,概念,搞清楚,这个叫监听文件描述 socket(),这个通信叫通信文件描述 accept()。那么这个监听文件描述它的作用是,就是监听客户端有没有链接到来,有链接到来是不是可以调用 accept 可以接收一个新链接啊?那么这个accept 的函数它作用是拿出一个新链接来,这个新链接是用于和客户端进行通信的,搞清楚了吗?好,那么接下来是不是得到一个通信的文件描述符以后,是不是接来就可以 receive send 就可以收发数据了?后续和这边是不一样了,最后不用了,要记得close,那么整体上就是这么一个流程,就是这么一个流程,好,朋友们就是这么一个流程。

那下面我给大家把这个流程给你说一下,给你写一下,好,看一下,先来个服务端,服务端开发流程第一步先干什么?

第一步,兄弟们,嗯,是不是创建socket?是不是调用socket()函数?是不是也函数了?那我得到了一个什么问题?返回一个文件描述符,是吧? 这个文艺描述符是干什么的?我给你写一下,该文件描述服务用于什么?用于监听客户端连接。兄弟们,这个知道,这是一类的。兄弟们,这是一类文件描述符。

第二个,干什么?干什么?那么你现在已经得到一个文件描述符了,接下来第二步是要绑定。嗯,就是绑定,将谁和谁绑定。将 l f d。和什么呀?比如说我们这个文件描述叫 l f d,可以吗?好,将 l f d,也就是将这个监听文件描述符和谁绑定 IP port 进行绑定,调用bind函数,这个没什么值得说的地方。

第三步,干什么?将什么呀? l f d 由什么变为什么呀?由主动由变为什么变为被动变为被动,其实就被动监听,调哪个函数? listen

第四步,第四步,是不是接下来我现在这个,我现在我这个程序是不是已经处于监听状态了?那接下来是不是要监听有没有客户端的连接到来啊?如果有客户端连接到来的话,调用哪个函数把这个连接拿出来呀?是不是 accept 接收一个新的链接?到哪儿?是不是 accept?返回一个什么值? 得到。

一个通信文件描述符。我这么给你说?得了一个文件描述符,是吧?好,这个文件描述符是干什么的?该文件描述符是用于和客户端进行通信的。这个是不是我跟大家说两类啊?同学们,一个是监听文件描述符,一个是通信文件描述符。

第5步干什么呀?同学们,第五步接下来是不是你?当然你可以在循环里面,也可以不在循环里面。肯定是什么呀?什么收发数据了?收发数据了,一般情况下我们这个服务端是先接收再发送,那么我问大家能不能先发送再接收?也行,你比如你客户端链建好了,你直接给他发也行,前提是链接一定先建好清楚了吗?

但正常情况下,我们是客户端先给谁发服务端发,服务端收到之后是不是得回?是接收什么呀?这边一般是在一个while循环里面了,不在一个while循环里面行不行?你就发一个就结束嘛,也行,是不是也行?这个看需求,咱们先在一个循环里面。好,接下来是干什么?是不是 read 数据? 接收数据, read 或者 recv 接收, 然后发送数据?那么好问大家,如果说客户端只是连接上服务端了,但是他发不发数据的话,服务端会怎么样?会阻塞?大家注意,咱们前面讲这个管道的时候给你讲过吗?管道是不是这个阻塞的?管道读端和写端是不都阻塞的?如果没有数据的话,没有数据可读,它是不是一直阻塞啊?我们这个也一样的。

socket文件描述分还记得吗?我们讲这个文件,这个read函数什么?是阻塞和非阻塞的时候跟你说过了,读普通文件是什么的?非阻塞 读管道, socket 这些是什么呀?还有什么终端设备这些都是阻塞的,清楚吗?好,发送数据是send?是,当然是write, write和什么呀?或者send 是不是那么好?这个完事以后最后要记得关闭文件描述,关闭几个,同学们说一下,一个啊,这个lfd是不是要关,那么这个一个新的文件描述符,比如这个叫什么呀?cfd这个是不是也得关啊? 什么呀?cfd 是不是两个?是不是两个?关掉之后就行了,不用管了,关掉就行了,没那么复杂,这两个文件描述符都调用 close关闭就可以了,对吧?那么这个是服务端的开发流程,能理解吗?同学们,这个理解之后咱就写个代码给你验证一下是不是这样的。

好,那咱们就写一个,这个是server.c,这什么意思?这是怎么样  服务端程序?好,那么先加一些头文件,加哪些?stdio.h,stdlib.h,string.h  types.h ,可能在这咱们用不着这里面,但是你这个加多了是不没事了?是不是少了会报错呀?同学们, 还有哪个?大家注意,还有两个,我在这给你写上,netinet.h

这个怎么看?这个可以这么查。怎么查?man 7 ip 这些头文件,一个叫这个头文件,你得有,你得有 可能是我记错了,不叫这个名,这里面是一个,还有一个叫什么来着?还有一个叫这个啊,有两个就够了,我记得是 arpa/inet.h 。是这个吗?这两个有,这两就够了,不够的话你得填,哪个?

 man 2 socket

这个不加也没事socket.h。为什么?这个头文件可能在这里面包含了 netinet/in.h。知道什么意思嘛?你别你写进去你看,如果说报错,你再加上这个没有关系的。好,咱们看一下 Int  main。好,第一步想干什么呀?同学们,创建 socket  怎么调?是不是返回一个文件描述符啊?我们叫 alfd 等于什么呀? socket 第一个参数什么?记不住过来翻。oh,是第一个,是这个,domain 呐?domain 的值是不是好多种?好多种,是不是一般我们用这个居多?是这个叫AF_INET。 

第二个参数什么呀?第二个是不是type 啊?type 的话我们经常用到的是这两个,那么这个是什么呀 socket_stream?同学们是不是用的是 TCP 协议?这个SOCK_DGRAM用的是UDP 协议吧?在这我们是,既然是面向链接的,是不是要有 connect 的过程?肯定是建链接的,那么所以我们用什么呀?socket_stream?第三个参数传 0 就可以了,懂了吗? 有没有可能失败啊?是有可能的,如果这个小于0,咱掉哪头了?

 是不可以?好,

第二步该干什么了?是绑定是吧?兄弟们,绑定。好怎么写?那绑定是不是将这个 IP 端口绑定? IP 端口和文件描述进行绑定,所以之前, 那这个函数我先给你。嗯,这样,这个函数我也给你扒出来,我给你放在这。这样东西我只放一次,后面的不再放了,是不是?这个我给你把这个注释加上,

第二的话是不绑定,咱们也把这个注释加回来, man 2 bind。是这个,

 这样的话咱们照着写就方便写是吧?绑定好,这个是不是bind呀?嗯,来一个返回值可以吗?这个返回值,你看一下这个返回值返回的什么东西?是不是成功与失败的意思?是不是成功返回0,失败返回-1吧?并设置errno。那么你给它加一个判断也行。

第一个参数是socket fd 是哪个?是不是就这个lfd?这个第二个的话是不是需要一个这个类型的一个结构体的地址放在这就可以了?所以你是不是应该先定义一个变量,定义变量以后是不是接下来你要赋值啊?比如说叫serv,可以吗? 那么定义了以后,接下来是不是进行初始化?在这给大家介绍一个你们没用过的函数,叫这个 bzero,这用过吗? 它只有一个参数, 我看是只有一个吗?我看 man   bzero 这个是那一块内存的首地址吧?这个是不是长度?这个长度应该怎么填?是不是 sizeof(serv)?是不是填这个struct sockaddr是不是也可以?它俩是一个值是吧?好,接下来开始赋值了,先赋谁?serv., 记不住翻 怎么翻? ,man 7 IP,我记得是有一个,这里面有吗?是不是有,是不是这个?兄弟们, 大家注意你定义的时候,你这样定义行吗 sockaddr?你这样定义行吗?是不是你说过了,你用的不要用sockaddr吧?用sockaddr_in    这样的话是我们赋值是不是方便一些?好看,第一个是不是这个sa_family_t 

 

 第二个是不是有个端口的?同学们,端口的话我们要在这指定一个端口,比如说 4 个 8  4 个 9 都行啊,这个你随便定,但是你不要这个使用 1024 以前的那些端口,清楚了吗?那些有可能被系统已经预留了,是不是?好,这怎么用?是不是要进行 这个高端字节序和低端字节序之间的转化?我们应该是把什么呀?把什么转化成什么?是不是把本主机字节序转化为网络字节序短整型 ,叫 htons(8888),这你直接填就可以了,比如说 4 个 8 可以吗?好,还有一个 serv.sin_addr.s_addr=, 这等于什么呢?

这咱就直接用那个宏表示使用本机任意可用IP,当然我这就一个。那么这样的话是不是也得需要转呢?也得需要转 。那么怎么转?同学们,那么大家想一下我们这个网这个 ip 地址是几个字节了?是 4 个,是不是最后转了一个是长整形了?这怎么写?htonl(INADDR_ANY)吧? 

这个我给你加个注释,表示使用本机。什么呀?任意可用 IP ,这个咱们先用一下这个咱们后面咱们给你,待会把这个测完之后,我再给你把那个用一下。那个是不是可以把这个字符串形式的ip地址 转换成什么呀?网络字节序 四节的整型值吧?到时候给你用一下那个。好,这个赋值赋完了吗?同学们,是不是就 3 个、 1 个、 2 个、 3 个,就这 3 个已经赋完了,那么接下来是不是开始给写这儿了?这怎么写? s e r v  是不是要做一个强制类型转换? struct sockaddr*  ? 那么你看见  这个参数 人家是不是这个类型的 struct sockaddr?你要给它进行一个强制类型转换 

好,后面还有一个参数,这个参数指的什么意思?这个参数指的是这一块 struct sockaddr *addr内存大小,怎么写?sizeof(serv)是不是这么用?终于可以了,好,判断一下 r e t 小于0,perror(bind error

return -1 是吧?好,这个完事了。好,这个绑定完事。

接下来第三步该干什么了?是不是监听?监听,调用哪个数?是不是listen?咱把这个写完之后再下课行吗?同学们,这个咱们这程序别间断了。行,咱们下课之后让大家多歇会行吗?好  man 2 listen   是不? 我把这个函数原型可以给你写上,你到时候你当然你自己也会查阅最好。好,看一下listen。

第一个它是什么?是不是lfd?第二参数我给他来个 128 行吗?最大值就是128。好,listen完以后接下来该干什么了?是不是要接受一个客户端连接啊?调用哪个函数呢?man 2 accept 好? accept 好,这个 accept 返回值是一个什么值?同学们,返回值是干什么的?是不是通讯的?

int  cfd = accept();

第一个参数是什么?是不是lfd啊?第二个参数是不是客户端的 IP 的端口在这,你不关心传什么,第三个是不是也就没用了?你不关心可以传NULL,待会咱们先凑一个简单慢慢的给你把这个加上。

好,这个好,咱们把这个 CF 打印出来,你说这个 CF 应该是几?同学们?lfd,应该是几,是几?又忘了你们是刚考过啊。同学们,这个前三个文件描述符是不是已经被分配了?那么接下来再分配应该是从几开始分配?3 因为你前面是没有打开文件,是不是?好,这是accept , accept之后,接下来是不是我们就已经得到了一个用于通信的文件描述? 接下来该干什么了?是不是?接下来进入while循环进读写数据?同学们,马上马再讲一会这个,接下来下课的时间一定给你们留时间长点。行,占用的时间一定还给你们。

 这个讲到这儿没办法,这个咱不能中途中断了,好吧?好。那么接下来是开始收数据了,收数据调哪个函数?读数据,其实就是读的谁的数据,朋友们,是不是客户端发过来的?好, read 在这我们需要定一个buf, int  n 等于个0,char buf[1024],接下来在这里面初始化, memset(buf, 0x00,sizeof(buf)),是不是开始读了?n= read 第一个参数传什么,cfd 这个你们应该记得,忘不了吧,不要写成lfd了。

第二个参数,第三个参数,这和文件是不一样的?打印一下这句话,read 函数是不是一个阻塞函数?在这儿,如果没有数,如果客户端没发数据,这个函数就一直阻塞,搞清楚了吗? 那么你这个读了数据了,你要记得给对方发回去,是不要回一个,咱们这样,咱们来一个大消息转换可以吗?明白,大消息转换for 什么呀?这儿就需要一个什么呀?需要循环因子 int i 等于个 0 等于0, buf[i]= toupper(buf[i])

这个函数的声明在这,man toupper  是吧?这个函数是不是这个?你看一下这个什么意思?    to buffer to 什么什么 是不是到什么呀?转换成大写,转成小写需要加一个头文件吗?是ctype.h,这个需要加以ctype.h,这个不加会报错的。是不是一个?好,那么这个相当于这儿是不是一个循环卷完了干什么呀?是不是发送数据啊?发送数据是不是就是写数据的意思啊?调用write,第一个是吧? c f d,第二个buf,第三个n,这场景你知道是不是?好,这个写完了,写完之后 rerturn 0,那么 rerturn 0 之前是不是记得关闭文件描述符了? 关闭监听文件描述符。和什么呀?和通信文件描述符吧?

  好,完事了,咱编译一下,看看, 一步到位是吧? 测试咱们先不测好,咱们下一节再测好,先说到这。

 好,那么上节课咱们把这个成语写完了,是不是?接下来咱们这个来测试一下我们写的这个程序对不对?看看有没有什么漏洞,是不是?有漏洞正常的,咱们改一下就可以了,是不是?咱们看一下这个怎么来测?我先教大家一个小的测试工具,叫 NC  现在给你启动起来吧 ./server。这个现在是不是你启动起来了?好,我问大家第一个问题,这个程序它是不是阻塞了?现在阻塞在什么位置了?哪? listen 是阻塞函数吗?我没说过这句话吧?谁是阻塞的?是不是 accept 在这了?同学们,他阻塞在了这个位置42, 清楚了吗?阻塞这儿了 。

接下来咱们用一个客户端工具去测试一下我们的代码是不对的,怎么测呢?有一个工具叫这个工具, 这个我叫 n c, n c,这是一个小的测试工具,小测工具怎么测?127.0.0.1,那么这个可以简写为 127. 1,光这样写行吗?同学们,光这样写你知道哪个端口吗?是不知道,后面再写个端口,端口是不是我们自己定的?回车看一下,这是不是立刻有返回了?

是不是lfd=3  cfd =4?这个是不是用于监听文件描述符啊?这个是用于通信的文件描述符了,是吧?那接下来咱们发送数据看一下,对不对?你好,他收到了吗?同学们,是不收到了,有 5 个,为什么在这显示了 4 个?是不是还有回车? 这没问题,他是不是也转换完成以后也发过来了?真的是,你是不是也回来了?没问题。

 那么你无论怎么发都没问题,是不是都没问题?那么接着看一个,看一看如果我把这个客户关掉,会发生什么情况?怎么关?我直接 ctrl c 是不是结束了?接下来它进入了死循环,是不是?同学们,那么在这儿这个程序我们是不是需要稍微调整一下?你看一下我们的代码,看一下我们的代码,如果说大家注意,如果说read 返回,如果说就是对方关闭链接了,那么这个read 的函数在这,我们通过这个观察一看出来是返回几,如果对方关闭链接,我们这儿应该返回0,那意味着对方关闭链接了。这种情况下我们这个while(1)循环是不是需要退出?是不是?所以在这儿应该需要调整一下,这个太快了是吧?太快了会容易使你的程序卡死。

 判断如果 n 小于等于0,那么等于 0 的话是什么意思?同学们,刚才看到是不是对方关闭链接了?小于 0 读失败.一个读失败,一个是什么呀?对方关闭链接,这种情况下我们都需要跳出while循环,是不是这样的? read error or 什么? client close退出可以吗?对方关闭链接, client close,可以 client close关闭这些了,然后你可以把这个值打出来,是几?是不是? n,那么这个n,应该是 client close,是不是客户端关闭了,当然客户端退出是不是意味着链接就关闭?然后,是吧?同学们,break,这样才比较合理吧,这样才比较合理。再测, 

 

 没问题,都咱给他结束一下,看看结束是不是他也结束,是吧? read error or client close 正确,对方关闭链接吗?对方关闭链接,他有必要在那阻塞吗?或者是在那死循环吗?没必要了,他也退出就可以了。那么这是我们跟大家学的这个例子,这个例子,这个服务端这个代码应该说并不算太长,而且我们写的是也完全按照我们这个流程来写的,你晚上把这流程敲一遍, 瞧瞧一遍。好,那么下面咱们再说一个什么呢?咱说一下这个客户端的开发流程。

好, 第一步干想干什么? 第一步是不是创建socket?那么可以得到一个什么呀?同学们返回一个什么?一个文件描述符,那么这个文件描述是干什么的?是不是通信的?我跟你说一下,该文件描述符是用于和谁通信?服务端通信。

第二步啊,有了 socket 了,接下来需要干什么啊?是不是要连接谁啊?连接服务端哪那么为大家。

第二步的话,我这个客户端能绑定吗?他能不能绑定? 。在这里不是说他不能绑,他能绑定,但是他绑定相当于多此一举。为什么说多此一举呢?你绑定相当于你把这个客户端的端口给固定了,如果不绑定会怎么样?不绑定其实是我们经常使用的不绑定这种方法。不绑定内核会给你随机分配一个端口,你绑定了相当于,你是不是你自己给它定死了?万一你定了端口有占用了怎么办?知道什么意思?所以这种东西你交给内核去处理就可以了,内核会给你随机分配一个端口,所以我们一般情况下不绑定,但是服务端必须绑定,如果不绑定,你让内核随机分配,连你自己都不知道是不是这样的。

你怎么对外提供服务,明白了吗?好,这个好,咱们看一下第二步是什么呀?直接是不是连接服务端啊?调用哪个函数了?连接服务端,调用哪个函数? connect  ,当然第一步的话我们调的是哪个?是不是这个socket? 调用 connect  函数连接服务端。

第三步,你们第二步连接服务端的话,你说这个客户端需要什么信息?他得知道连谁他怎么知道?说那个谁?怎么标识啊?是不是 IP 加端口? IP 和端口 好?第三步,那么连接好以后,接下来是不是很简单了?就看什么呀?链接已经有了,是不是收发数据就可以了?是不是同学们?就这样的创建socket,我看咱们应该是没落,这个客户端,这个相对来说比这个服务端是不是要简单很多?是不是 socket 和 connect 接下来是不是要收发数据了?我问大家怎么没表情呢?我以为写错了。

第三步叫什么?是不是他先发送数据?发送数据,发送数据是不是相当于写数据调啊?调用哪个函数呢?write或者什么呀? send吧? 这玩意之后呢?接收数据调用哪个函数? read 或者什么呀? recv 那最后不用了呢?完事之后,要close,是吧? close 就可以了。

close 是不是只有一个?是不是同学们?好,整体上这客户端的流程就这样子,下面咱们就遵照这个流程给大家把这个代码写下。这个写起来应该就比那个是不是简单很多了啊?简单很多了。好,

 

那咱们接着写好 这个我再给你说一遍。那么这一步创建socket这个第一步的话和那个服务端是不是一模一样?嗯,那句话你就可以直接扒过来,但是这个它返回这个文件描述符呢,是用于通信的,服务端。服务端那个用的是不是用于监听的?给你加一个注释,用于什么呀?用于和服务端进行通信是吧?好,第二个是连接服务端,那这个你记不住过来看,是不是这个?同学们,

第一个参数它显示什么呀?是fd吧?,第二个是一个地址吧?,第三个是不是这个地址长度?好,这个参数咱想和哪个函数完全一样? 和bind 不是bind 一样啊?还记得吗?那个是绑定,这个是连接,他俩才是完全一样。这个是第一次讲,我给你把这个扒出来。
 

 好,这个返回值怎么说的,我看看,你看没有,什么意思?你看他俩是不是说在一块了,是吧?你们如果连接成功或绑定成功的话,是不是返回 0 失败?返回-1? 必须是errno  ,你给他,那就给他判断一下吧

 connect 第一个什么呀?cfd吧?第二个,第二的话咱们先写上好,到时候再赋值,比如说我们叫serv,当然这个是不是要进行强力转化? struct sockaddr *  ,最后一个是不是长度 ? sizeof(serv)?那么接下来是不是你应该给这个给这个 serv赋值?所以我们要定义结构体叫struct sockaddr_in serv;赋值。

serv.sin_family 等于什么?AF_INET;    第二个呢? serv.sin_por  这是端口吧,这端口谁啊?同学们谁的端口了?那要连服务器,是不是你得知道服务器端口了,这个服务器我们设置的是不是 4 个8?在这是不是你仍然要使用 4 个8?所以进行什么呀?是不是转换啊?htons 第一个参数,什么?它只有一个参数,那将来是不是这个?接下来是不是 IP啊? serv.sin_addr.s_addr,  这能不能用那个 in_addr吗?用那个行不行?也没问题,用那也没问题,但是在这我给你用一个另外一种方式,这俩给你岔开 

 现在我们是不是要把一个字符串形成的 i p 地址转换成什么呀?是不是网络字节序的 4 字节的那个地址?嗯,用哪函数啊?用哪函数?inet_pton();是不是指的是点分十进制的那个啊?n是不是网络字节序啊?这个参数记不住,查,man inet_pton是不是这个?

好,第一个参数 是不是af啊?很显然我们是不是应该用AF_INET, AF_INET,第二个参数是不是这个是不是一个点分十进制的字符串形式的 ip 地址?后面是不是我们要保存在哪个位置,是吧?好,第二个的话,有了这我们怎么写?127.0.0.1,这个是不是指的本地地址啊?好。

 第三个参数是不是就这个玩意了?是不是他 serv.sin_addr.s_addr ?这儿是不是加个地址啊?同学们,看人家加了吗?是不是有它是void * 吧?是吧?好,这个也就是说这个我们已经是不是把这个 ip地址的值给附上了?并且也转换成了什么呀?是不是网络字节序的四节整型值?,这个我给你把这个整型值打出来,是不是这样的?是不是要打他serv.sin_addr.s_addr ?同学们,是不是打他?咱们打印成 16 进制可以吗?百分之什么呀? p 吧?是不是这个?好,这个你关注一下。好,接着 connect 判断一下是不是有可能会失败。

man 2 connect 

connect 的返回值是什么呀?同学们,成功是0,是不是成功是0?失败返回-1啊?,一般都是这样的,我看是不是吧,一般都这样了。好,如果小于0是不是认为失败了? perror吧?好,是不是有了?现在 这个函数量成功是不是相当于和他和这个服务端建链接了?建立链接之后,那么接下来是不是他可以收发数据了?可以发送数据了,好 while。什么呀?发送数据,那我问一下大家发送数据,它把数据写到哪去了?写哪去了?写到了内核的什么缓冲区?是不是写的缓冲区?那么我问大家,你说这个,我在这调用这个 write这个函数 

那么我是你说这个函数它有没有直接把数据给你发出去?有没有?你搞清楚?没有,这个它这个 write 函数只负责往发送缓冲区里面写。那么至于说到底是谁把数据真正发送出去的,并不是你做的,谁做的?内核做的 清楚了吗?你只要往那写就可以了。内核负责把这个数据从发送缓存去拿出来,然后是不是最终要调用这个网卡的驱动程序把数据发送出去,最终发送数据的设备一定是网卡,清楚吗?是不是硬件的?write ?第一个怎么写?咱们这样,咱们那个发送的时候,咱们先是不是可以从这个标准输入读数据,可以吗?读什么数据?读标准输入数据,调用哪个函数呀?同学们, read 吧,char buf[256],这个能小点。memset  ,n 等于什么呀?read,先读数据,读数据读的是这个 STDIN_FILENO,也就是我们从这个终端输入,然后再把这个数据是不是发送到网络上啊?

好,那这个数据读出来了,然后接下来是不是要把这个数据写上哪了?写到这个网络上去,第一个 c f d,第二个 buf,第三个n,是不是? 好,那么发送出去之后是不是要读服务端发过来的数据?嗯,读服务端发来的数据,调用哪个函数?当然是不是,我们先初始化一下啊?是吧? n 等于 1 个read,第一个参数 cfd,第二参数buf ,第三个参数 sizeof(buf)。

好,咱们打一下这个读的数据,printf,那就直接写行,是不是了?这个是不是相当于我从标准输入读数据,然后把读的数据是不是写到网络上去?是吧?发到服务端,然后发过去之后是不是要我要等待这个服务端发送数据回来?整体是不是来回循环的?来回循环。

好,咱们看一下那最后的最后这个退出循环以后干什么呀?close?哪个?关闭套接字?谁?cfd?这个套接字是不是通信套接字啊?好最后呢?return 0,这才是你的标准程序?当然这个里面的话,是不是我们这儿应该也加一个判断,如果说我服务端把这个链接关掉了,有没有可能啊? n 如果小于等0,是不是相当于这个读失败或者什么呀?或者是这个对方关闭链接了吗? read error  or server is closed ?

 这个是 n 是吧?这儿是不是直接 break啊?好,那么整体上我们这个程序是写是不写完了? 一共就这么五十几行一共就这么五十几行。那么咱们编译一下看一看。

man  inet_pton  缺少头文件,他们这个他是不是在这用?看着少他不行。那就咱每次把它加上就完了。还少哪个? 26 号? 26 个,我看26。这个手是吗类型?噢,这个错了,这个应该是打什么呀?咱们打成百分之x,这样比较合理。那个打地址对吧?是吧?同学,那个打地址的话是不是就要加个 enter符吧? 那应该加个什么呀?加个回车吧, 好,没问题, 那咱就测一下是不是应该先启动服务端。好看一下,我给它启动一下。起来。

 这个先看一下这个值是不是那 127.0.0.1   

   7F 加 1 是不是128?这你说嘛? 7F 是不是 7 个1啊? 7 个 1 加 1 是不是就是1,后面 7 个 0 是不是这样的? 2 的几次方? 7 次方减一是不是127?我把这个计算器打开给你看一下,这个是这个,首先把这个地址给观察一下,这个是这个二进制的,得弄 16 进制是吧?

但你这样算不行,你知道什么意思吗?我们这个是什么字节序啊?,这个是不是网络字节序啊?网络字节序,你是不是因为我们本机是不是小端字节序啊?你是不是要给倒开啊?这是不是7f 在前面了?7f然后0.0.1吧?那么这个 7f很显然我打出这个时候 应该是打7F吧?7F就是什么呀?是不是这个啊?对吧? 那么这个加 1 等于多少?加1,这样是不是 128 ,128减一是不是127,这没问题,这没问题。

好,这是这个,咱们给大家看过了,我再让大家观察一下。链接。netstat -anp,大家注意查看这个 t c p状态的,这个怎么看?叫 net stat 这个命令。 net 是网络的意思。  state 是不是状态的意思?-a, a 指的所有的, n 指的数字形式显示。这个这个讲义我有,我给你说一下。这你用的时候有这么用就可以了。在哪?我看,这这个命令,这个 a 表示显示所有, n 表示显示的时候以数字的方式显示,比如说pid是不是数字啊?是吧? p 是显示进程的信息,比如说这个进程名和 进程pid 等等。

 

 这个你看一下,这个我给你打一下,知道什么意思? grep 是不是过滤一下? grep 8888

注意看,注意看,看看这一行,这一行,这是不是 server啊 第三行?

是不是server?那么这个 server 它的这个 IP 是不是 127.0.0. 1?这个端口是8888?这一侧指的是本,指的是自己这一侧这种情况,因为连接的话,是不是双方啊?这是自己这一侧 127.0.0. 1:8888,那么这一侧是对方那一侧,对方指的谁? server 的对方是谁?是不?客户端的,这是客户端,客户端是51188,看这个是不是客户端啊 第二行?

客户端这一侧是不是 注意看客户端这次是不51188,这是 正常对应啊?嗯,这俩是不是相互?对方是不是指的是相互的? 他的对方是 a 的对方是b, b 对方是不是a?这意思也就是说你看一下这个是完全一样,嗯,这俩是不是正好配对了? 这个整个的,这个整个下来啊?嗯,注意看啊,整个下来这个是不是就是我前面跟你说的那个socket片啊?我是不是跟你说过一个链接里一个链接其实真正有socket片啊?这个是不是socket片啊?是吧?从这就看可以看出来了。

 那么这儿呢,有一个状态叫ESTABLISHED 的,这个呢,咱们后面讲进程状态的时候跟你说这个的意思,表示链接建立了,清楚了吗?朋友们,表示链接了,再看这什么意思 LISTEN?这个LISTEN的出现一定是出现在客户端还是服务端?一定出现在服务端,那这LISTEN表示你这个进程已经处于 listen 状态了,能理解吗?那么处于 listen 状态的进程是可以让客户端去连接他的。

很显然,我们下面是不是已经建立链接了?能理解吗?他们已经建好链接了,是不是这块了?这个是不是一个连接对啊? 那咱们这个大家会看了以后我给大家来演示一下。那么我这个客户端和服务端进行通信的过程。

这个是服客户端,写一下,你好,收过来了,他收到了吗?看正常。然后再来一个,是不是收到了转换是不是正常?然后咱们看一下,如果说我讲服务端给关掉,客户端会不会退出,理解什么意思吗?嗯,退出没有?没有,再想一下这个没有是为什么?没有?阻塞在哪?我们这个客户端是不是接收标准输入的输入啊?然后是不是我们输入数据以后把这个数据是不是要写到网络?是要发送给谁呀?服务端吗?他阻塞在哪了?阻塞在标准输入了,你不信我一写一下,我写这我一回,这马上可以出,你好是不是退出了?

 嗯,那么也就说也第二个read,他在读网络的时候,是不是他看到这个对方的这个链接已经关掉了,他是不是马上就退出了,也就不再阻塞了?理解了吗?这个咱这样是不是这样?那么咱们观察一下这个accept之前这个链接是不是已经建立了,知道什么意思?怎么测也非常的好测。代码,我给你稍微调整一下,这个叫,那么我这样做,你看一下我这样给他做一个实验。

 怎么做实验?我在 listen 之下,accept之上,我给他加一个sleep,30,知道什么意思吗?我加一个sleep,然后我用客户端去连接它,那这个函数肯定是仍然是不是在这 sleep 30,那么你看观察一下这个链接是不是已经有了,知道什么意思吗?观察一下这链接是不是已经有了? g c c  -o  server

 

 

,是不是起来了,然后我这样,我用nc 这个命令 127. 0.0.1,然后 4 个 8 回车,很显然这个accept函数是不是没有立刻返回?这句话是没打出来。好,那你观察一下链接有没有 netstat -anp | grep 8888   连接有了没有?有了没?同学们,有了,你只要能看到这说明链接已经有了,清楚了吗?也就是链接其实是在accept之前已经建立了。

 

 那么关于这个 accept的函数,我这儿有一个图给大家看一看。这个图,这个有点不太雅观,我本来不想看这个,这个我给你找找。这个比较这个有点搞笑, 我看看是哪个还有没有了。哪,怎么想找他找不着他呢?看这个图明白,这是我从深圳的时候一个同事给我的,

我看着非常这个,当时这个讲这个时候有同学可能不懂这个 accep什么意思,那么这我为什么要在这说这个?刚才我大家举那个 sleep 30,我在accep的之上是不是加了一个 sleep 30 啊?我是不是跟你说了, Excel 的函数之前可能链接已经建立了,那么调用accep 的函数是不是相当于拿出一个已用的可用的链接来?那么很显然这什么意思?比如说这个是我们已链接队列,兄弟们,这个这里面这有人是以链接队列,那么也就是说在accep之前这个队列里面已经有链接了,那么调用accep 函数其实就是从这个链接里面拿出一个来,知道什么意思吗?

从这个已链接队列当中拿出一个可用链接来,就这意思在言外之意什么呀?同学们?言外之意是 调用 accep的之前,链接就已经可能已经存在了,是吧?同学们,当然我在前面如果不加sleep 30的话,是不是客户端只要一连接accep函数是不是立刻返回啊?因为什么呀?因为它那个是瞬间就完成了,知道意思吗?如果说accep之前有一个sleep,那么这个时候你不要认为accep 之前就是 sleep 30 期间的并没有新的链接产生,这是不合理的

 知道这意思,调用 accept 并不是说新建一个链接。我这给你写一下。这个我比较清楚。一些细节。第一个细节,调用 accept 的函数不是说新建一个链接而是什么同学们?而是从已链接队列中取出什么呀?一个可用链接。这句话咱们这个测试是不是给你测过了?因为在accept 的之前已经有这个链接了,我们调用accept的只是说拿出一个可用链接来,并不是说他去新建一个链接,这句话能搞清楚吗?好,这个好,那么关于在哪函数,咱们还有一个什么呢?还有一个小的点没有给你测到。哪个点?这个点。

咱们看一下这个客户端的 IP 和端口是不是在这没有给你用?42 是不是第二个参数,第三个参数,都是NULL啊?在这咱们给他用一下,不是那我的情况,那为此我们是不是应该定义一个结构体,用来接收这个客户端的信息啊?哪些结构体呀?是不是struct sockaddr_in client;这叫 client  他那是不是还需要一个长度,是吧?同学们, 这个长度怎么说? 不是len,他的数据类型

 man 2  accept

 是不是这个数据类型啊? socklen_t  len

它初始值应该是什么呀?同学们,是不是sizeof(client)?我是不是跟大家说过这个参数是不是一个?既是一个传入也可以传出?好,第一个参数怎么写?是不要进行强制类型转换啊?,是转化问题吗?看一下哪是不是这个?你得转换这种类型吧?这儿怎么写?是不是client ?是不是取地址?嗯,这个是不是既是传入又是传出啊?是吧同学们?这怎么写? 如果仅仅是传入的话,还有必要用这个地址吗?兄弟们,没有必要。嗯,这种数值类型是不是直接传值就可以了?这种是既是传入也是传入,len是一个输入,输出参数。

 好,那么咱们把这个客户端地址获取了,然后咱们打印一下客户端的 IP 和端口,可以吗? ,第一参数怎么说?这个的话,首先大家注意我们现在是不是已经得到 IP 了, IP 的话是一个什么类型的?同学们,是不是一个网络字节序的长整型的整数值啊?我们是不是应该调用一个函数,把这个值转换成什么字符串形式吧?调用哪个函数啊?inet_ntop是不这个? 参数记不住没有关系,查慢这个。

man  inet _ntop 

第一个是af 

 这是第一个参数,应该填什么呀?

是不?这个你看到这af,  你就很容易能想到这个AF_INET ,第二个是src,这个是一个传入还是传输?传入,传入的是谁?是不是就是那个 4 字节的整型的网络字节序那个值啊?整型值,这怎么写?这你写地址吧,应该怎么样?应该是client.sin_addr.s_addr,是不是这个已经拿到值了?是不是?这个ip地址是不是保存在这个 s_addr里面,是吧?同学们,这个你记不住,你到时候你把这个代码拿过去之后,你好好写一遍,好吧?

第三个参数是一个什么呀?是不是要把这个 ip 地址保存到哪个里面去?在这我们是不是应该定义一个什么呀?什么是不是 IP 啊?多少?是不是 16 就够了? memset,是不这个,好看一下?那么第二个参数我们应该传第三个参数,是不是写 SIP 就可以了?最后一个参数,最后一个参数是不是指的它的长度 char * dst? 是不是sizeof(SIP)是不是这个?那这样的话,我们这个ip地址是不是就保存到这个 s i p 里面来了

?那么再看一下它的返回值,这个函数的返回值是什么呢?是不是在这?是不是反回 char *啊?这 char *是不是指向就是他呀 char * dst?是不是?这个我是不是跟你说过了?嗯, 好,这个那么再看 ip 地址呢? ip 地址是不是也是一个网络字节序的值?是不是网络字节序?那么你应该把它转化成什么呀?主机字节序吧。

 

 你注意你从网络当中得出来的值都是网络字节序的,这个是不是你44 调用accept函数之后,是不是那些 IP 地址端库给你保存到这个里面来了 client?保存这里面来的一定是网络字节序的值,只要是这个什么呀?这个数据类型的,这个长度大于 1 的都是这样的,你需要进行转化,那么这个端口号是不是也是两个字节的?是不是短整形?这个怎么把它转化成什么呀?主机字节序怎么转? ntohs(client.sin_port)是不是这样的? 这端口是不是保存在这个 sin_port里面,这个有点长了, 

 

好,它是不是这样的?这两个函数也大家也学着用一下,特别是你调用accept函数以后,那么你获取到了这个客户端的这个地址信息的时候,你需要把这个东西给加上,那么大家想一下这个有什么好处?我们 accept 函数把第二个参数给它写上去,我们获取对方的 IP 的地址有什么有什么好处? 一个最大因素是它可以设置黑名单,知道什么意思吧?我举个例子,那么我这个服务端可以让,可以不让某些恶意的客户端来访问,是不是?我一看是你的话,我立刻给你拒掉,嗯?怎么去掉他们?你 accept 之后是不是你就知道谁给你谁连你了?你连以后一判断,你可以把这个恶意的这个 IP 的这客户当IP,你保存一个什么里面保存一个文件当中,你是不是可以搜索这个文件,这个 IP 是不在这个文件当中?或者是你组成一个列表是不是也可以?反正这个办法很多,保存数据库当中也行,那么一查的话,这个 IP 在这个黑名单里面直接就close掉,他是不是想发数据发不了了?知道这意思这么回事。好,这个我给你测一下是不是这样的?

 

 这个已经被占用了 bind error,这个的确被占用。他是不是还没退出?他没退出你能连吗?兄弟们,你连不了,是不是他也退出了,是吧?这个服务端一关,是不是马上的 NC 也退出了?是不是现在你再启动仍然启动不了?是不是启动不了?bind error 这个大概要等 1 分钟大概要等 1 分钟。

 为什么会这样?咱们后面会讲这叫 地址重用, 地址重用了,它会保持一个大概 1 分钟的时间左右,  1 分时左右,那么有一个函数可以解决这个问题,明天咱们再讲,那叫 set sock OPT 函数可以设置端口复用。这现在启动一下,看看有没有起来,是不是起来了?好,起来了,咱们接下来看一下咱们能不能获取这个客户端的IP,来获取一下。

起来,没反应,不对,这个,他 sleep 了,是不是有sleep?是吧? 这是不是有sleep30?那会儿?好,你现在这个地址是不是找到了这个端口是 51992 了,那么怎么看下验证下这个端口对不对呢?n

 

是不是端口是 51992了?那么打印出来是不是51992,你看没?是不是这个?

那么客户端口是不是这个没问题吧?好,这个程序咱们就说到这行,这程序咱说到这,那么基本上咱们该讲的差不多讲完了,这个 sleep 30 给它去掉,这个 sleep 30 是不是在这加的?去掉这一块是,给你加个注释,获取client端的 IP 和端口,当然获取的话应该是不是 accept 第二个参数获取的,在这是不是我们调用这个函数 inet_ntop和这个函数ntohs打印出来的?兄弟们,这个你得会用,再试,得等大概 1 分钟,不到 1 分钟可能,

好起来了再试,咱们用client,这没有这个,这个是把这 sleep 去掉之后,是不是这个是不立刻就有信息了?端口是51994,看每次和每次都不一样,再看是不是这个 51994 51194,看,是吗?我摇一句没问题,那发出去也正常吧?关闭呢?是不是也退出,是吧?同学们,这个。

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值