网络基础概念
网络基础概念
- 1、计算机网络背景
- 2、初识协议
- 2.1、初识协议
- 2.2、协议分层
- 2.3、OSI七层模型
- 2.4、TCP/IP五层(或四层)模型
- 3、再识协议
- 3.1、为什么要有TCP/IP协议族?
- 3.2、网络与操作系统的关系
- 3.3、究竟什么是协议?
- 4、网络传输基本流程
- 4.1、局域网(以太网为例)通信原理
- 4.2、数据包封装和分用
- 4.3、MAC和IP
- 4.4、跨网络传输
- 5、Sokect编程预备
- 5.1、认识端口号
- 5.2、传输层的典型代表
- 5.3、网络字节序
- 5.4、socket 编程接口
1、计算机网络背景
最早,计算机是在实验室,那些科学家使用的。但是它们发现比如小松处理完的数据要交给小竹继续处理,小竹处理完的数据要交给小梅继续处理。小竹要等小松的数据,小梅要等小竹的数据,小松处理完之后要拷给小竹,它们还不一定在同一个地方,如果在不同地方的话小松还得专门跑一趟再拷给小竹。刚开始计算机之间是相互独立的,由于这种方式效率低下,所以科学家就想办法让网络互联,多台计算机连接在一起,完成数据共享。
小松处理完之后将数据推送到服务器,然后小竹从服务器上拉下来,小竹处理完之后再把数据推送到服务器,然后小梅再从服务器拉下来。效率就提升了。
局域网LAN:计算机数量更多了,通过交换机和路由器连接在一起。
广域网 WAN:将远隔千里的计算机都连在一起。
2、初识协议
2.1、初识协议
协议是一种约定。
在过去打电话用的是座机,而且电话费挺贵的。这时候你上大学了,准备去千里之外上学,你就给你爸说,电话费挺贵的,我用舍友的电话打,你给了你爸一个号码,并和你把约定说:以后我往家里打电话,响一声直接挂掉就是我在给家里报平安。响两声直接挂掉就代表我没钱了,你得给我打钱。响三声这时候你再把电话接起来,这时候说明我有重要的事情要和你商量。然后你去上大学了,你和你爸一直遵守着这套约定,这套约定实际上就是协议。
我们知道计算机只能识别01,而不同计算机对01的表示方式不同。比如有的计算机用光电信号的有无、有的用光电信号的强弱、有的用波形图的疏密。而两台计算机要进行通信,它们硬件方面就得采用同一套协议来表示对应的01。
计算机生产厂商有很多。
计算机操作系统, 也有很多。
计算机网络硬件设备, 还是有很多。
如何让这些不同厂商之间生产的计算机能够相互顺畅的通信?就需要有人站出来,约定一个共同的标准,大家都来遵守,这就是网络协议。
2.2、协议分层
协议本质也是软件,在设计上为了更好的进行模块化,解耦合。也是被设计成为层状结构的。
当两个人在电话通信的时候,我们都认为两个人在直接通信。但实际上你说的话是先要交给电话机,然后电话机传输到对方的电话机,对方的电话机再处理播放出来,所以对方才能听到。在语言层面上,我们都用汉语沟通,所以使用的是汉语协议。而在下面的通信设备,它们遵守的就是电话机协议。站在小白的视角,我们认为同层可以直接通信。
上图就是协议分层的例子,当我们不使用电话机了,改用无线电了,我们发现通信设备层的改变并不会影响语言层。当我们语言层改用英语进行交流,我们发现通信设备层也不会受影响。这就是协议分层带来的好处。
视角:
1、小白:同层协议,直接通信。
2、工程师:同层协议并没有直接通信,是各自使用下层提供的结构能力完成的通信。
分层是解耦合的有效方式,提升可维护性。
2.3、OSI七层模型
OSI(Open System Interconnection,开放系统互连)七层网络模型称为开放式系统互联参考模型,是一个逻辑上的定义和规范。
把网络从逻辑上分为了 7 层。每一层都有相关、相对应的物理设备,比如路由器,交换机。
OSI 七层模型是一种框架性的设计方法,其最主要的功能使就是帮助不同类型的主机实现数据传输。
它的最大优点是将服务、接口和协议这三个概念明确地区分开来,概念清楚,理论也比较完整. 通过七个层次化的结构模型使不同的系统不同的网络之间实现可靠的通讯。
但是, 它既复杂又不实用。所以我们按照 TCP/IP 四层模型来讲解。
其实在网络角度,OSI 定的协议 7 层模型其实非常完善,但是在实际操作的过程中,会话层、表示层是不可能接入到操作系统中的,所以在工程实践中,最终落地的是 5 层协议。
2.4、TCP/IP五层(或四层)模型
TCP/IP是一组协议的代名词,它还包括许多协议,组成了 TCP/IP 协议簇。
TCP/IP通讯协议采用了 5 层的层级结构,每一层都呼叫它的下一层所提供的网络来完成自己的需求。
物理层:负责光/电信号的传递方式。比如现在以太网通用的网线(双绞线)、早期以太网采用的的同轴电缆(现在主要用于有线电视)、光纤,现在的wifi无线网使用电磁波等都属于物理层的概念。物理层的能力决定了最大传输速率、传输距离、抗干扰性等。集线器(Hub)工作在物理层。
数据链路层:负责设备之间的数据帧的传送和识别。例如网卡设备的驱动、帧同步(就是说从网线上检测到什么信号算作新帧的开始)、冲突检测(如果检测到冲突就自动重发)、数据差错校验等工作。有以太网、令牌环网,无线 LAN 等标准。交换机(Switch)工作在数据链路层。
网络层:负责地址管理和路由选择。例如在 IP 协议中,通过 IP 地址来标识一台主机,并通过路由表的方式规划出两台主机之间的数据传输的线路(路由)。 路由器(Router)工作在网路层。
传输层:负责两台主机之间的数据传输。如传输控制协议 (TCP),能够确保数据可靠的从源主机发送到目标主机。
应用层:负责应用程序间沟通,如简单电子邮件传输(SMTP)、文件传输协议(FTP)、网络远程访问协议(Telnet)等。我们的网络编程主要就是针对应用层。
一般而言:
• 对于一台主机,它的操作系统内核实现了从传输层到物理层的内容。
• 对于一台路由器,它实现了从网络层到物理层。
• 对于一台交换机, 它实现了从数据链路层到物理层。
• 对于集线器, 它只实现了物理层。
但是并不绝对很多交换机也实现了网络层的转发。很多路由器也实现了部分传输层的内容(比如端口转发)。
3、再识协议
3.1、为什么要有TCP/IP协议族?
首先,即便是单机,你的计算机内部,其实都是存在协议的,比如:其他设备和内存通信,会有内存协议。其他设备和磁盘通信,会有磁盘相关的协议,比如:SATA, IDE, SCSI 等。只不过我们感知不到罢了。而且这些协议都在本地主机各自的硬件中,通信的成本、问题比较少。
现在主机A要给主机C发送数据,但是目标主机C离主机A太远了,所以就会有以下问题:
1、我要发数据给主机C,得先发送到路由器R,怎么办?——物理层+数据链路层
2、网上这么多主机,怎么定位并找到主机C,怎么办?——网络层
3、如果我的数据发出去丢失了,怎么办?——传输层
4、发送数据不是目的,只是手段,用数据才是目的,主机C怎么知道我发出去的数据该怎么处理,该怎么使用?
有了问题,就需要解决问题。所以针对这些问题我们需要定制协议来解决,而这些问题又是不同性质、不同种类的问题,所以协议是要分层的。
网络通信最大的特点就是主机之间变远了,所以产生了这些问题,而TCP/IP协议族是这些问题的解决方案。
什么是TCP/IP协议?
TCP/IP 协议的本质是一种解决方案。
TCP/IP 协议能分层,前提是因为问题们本身能分层。
3.2、网络与操作系统的关系
网卡就是底层硬件,数据链路层属于驱动程序,传输层和网络层在内核中,之后往上我们统一称为应用层。
而操作系统可以不同,比如我是Windows,你是Linux,但是网络协议栈必须是一样的。所以虽然操作系统不同,但是使用的是相同的网络协议栈,因此两台主机可以直接通信。
传输层最著名的协议是TCP。
网络层最著名的协议是IP。
而传输层(TCP)和网络层(IP)两层必须在操作系统内实现,所以无论操作系统再怎么不同,这两部分代码必须是相同的。而在网络协议栈中最核心的就是TCP和IP,所以把这个协议整体统称为TCP/IP协议。
所以最终的结论就是:网络是操作系统的一部分。
3.3、究竟什么是协议?
传输层网络层都是对所有协议的统称,传输层有很多协议比如:TCP、UDP,网络层也有很多,那么这么多协议操作系统要不要管理呢?当然要管理,如何管理?——先描述,再组织。所以协议就是结构体。
操作系统使用C语言写的,而网络属于操作系统,因此TCP/IP网络也是用C写的。而Windows和Linux操作系统的源代码是不一样的,但是它们网络部分的代码必须是一样的。
那么今天windows上有一个协议struct protocol,里面三个整形变量a,b,c。主机A定义了一个数据data赋值10、20、30。那么主机A把数据发送给主机B,主机B一定能把数据提取出来。因为它们的代码一样,数据结构也是一样的。
用同样的代码实现协议,用同样的自定义数据类型,天然就具有”共识“,能够识别对方发来的数据,这不就是约定吗?
所谓协议,就是通信双方都认识的结构化的数据类型。
我们网上购物收到快递,比如买一瓶洗面奶,商家给你发过来,你只要洗面奶,但是你收到的是一个盒子,盒子上还有一张纸。你收到的东西比你要的东西会多出来一部分,就是那张纸。如果用计算机语言来描述这张单子就是结构体。今天你要的东西是洗面奶,但是你实际收到的是单子+洗面奶,这个单子我们就称为协议报头。所以进行网络通信的时候也和快递物流一样,今天你要发送的数据是hello,但是实际上你发送的是还要在hello前面加上一个结构体变量,这个结构体就是报头。而我们刚说协议就是双方都认识的结构化的数据类型,所以完整的报文里面带了报头,发送方认识接收方也认识,那么就可以进行报文的读取解析和处理。
4、网络传输基本流程
4.1、局域网(以太网为例)通信原理
首先,两台主机在同一个局域网可以直接通信。
今天老师在上课,突然说:张三,你作业为什么没做。那么老师说了这句话之后,张三就站起来。那么教室里的所有人都听到了,那为什么其他人不站起来呢?因为所有人在听到这句话之后,会提取一个关键信息,就是名字:张三,然后跟自己的名字进行比对,发现不是自己的,所以就不响应。然后张三站起来之后就对老师说:老师我早做了,你是不是没看呢,下课再仔细看看吧。那么这时候教室里的其他人也都听到了张三说的话,但是只有老师会处理,其他同学不会说:张三你作业就是没做,你还敢顶嘴。其他同学并不会这样。所以刚才老师在和张三通信的过程中,老师认为他在和张三直接沟通,张三也认为他和老师直接沟通。
那么每台主机都会有一张网卡,而每张网卡会有一个唯一的地址,叫做MAC地址。
现在有一个局域网,有五台主机A、B、C、D、E。每台主机都有一个MAC地址,分别对应MacA->MacE。现在主机A要给主机E发送数据:你好,所以主机A构建一个报文如上图,然后主机A就会将报文发送到网络里。那么网络里的所有主机是都可以收到的,就类似上面老师对张三说话,那么主机B收到了之后会进行判断,发现dst为MacE,而我是MacB,所以就丢弃掉了。那么对于主机CD也是如此。所以底层把收到的数据直接丢掉了上层用户是感知不到的。到了主机E,主机E将dst提取发现dst为MacE,而自己就是MacE,所以就接受向上处理。那么主机E给主机A回数据也是这样的过程。所以局域网通信,主机发送的消息,其他所有主机都能接收到。
我们不能只看到一台主机,我们还要看到每台主机都有一个网络协议栈。用户发送数据和接受数据要贯穿网络协议栈。
主机A和E要通信,那么其他主机也可能要通信。就比如现在教室里大家都在说话,所以就乱糟糟的。因此局域网通信在任何时刻只允许存在一份有效的报文。那么今天主机A要给主机E发数据,主机B要给主机D发数据,那么它们之间就会相互干扰,这种情况我们称之为碰撞。所以就需要进行碰撞检测和碰撞避免。主机A会对发送的数据进行检测,如何检测呢?硬件是有电压的,那么当没有发数据的时候以太网电压和网卡电压是比较低的,当发送数据后电压就会升高,所以可以通过电压来判断。主机A检测到发生碰撞后就会执行碰撞避免算法,隔一段时间再次发送。我们把一个局域网称为一个碰撞域,每台主机发送数据可能会发生碰撞,所以就要进行碰撞检测和执行碰撞避免算法。
以太网随时都可能被主机A、B、C、D、E访问,所以以太网就是公共资源,在以太网中发生了碰撞就是数据不一致问题,而碰撞检测和碰撞避免本质就是保证以太网使用的唯一性。所以以太网就是临界资源,所有主机访问以太网就是以互斥的方式访问的,只不过它互斥的方式比较特殊。
4.2、数据包封装和分用
报文=报头+有效载荷。
并不是主机A给主机E发送数据,实际上是用户A要给用户B发送数据。用户A发送的数据要先经过应用层,封装应用层的报头,这时候有效载荷就是你好。然后在经过传输层,封装传输层的报头,这时候有效载荷就是除传输层报头以外的所有内容,经过网络层和数据链路层也是如此。我们把这个过程称为封装的过程。
数据发送给用户B,用户B的网卡先收到,然后向上交付给数据链路层,数据链路层将链路报头和有效载荷分离,这就是解包。然后再向上交付,而要向上交付报头里必须要有一个字段用来表示交给上层的哪个协议,这就是分用。网络层同样将报头和有效载荷分离继续向上交付,最后给用户B的数据就是你好。这个向上的过程我们称为解包和分用的过程。而在同层协议看来,我们认为同层协议直接通信。
报头的共性:
1、提供报头和有效载荷分离的能力。
2、报头内部必须包含一个字段,用来表示交付给上层哪个协议的字段——分用。
用户A发送数据给用户B,用户B的网卡先收到,然后肯定要通过操作系统来不断向上解包和分用,最后交给用户。那么用户B的操作系统如何知道网卡上有数据了?——硬件中断,操作系统就会找中断向量表里的中断方法,然后将网卡上的数据搬到操作系统内,解包分用向上交付。
报文=报头+有效载荷。不同层对报文的叫法有所不同:
应用层——请求与响应
传输层——数据段
网络层——数据报
数据链路层——数据帧
4.3、MAC和IP
唐僧和它的徒弟去西天取经,目前到了车迟国,那么唐僧问车迟国的国王,我从东土大唐来,我要去西天取经,那么下一站我该怎么走,车迟国的国王就告诉唐僧,离我们这最近的城池是女儿国,下一站你应该去女儿国。所以唐僧就有两套地址:东土大唐到西天,这是从起点到终点。还有一套地址:车迟国到女儿国,而这套地址没经过一个城池就会发生变化。当唐僧到了女儿国,问儿女国的国王下一站应该去哪,女儿国国王就说你下一站应该去黑风岭,所以第一套地址还是不变,但是第二套地址就变成了女儿国->黑风岭。就这样直到西天。
东土大唐->西天,这套地址是不变的。这就是源IP地址->目的IP地址。
女儿国->黑风岭(经过一座城池就会发生变化)。这就是源MAC地址->目的MAC地址。
所以这一座一座的城池就是路由器,通过唐僧的目的IP地址查路由表,然后辨别下一站应该去女儿国。所以是看目的IP进行路由的。而车迟国和女儿国最近,潜台词就是它们在一个局域网,而在局域网进行通信使用的是MAC地址。数据长距离传输本质上就是通过一个一个局域网进行传输的。
IP几乎不会变化,MAC地址一般只在局域网中有效。
4.4、跨网络传输
令牌环网提供一个令牌——其实就是一个数据,就比如今天在教室里有个水杯,谁持有水杯谁就能说话,今天你持有水杯说了一大堆,然后交给张三,这时候你就不能说话了,然后张三持有水杯可以说话,所以张三说了一大堆,然后再将水杯交给下一个,这就是令牌环网。在令牌环网中谁持有令牌就能发送数据,谁持有令牌才能访问令牌环网——这本质上就是锁。
路由器是工作在网络层的设备,在主机A看来,路由器是一台主机,在主机B看来也是如此。在主机A看来,主机A要将数据交给路由器,这就是一个以太网局域网通信的过程。在主机B看来,路由器要将数据交给主机B也是一个局域网通信的过程。主机A和主机B都有网络层,所以它们本身都有路由功能。路由器要和AB通信,横跨了两个不同的子网,所以这台路由器至少要有两张网卡和两种驱动程序。
用户主机也有路由功能,用户数据在向下交付到网络层,根据目的IP地址判断,当前主机也不知道目的IP地址是谁,但是它能知道这个IP地址和我一定不在同一个局域网,所以要将报文转发给路由器。那么如何知道路由器的MAC地址?你要上网就要先连接路由器,首次连接路由器的时候路由器会给你分配一个IP地址,同时你的主机也会记录下路由器的MAC地址。
用户的数据向下封装,所以会有源IP和目的IP地址,源MAC和目的MAC地址。交给路由器之后,路由器的网卡接受后向上解包,发现目的macLeft就是自己,所以继续向网络层交付,网络层根据目的IP地址,发现就在我的另一个局域网中,所以继续向下重新封装,源MAC:macRight,目的MAC:macB,然后发送给主机B。我们发现这个过程中,主机A发送给主机B可能需要经过很多个局域网,可能会经过很多个路由器,但是源IP和目的IP一直不变,而源MAC和目的MAC在每个局域网中都会发生变化。
网络层,全网同一层,拿到的报文是一样的,统一的。
所以,IP地址几乎是不变的,MAC地址一般只在局域网中有效。
全球有非常多的局域网通信标准,而这些不同的局域网现在也想通信了,该怎么办呢?——任何软件问题都可以通过新增一层软件层来解决,也就是网络层。通过网络层来屏蔽了底层的差异。
IP网络层存在的意义:提供网络虚拟层,让世界的所有网络都是IP网络,屏蔽最底层网络的差异。
所以用户A给用户B发送数据,是经过上面这样的不断经过一个又一个路由器,不断地解包和重新封装的过程。而逻辑上抽象我们可以认为主机A的网络层是经过无数个网络层然后交给主机B的网络层的。
5、Sokect编程预备
5.1、认识端口号
IP在网络中,用来标识主机的唯一性。
数据从主机A传输到主机B是目的吗?并不是,因为数据是给人用的。比如:聊天是人在聊天,下载是人在下载,浏览网页是人在浏览。
但是人是怎么看到聊天信息的呢?怎么执行下载任务呢?怎么浏览网页信息呢?通过启动的 qq,迅雷,浏览器。而启动的 qq,迅雷,浏览器都是进程。换句话说,进程是人在系统中的代表,只要把数据给进程,人就相当于就拿到了数据。
所以:数据传输到主机不是目的,而是手段。到达主机内部,在交给主机内的进程,才是目的。
发送数据就是:进程(用户) + 网络(OS)/主机 -> 网络(OS)/主机 + 进程(对端用户)。
而源IP和目的IP用来标识主机的唯一性,它是解决两端主机通信的问题。而对端主机收到数据后向上交付,怎么知道交付给哪个进程呢?——所以就需要端口号。
端口号是一个2字节16位的整数。
端口号用来标识一个进程,告诉操作系统,当前的这个数据要交给哪一个进程来处理。
IP地址用来标识主机的唯一性,端口号用来标识主机中进程的唯一性。所以IP地址+端口号能够标识全网唯一的一个进程。
今天我们起了两个进程:qq和抖音。QQ要访问就到QQ服务器,抖音去访问抖音服务器,而在客户端必须有端口来标识这两个进程。未来我可能受到QQ和抖音的消息,那么在未来到达传输层就可以通过端口来来区分这个消息应该给QQ进程还是给抖音进程,而不会给反了。
那么左边通过IP+端口可以标识全网唯一的一个进程,而右边通过IP+端口也可以标识全网唯一一个进程。
所以网络通信的本质就是进程间通信。
而我们把IP + 端口号称为Socket。
进程在我们看来就是一个一个的PCB,在操作系统内就要维护一个端口号的哈希表。所以就是一个数组,哈希表下标就是端口号。所以当底层报文通过目标端口直接在哈希表里面找,就可以找到进程,报文解包把数据拷贝到文件缓冲区里,上层进程就可以读取到数据了。
那么上层有没有可能数据来不及拿走呢?操作系统内有很多报文积压?上层的应用层进程可能还在处理数据来不及取,此时操作系统还在不断地接受数据,等待进程处理完了再来取数据。这你能想到什么?——这不就是生产者消费者模型吗。
端口号范围划分:
0 - 1023:知名端口号,HTTP、FTP、SSH等这些广为使用的应用层协议,他们的端口号都是固定的。
1024 - 65535:操作系统动态分配的端口号。客户端程序的端口号,就是由操作系统从这个范围分配的。
理解 “端口号” 和 “进程 ID”:
进程可以使用PID来标识唯一性,那么在网络这里直接使用PID标识进程不就行了吗?为什么还要有一个端口号呢?从技术上讲是可以实现的,但是这样会导致进程和网络强耦合,所以并没有这么做。
综上:
1、IP地址用来标识互联网中唯一的一台主机,port用来标识该主机上唯一的一个网络进程。
2、IP+Port 就能表示互联网中唯一的一个进程。
3、所以,通信的时候,本质是两个互联网进程代表人来进行通信, {srcIp,srcPort, dstIp, dstPort}这样的 4 元组就能标识互联网中唯二的两个进程。
4、所以,网络通信的本质,也是进程间通信。
5、我们把 ip+port 叫做套接字socket。
5.2、传输层的典型代表
我们要进行网络通信,本质就是访问网卡,而网卡属于硬件,被操作系统管理。用户无法直接访问网卡,必须贯穿协议栈,而网络属于操作系统的一部分,操作系统不相信任何人,所以就需要使用系统调用。
认识TCP协议:TCP是传输层协议,面向有连接的,提供可靠传输,面向字节流。
认识UDP协议:UDP是传输层协议,面向无连接,提供不可靠传输,面向数据报。
5.3、网络字节序
我们知道,内存有大小端之分。
什么是小端:数据的低位存放在低地址处,数据的高位存放在高地址处,这就是小端。
什么是大端:数据的高位存放在低地址处,数据的低位存放在高地址处,这就是大端。
现在进行网络通信,如果你是小端机器,数据发送给对方,而对方是大端机器,那对方进行数据解析的时候就反了。所以在网络中必须把大小端规定好。
网络规定:所有发送到网络上的数据都必须是大端的。
为使网络程序具有可移植性,使同样的 C 代码在大端和小端计算机上编译后都能正常运行,可以调用以下库函数做网络字节序和主机字节序的转换。
这些函数名很好记,h表示host,n表示 network,l表示 32 位长整数,s表示16位短整数。
例如htonl表示将 32 位的长整数从主机字节序转换为网络字节序,例如将IP地址转换后准备发送。
如果主机是小端字节序,这些函数将参数做相应的大小端转换然后返回。
如果主机是大端字节序,这些函数不做转换,将参数原封不动地返回。
我们常见的IP地址是:192.168.34.45,这种是字符串风格的IP地址,称为点分十进制。
而网络通信如果直接使用这种需要十几个字节,所以实际上网络通信是4字节IP地址。
如:struct { char p1; char p2; char p3; char p4; };
那么整数IP怎么转换为字符串风格IP呢?struct* ip = addr。
to_string(addr.p1) + “.” + to_string(addr.p2) + to_string(addr.p3) + “.” + to_string(addr.p4)
5.4、socket 编程接口
Socket常见API:
// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);
// 绑定端口号 (TCP/UDP, 服务器)
int bind(int socket, const struct sockaddr *address, socklen_t address_len);
// 开始监听 socket (TCP, 服务器)
int listen(int socket, int backlog);
// 接收请求 (TCP, 服务器)
int accept(int socket, struct sockaddr* address, socklen_t* address_len);
// 建立连接 (TCP, 客户端)
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
上面我们发现有一个叫做struct sockaddr的结构体。
套接字编程有很多种类型:
1、网络socket,既可以进行本地通信,又可以进行网络通信。
2、本地socket(unix域间socket),用来进行本地通信。
3、原始socket。
操作系统要提供系统调用,而套接字编程种类比较多,接口如果设计的比较多,而且这些接口还都具有相似性,这样设计就不好,所以把socket接口统一了。
而为了实现接口的统一性,定义了一个结构:strcut sockaddr。
你在使用socket进行通信无非就是要告诉操作系统:1、你的源IP和目的IP是多少。2、你的源端口号和目的端口号是多少。3、你想做本地通信还是网络通信。
如果使用网络通信,使用的是struct sockaddr_in。struct sockaddr_un是本地通信。本地通信是通过文件路径标识资源唯一性,就是管道。而C语言接口不支持重载,所以要想办法将它们统一,所以设计了一个struct sockaddr,只准你传struct sockaddr,不管你选择哪种通信方式,将来在传参的时候做一下强转就可以了。
虽然这里统一了,但是底层接口内部也必须区分清楚到底是网络通信还是本地通信。
所以规定这三个结构的起始两个字节16位用来表示网络通信还是本地通信。在接口内部通过访问结构的前两个字节判断是AF_INET还是AF_UNIX区分网络还是本地通信。