文章目录
- 协议
- 局域网通信
- IP 地址
- 网络通信的本质
- tcp 和 udp 协议
- 网络字节序
- 网络主机数据转化接口
协议
协议:收到数据后,多出来的那一部分,也叫一种 “约定”,一整套的自硬件到软件,都有协议,需要有人定制,也需要有人实现
当通信距离边长后,如何保证将数据交给下一跳主机,如何定位目标主机,如何处理报文出错,如何使用送达的数据等问题,都需要对应的协议
网络的层协议:和软件的层状结构一样,实现了各个部分代码的解耦,更容易维护,只需要考虑各个子问题即可。
网络协议一般叫:TCP/IP 协议,是在内核中实现的
网络编程:用户在操作系统的用户层使用系统调用,来实现网络层的功能
网络库:对网络层的系统调用进行封装,简化开发流程
任何操作系统都必须基于 OSI 标准实现网络协议栈,所以在不同的系统中,网络调用接口大同小异
报头使用C语言描述的结构体,client 和 server 之间是,都是可以识别这个报头的,因为client 和 server 描述报头的源代码都是一样的。
局域网通信
局域网通信:在同一个局域网中,两台主机是可以直接通信的,(局域网中建房间,玩游戏)
原理:两台主机在局域网中通信,局域网中所有主机都能收到消息,只不过通过 Mac 地址(网卡地址)来区分谁接受,其他不接收的主机会选择将消息直接丢弃掉
但有可能同一时刻,局域网中由多台主机在同时发消息,就可能会形成数据碰撞(丢包),那么发送方主机就会执行碰撞避免算法(休息一会再重发)
ifconfig:可查 Linux 主机的 Mac 地址(Mac只在局域网内部有效)
要正确的发送消息,再同一时刻,只允许一台主机在局域网中发消息,因此,局域网中的设备少,越安全,局域网中消息是否能发送成功是基于概率的,因此也叫 以太网(例如运动会操场上,消息发不出去一直丢包,就是因为几千人都访问的是附近同一个基站,而当操场上只有几个人的时候,消息特别流畅)
用系统的观点:局域网就是一个临界资源,主机在局域网出往另一台主机发送消息就是访问临界区代码,碰撞检测和碰撞避免、重发就是完成互斥访问,维护临界资源,单独发送,就是独占网络资源
用户之间通信时,消息在双方两台主机上,都要贯穿协议栈(软件->硬件 ——> 硬件->软件)
封装报头:在自己拿到的报文的基础上,添加同层协议的报头
每层协议都会封装自己对应的报头,也要考虑如何将收到的报文中,报头和有效载荷进行分离,如何将自己的有效载荷,交给上层的协议。
IP 地址
Linux 查看 ip 地址:ifconfig
windows 查看 ip 地址:ipconfig
整个ip 地址的范围:[0,255].[0,255].[0,255].[0,255]
,也叫点分十进制
在语言视角,这种点分十进制的 ip 地址,C++种可以使用字符串来表示
IP 地址分为公网ip
和 内网ip
,两个 ip 地址加起来,才是所有的 ip 地址,一般在 Linux 或 windows 上直接见到或查到的 ip 地址,都是内网ip
,但如果要使自己的服务被别人看到,就要使这个服务或对用的服务器具备公网ip
一般来说,ip地址表示公网 ip,用来表示互联网种唯一的一台主机,也可以表示局域网种唯一的一台主机
实际网络通信时只需要4个字节即可表示一个网络 ip,8* 4 = 32,32个比特位就能表示任意一个网络 ip,占用的字节数较少
那么如何将整形存储的ip地址转化为便以阅读的点分十进制这种字符串风格的ip地址呢?
ip地址
和 Mac地址
的区别:
ip 地址是永远不变的,在互联网中唯一,而 Mac地址是在局域网中不变的,但出了局域网后会变
Mac 地址意义:标识主机唯一性,用于局域网通信
IP 地址意义:帮助用于路径选择,目标ip
同层协议要发的,就是同层协议要收的!!
在 ip 层往下,报头在变,而ip层往上是一样的,因此也叫网咯ip地址
相当于在全球所有主机层面上,搭建了一层软件层,通过ip地址,就可以屏蔽底层所有局域网通信的网络差异了
网络通信的示意图:
网络通信的本质
网络之间的通信,本质上就是进程间通信
对双方主机的两个进程而言,需要先将数据发送到对方的主机(ip地址),再找到指定的进程(port:端口号),就能实现通信
ip地址用来标识互联网中唯一的一台主机;port端口号用来标识该指定机器中进程的唯一性
那么(ip, port) 则可以用来表示互联网中唯一一个进程,ip + port 也叫网络套接字 socket
如何理解port:
一个端口号和一个进程相绑定,一个进程可以绑定多个端口号,反之则不可以。
那么为什么不用进程pid来表示网络中进程的唯一性呢?
为了其他的进程模块和网络进行解耦(万一pid的规则变化,网络部分也不受影响),port是专门用于网络通信的
tcp 和 udp 协议
tcp 协议常用于可靠通信,适用于对数据要求比较高的场景(如游戏,传输重要文件等),复杂
udp 协议用于不可靠通信,适用于允许数据偶尔出现差错的场景(如体育赛事直播等),简单,快
这两个协议没有好坏之分,只是应用场景不同,如果不确定使用哪个的时候,就要 tcp,毕竟复杂一点比丢包好
网络字节序
机器有大小端之分,大小端机器存储数据方式不同。大端是“正着存储”的,可读性较好,因此在网络传输时规定,所以到达网络的数据,必须时大端存储的,因此,如果是小端机,收发数据到网络时需要先转化为大端
网络主机数据转化接口
ip 地址为4个字节,使用 uint32_t,port 为2个字节,使用 uint_16
htonl、htons 是转网络,ntohl、ntohs 是转主机数据,使用这些接口可以自动识别机器的大小端,并将数据转化为需要的大小端数据。
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uintl6_t ntohs(uint16_t netshort);