海底光纤,搭卫星
90年代,马云去美国,回来就做了网页
互联网最早的是阿帕网,用于军工,后来不断普及到高校,企业
计算机是独立的,而计算机A的处理结果交给另外一台计算机,就需要软盘等硬件,需要人的参与,一般人的参与就慢了,生物信号和光电信号相比肯定慢,所以就出现了用线将多台计算机连在一起,使用一台计算机作为中转,其余计算机的处理结果交给这台中转计算机,再由中转计算机交给其它计算机
慢慢的,需要连接的电脑越来越多,一个学校,一个企业,到一个国家,多个国家,从局域网到广域网
人们看到背后巨大的经济价值,铺设海底光纤,搭建卫星
1.协议
协议是一种约定
包括硬件级别的协议和软件级别的协议 - 协议分层 - 软件分层
层状结构,比如继承
任何问题,都可以通过添加一层软件层来解决问题
假设主机A和主机B要通过网络进行通信,主机A给主机B发信息,首先主机A要能和路由器通信,之后要通过网络中的多个中间节点
这就引发了几个问题,主要还是因为物理距离变长(客观事实),引发新问题
- 数据如何在两个相邻的设备之间传递,网络通信最终转化成无数个相邻数倍通信的问题
- 目标主机定位和路径选择的问题
主机B所在的局域网肯定有多个主机,主机A发出的报文怎么找到主机B,路上有很多节点,从而有很多路径,要走哪一条?选择原则是什么?是通信时间越短越好吗? - 数据出现丢失/错乱怎么办
- 使用数据的目的,怎么处理数据
解决完上面的问题,千辛万苦送到了,那怎么处理呢?
网络通信,才能解决"人"的问题



集线器现在一般都集成在路由器内部
OS是C和汇编写的,部分协议栈被设计到OS内核中,协议栈也是C写的



举一个生活中的例子

2.网络传输基本流程
2.1 局域网通信
每台主机在局域网上,要有唯一的标识来保证主机的唯一性:mac地址,48bit,硬件固定,一张网卡,一个mac地址

主机A向局域网发送MAC帧,局域网内所有主机都能收到(类似教室内老师说话,所有学生都能听到),而MAC帧头部有src和dst也就是谁发的和给谁的信息,收到mac帧的主机会判断自己的mac地址和dst是否相同,相同则接收,主机E,不同则丢弃
但是存在一个问题,如果主机A和其它主机同时发送(类似有多个人同时说话,听不清),这时候发生碰撞,碰撞的主机进行休眠一段时间(这段时间,其它主机就可以发送了),重新发送
以太网碰撞域,任何主机都能进行碰撞检测+碰撞避免算法(从而维护任意一个时刻,只能被一个人使用=>原子性),局域网通信就是基于碰撞检测和碰撞避免不断重试的过程
从系统的角度看,以太网看作所有主机(可以看作线程,因为执行发生数据的最终还是落在执行流上)共享的资源,但需要保护起来,也就是临界资源

主机A为什么给主机E发数据?用户的需求
局域网和以太网什么关系?还有其它局域网吗?
令牌环网,有一个令牌,谁拿到令牌,谁就可以发送数据,令牌会在主机间轮询,需要发送数据,在轮到本主机的时候,就拿令牌,发数据,发完释放令牌,令牌去下一个主机,从系统角度看,令牌就是锁,局域网就是锁保护的临界资源
科学家们根据声音/光的传播需要介质,判定太空中也有光传播的介质,只不过我们看不到,就起了个名字叫以太,研究后发现确实没有,程序员就把以太拿来命名局域网
局域网负责将主机A在数据链路层的数据交给主机B的数据链路层,数据来自应用层,由用户定制



也是协议栈这个名字的来源
举一个例子,当A和B打电话的时候,A和B都以为自己和对方是直接通信,但并非如此,A的声音作为用户的数据,经过用户层、传输层、网络层、数据链路层的逐层封包,最后由网卡传输信号,达到B所在主机的网卡,经过数据链路层、网络层、传输层、应用层逐层解包,最后传送给用户,B听到来自A的声音,但逻辑上,认为A和B直接通信

每层发出的数据和每层收到的数据是一致的,比如传输层,可以将发送方传输层以下对传输层数据做的封包,和接收方传输层以下解包之后把数据交给传输层看作黑盒操作,传输层不管,达到解耦,就好像打电话时对方说话,因为数据传输和处理快到我们感知不到,在感官上,我们认为和对方直接通信;对于网络协议栈的各层来说也是这样的,由于下层的封装和解包对于该层是透明的,所以发的数据和收的数据一致,逻辑上认为层与层之间直接通信
对于接收方主机的协议栈各层,要解决两个问题
- 报头和有效载荷分离的问题
- 有效载荷向上交付给哪一个协议
应用层有HTTP,HTTPS,DNS,DHCP等
传输层有TCP,UDP等
网络层有IP,ICMP,IGMP等
数据链路层有ARP,RARP等
2.2 封装
协议本身是一个结构体类型,报头就是结构体变量
在内存中给此次要传输的数据分配缓冲区,首先将要传输的数据拷贝到缓冲区,接着是应用层报头,传输层报头,数据链路层报头
报头根据长度是否固定分为固定长度报头和变长的报头
而封装报头的本质,就是在报文头部,拷贝结构体变量

那么对于第一个问题,报头和有效载荷分离的问题,以太网mac帧的长度是固定的,而IP/TCP的报头中都有各自首部的长度,UDP的报头有总长度,UDP报头长度是固定的,除了报头就是有效载荷,自然能分离

对于第二个问题,交给上层时交给哪一个协议呢?比如以太网mac帧有类型,不同的类型表征不同的IP协议,当发送方IP数据报交付给数据链路层时,肯定会指明是哪个具体的IP协议(类似函数调用传参),那数据链路层在mac帧中就可以设置相关字段,等到接收方将mac帧交给网络层时,根据字段值交给对应的网络协议,其它层也是类似
2.3 IP地址和Mac地址

IP侧重点:标识公网中唯一一台主机
一台主机有两个地址,IP和mac,
举个例子,唐僧取经,每到一个地方就会说,贫僧从东土大唐而来,到西天取经,但唐僧不知道怎么去,因为之前没去过,所以就路上挨个问询,到车迟国的时候问国王得知下一站是女儿国,到了女儿国

IP用于定位主机,IP提供长远目标,是路径选择的依据
MAC地址作为当前或者下一跳地址,解决的事局域网转发的问题
比如身份证号码可以在全国标识你的唯一性,但是学号用于在一个范围内标识你的唯一性,也是为了解耦,如果在学校内随时随地都用身份证号标识学生的唯一性,万一身份证号发生重大变更,当然一般不会有,那么学校的相关系统也要大改,而用学号,如果身份证号码发生变化,学号不变,这个标识学生唯一性的key就不会变,不会受影响
之前看的是在局域网内部的数据传输,接下来看一下不同局域网之间的数据传送,首先协议栈从上到下会封装发送方的数据,在网络层,会检测目的IP并不是局域网内部的,但直接交给路由器,目的mac地址是路由器的mac地址,经过网卡传输给路由器,路由器也是层状协议,不过只到传输层,数据链路层解包将数据交给路由器,路由器根据目标IP地址判断应该从哪一个接口转发到哪一个局域网,接着网络层进行封包,交给数据链路层,数据链路层根据自身所在局域网也就是令牌环网的协议进行封包,接着根据目的mac地址进行传送,剩下的就是向上交付的过程
可以看到,不同局域网的主机是可以通过路由器通信的
当然这是比较简单的情况,中间只隔了一个路由器

其实可以看出来,网络层都有路由的功能,对于非路由器也就是主机的网络层来说,路由的能力是路由给局域网内的主机还是给路由器(交由路由器路由到其它局域网到指定主机)


IP地址在整个路由过程中,一直不变(有些问题,后面修正说法)
Mac地址一直在变
目的IP地址是一种长远目标,Mac地址是下一阶段目标,目的IP是路径选择的重要依据,mac地址是局域网转发的重要依据

2.4 端口号
端口号是传输层协议的内容,是一个2B也就是16位的整数,范围是0~65525,
0 ~1023:知名端口号,比如HTTP,FTP,SSH等广为使用的应用层协议,端口号都是固定的
1024~65535:OS动态分配的端口号,客户端程序的端口号,OS就是从这个范围内分配的
把数据从主机A传送到主机B是网络通信的手段,目的是让用户通信,代表用户的是启动起来的程序,也就是进程

那传输层怎么知道把数据交给哪一个进程呢?每个要进行网络通信的进程都会分配端口号,一般服务器的端口号是固定的,方便客户端发起请求,而发起请求的客户端进程会动态分配和释放端口号,发起请求的报文内容会携带端口号,用于和服务的建立连接
端口号

pid已经可以标识进程的唯一性,为什么还要有端口号
一方面,不是所有进程都要进行网络通信,使用pid如何区分哪些进程要通信,哪些进程不需要通信,有端口号之后,谁拥有端口号,谁就需要进行进程间通信;另一方面就是解耦,一旦pid有什么变化,端口号不需要做大的变动
也实现专车专用
一个是系统概念,一个是网络概念,端口号是强标识
而ip和port的概念类似于,10086和内部某个话务员的工号
OS如何把收到的数据转发给对应端口进程?
OS会受到很多份报文,最后到达传输层,肯定有描述这些报文的数据结构,内存中开辟了空间保存报文,开辟了空间存储描述报文的数据结构,还要管理这些数据结构,可以用双向链表,同时以端口号作为key,建立哈希表,索引发给对应端口号进程的报文
那如何把网络数据交给对应端口号的进程?
linux下一切皆文件,网卡也是文件,有对应的文件描述符fd,内容指向struct file,file内部有文件属性以及指针指向对应的文件缓冲区,存储的就是收到的网络数据,接着,把缓冲区的内容拷贝到进程虚拟地址空间用户区开辟的缓冲区,进程就拿到了数据(有些不准确,后续修正)
IP地址用来标识互联网中唯一一台主机,port端口号用来标识主机中唯一一个进程,IP+Port标识互联网中唯一一个进程,通信的本质是两个互联网进程代表人来通信,{srcIP, srcPort, dstIP, dstPort}四元组可以用来标识互联网中唯二进程,网络通信的本质是进程间通信,system V标准只能用于本地进程通信,POSIX可以用于本地/网络通信
ip+port也就是socket,套接字

3.传输层

由于UDP在数据发生丢失时不进行重传,所以不需要保存已发送但未应答的数据,也没有设立应答机制,因为要做的事情少了,所以速度快,用于对可靠性要求没那么高的场景,比如直播,视频流等
而TCP在数据发生丢失时需要进行重传,需要保持已发送但未应答的数据,速度稍慢一些,现有的场景大部分用的都是TCP,比如银行转账等
4.网络字节序
OS内部的字节序分为大端和小端,小端是低权值位字节在低地址,"小小小",大端是高权值位字节在低地址,和人类视角一致

但是所有的机器大小端并不统一,假设先发送低地址,后发送高地址,机器A是小端,发的就是44332211,接收方主机B拿到之后先拿低地址,放在低地址,从低地址到高就是44332211,假设机器B是大端,那收到的就是44332211,和发送数据并不一致,所以就出现了问题,本来这个问题是不存在的,但是引入网络通信后就存在了,
如何解决呢?一般网络中发送的都是大端,而且一般不需要我们转,系统提供的有函数,只有极少数情况下才需要我们自己转,htonl就是把32位的整数转为大端(如果本就是,什么都不做,否者进行转化)

5.socket网络编程
5.1 概念和接口
socket网络编程的设计者,也希望支持本地ipc

由于socket的设计者既想支持网络通信,也想支持本地通信,还能支持raw socket,网络通信需要ip地址+端口号,本地通信需要文件路径,原始套接字需要其参数,参数个数和数量不同,接口肯定不能相同,接口不同,就导致学习成本增加,于是就想通过增加一个中间层,来统一参数的传递,并统一函数名,降低学习成本



bind传的是struct sockaddr的地址,struct sockaddr_in和struct sockaddr_un以及struct sockaddr开始的字段都是16位数据,根据传入sockaddr前16位是AF_INET决定是网络通信,是AF_UNIX决定是域间通信,如果是网络通信,定义struct sockaddr_in,传参时强转即可,内部使用时再强转使用->访问成员,其实C++的多态估计也是这么设置的,sockaddr是基类,另外两个是子类


点分十进制ip地址和4字节IP地址转化

sockfd也就是当前socket绑定的文件描述符,flags设为0也就是阻塞读取,如果没有数据就阻塞,类似scanf,其实本身是阻塞在系统调用,那ssize_t要么读取到数据>0,要么读取失败,<0


sendto 第一个参数是要通过哪一个文件描述符进行发送,本质是把用户地址空间的内容拷贝到文件描述符对应的缓冲区,最后由系统转发,第二个参数是发送什么数据,数据起始地址,第三个是长度,第4个位0就是阻塞式发送,第4个是发给谁,目的主机的socket信息,第5个是第四个参数的长度
总而言之就是1.发送什么数据,buf 2.发给谁,dest_addr 3.如何发送 sockfd,通过文件描述符进行发送
client需要有自己的IP和Port信息,但是不能显示bind,因为不同客户端是独立的,如果显示bind就可能出现冲突,比如淘宝和抖音都绑定端口号8080,如果淘宝先启动,抖音就启动不了
端口号只需要具有唯一性即可,具体数值不重要,client一般会采用随机端口的方式,由OS自主选择,udo client首次发送数据时,OS底层会隐式自动获取随机端口,bind+Port+IP
client需要知道服务端的IP和Port,这些信息是内置到client内部的
5.2 测试代码echoserver
5.2.1 内网测试版本



测试结果


如果使用127.x.x.x地址可以通信,说明客户端和服务端没有问题,如果不能通信,可能是网络的问题
通过查询可以看到127.0.0.1是本地环回地址

5.2.2 公网测试版本
5.2.2.1 Linux和Linux通信
绑定购买云服务器分配的公网ip失败

一台主机可能有多个ip地址,如果主机装了多个网卡,还会增加多个IP地址

下面也可以看到多个IP地址,因为任何主机都可以连有线/无线,根本原因是不同路由器分配多个IP

内网IP指本主机,局域网IP是指购买云服务器内部有多台主机形成一个局域网,局域网IP标识主机在局域网内部的唯一性,公网IP在服务器内部是查不到的,报文会转发到公网IP


测试结果发现,客户端发向公网IP的报文发不出去,内网和局域网IP都可以

如果绑定单一IP地址,可以看到只能接收发给绑定IP地址的报文



网络发来的网络字节序IP地址->点分十进制字符串格式

获取客户端IP和端口号

其实我们发的数据都是先到服务器入口IP地址,会有防火墙等进行阻拦,正常数据都会通过

如果要./client 公网IP 8080 也可以通信的话,在云服务器的防火墙添加规则,UDP+8080

客户端静态编译,可以避免对动态库的依赖

把生成的客户端程序通过sz发送到桌面

通过社交网络传递,多人收到
通过rz从桌面获取程序,或者拖拽等方式,运行客户端程序,就可以通信,下图是一台centos虚拟机通过公网IP进行通信

如果多人收发,就可以实现群聊
客户端收到数据,也会获取发送方的socket信息,如果发送方想将数据发送给指定的某个人,可以将数据转发给某个用户(有唯一标识),实现私聊
netstat可以查看已经启动的服务,打印与网络和通信(套接字相关信息)

-a所有(域间/tcp/udp) -n 以数字形式 -u UDP -t tcp -p显示进程信息
查看udp
下面端口号为8080就是自行设定的服务端,全零表示任意IP,进程名因为长度限制截断

查看tcp,可以看到刚开始有的PID为-,因为权限限制,下面sudo提权后可以看到PID

我们可以用ssh登录是因为服务器上启动端口为22号的服务,我们本质上是和该服务通信,所有的操作都会被该服务解释为shell命令,返回执行结果

5.2.2.2 Linux和Windows通信
上面是Linux和Linux机器通信,那么Windows呢?因为传输层和网络层内嵌于OS,核心接口是一致的,可能不同OS对一些数据类型进行封装不影响大体使用
问题是可能编码方式不同,Windows发汉字,Linux这边是乱码

如果在windows上用qt或者easyx等简单的图形化界面,linux收集多个用户的数据和用户信息,就可以实现简单的聊天,游戏等

5.3 Dict


EchoServer只做了些许改动


测试

- 计算机技术和()是计算机网络产生于发展的两个最基本的因素
A.电话
B.通信协议
C.线路
D.各种协议
B
- 用于域名解析的协议是()
A.HTTP
B.DNS
C.FTP
D.SMTP
B
- ICMP报文通过()协议来传输
A.UDP
B.TCP
C.IP
D.ARP
C
- 下列不属于传输层的协议是()
A.TCP
B.UDP
C.SMTP
D.OSPF
C
C.应用层
- 以下关于网络协议分层说法不正确的是()
A.表示层一项重要的工作就是网络标准数据格式的转换
B.会话层负责管理传输层以下的分层
C.数据链路层是地址管理和路由选择
D.传输层管理两个节点之间的数据传输
C
-
以下关于网络协议分层理解正确的是()(多选)
A.网络协议分层使网络使用更加复杂,不利于人们的使用
B.OSI模型分为 7层,自下而上为,物理层,数据链路层,传输层,网络层,会话层,表示层,应用层
C.网络协议分层后每层利用紧邻的下层服务,更容易记住各层的功能
D.人们可以很容易的讨论和学习协议的规范细节
-
传统交换机和路由器分别运行在OSI参考模型的()
A.数据链路层和网络层
B.网络层和传输层
C.传输层和数据链路层
D.物理层和网络层
A
- OSI参考模型中,()提供了差错报告,网络拓扑结构的功能
A.网络层
B.传输层
C.数据链路层
D.物理层
C
- 在OSI模型当中,第N层和其上的N+1层的关系是()
A.N层为N+1层提供服务
B.N+1层将从N层接的信息增加一个头部
C.N层利用N+1层的提供的服务
D.N层对N+1层没有任何作用
A
- How long is a MAC address? ( )
A.4 bytes
B.6 bytes
C.8 bytes
D.10 bytes
B
- 以下有关MAC地址意义和作用描述错误的是()
A.MAC地址与网络无关
B.在网卡出厂时就确定了, 不能修改. MAC地址通常是唯一的
C.MAC地址用来识别数据链路层中相连的节点
D.一台计算机只能有一个MAC地址
D
- 下列IP地址和MAC地址说法错误的是()
A.IP地址的分配是基于网络拓朴,MAC地址的分配是基于制造商
B.IP地址应用于OSI第三层,即网络层,而MAC地址应用在OSI第二层,即数据链路层
C.数据链路层协议可以通过MAC地址使数据从一个节点传递到相同链路的另一个节点上
D.一个MAC地址只能对应唯一一个IP地址
D
- IP数据报的收发方进行跨网投递时,发送方需利用ARP协议获取哪些信息()
A.接收方IP地址的MAC地址
B.发送方本网段路由器对应端口的MAC地址
C.接收方本网段路由器对应端口的MAC地址
D.发送方IP地址的MAC地址
B
- A、B两个网络,IP均为静态分配,且IP段不同。当一台主机从一个A网络移到B一个网络时,以下说法正确的是()
A.必须改变它的IP地址和MAC地址
B.必须改变它的IP地址,但不需改动MAC地址
C.必须改变它的MAC地址,但不需改动IP地址
D.MAC地址、IP地址都不需改动
B
- OSI的哪一层通常同时使用报头和报尾进行封装()
A.网络
B.传输层
C.数据链路层
D.表示层
C