1. 网络协议
网络通信双方约定的一套标准,称为网络协议。
2. OSI 通信协议模型
- 应用层:要传输的内容
- 表示层:对数据加密
- 会话层:是否建立会话链接
- 传输层:传输方式(TCP、UDP)
- 网络层:数据的路由
- 数据链路层:数据在局域网内的传输
- 物理层:物理介质的连接
3. TCP/IP 模型
- 应用层:传输的数据
- 传输层:传输的方式
- 网络层:数据如何由一台主机到达另一台主机
- 网络接口层:接口电器特性及接口标准
4. 常见协议
4.1 应用层协议
- HTTP:超文本传输协议
- HTTPS:加密 HTTP 协议
- TFTP:简单文件传输协议
- FTP:文件传输协议
- DNS:域名解析协议
- TELNET:远程登录
- SMTP:邮件传输协议
4.2 传输层协议
UDP(用户数据报协议):
- UDP 传输简单
- UDP 占用资源比较小
- 不安全、不可靠
- UDP 是无连接的
TCP(传输控制协议):
- TCP 传输机制复杂
- 通信之前三次握手建立连接
- 通信过程中有传输确认机制
- 通信结束时通过四次挥手结束连接
- 掉线检测、滑动窗口、拥塞控制来完成对通信过程的管理
- TCP 占用资源较大
- 安全可靠
- TCP 是有连接的
4.3 网络层协议
- IPV4
- IPV6
- ARP/RARP
5. IPV4 协议
5.1 IP 地址
IP 地址由网络位 + 主机位构成。
- 网络位:局域网编号
- 主机位:该局域网内的第几台主机
管理员表示形式:192.168.0.175
内存中的表示形式:11000000.10101000.00000000.10101111
网络位不变,主机位全为 0 表示该 IP 地址所在的局域网编号:192.168.0.0
该局域网内最多可以容纳 256-2 台主机(除了网段号:网络位不变,主机位全为 0;除了广播地址:网络位不变,主机位全为 1)。
192.168.0.175 IP 地址在 192.168.0.0 局域网中,广播地址为 192.168.0.255。
局域网内部通信通过 MAC 地址完成。MAC 地址:每个网卡出厂都会有一个属于该网卡的唯一识别的地址,该地址不会冲突。
子网掩码:搭配 IP 地址来使用,用来区分网络位和主机位的。子网掩码是 1 的部分对应 IP 地址的网络位,子网掩码是 0 的部分对应 IP 地址的主机位。
5.2 IP 地址分类
IP 地址:192.168.0.175 11000000.10101000.00000000.10101111
子网掩码:255.255.255.0 11111111.11111111.11111111.00000000
192.168.0.175/24
| 类别 | 地址范围 | 子网掩码 | 管理规模 | 私有地址 |
|---|---|---|---|---|
| A 类 | 1.0.0.0 - 126.255.255.255 | 255.0.0.0 | 超大规模型网络 | 10.0.0.0 - 10.255.255.255 |
| B 类 | 128.0.0.0 - 191.255.255.255 | 255.255.0.0 | 大中规模型网络 | 172.16.0.0 - 172.31.255.255 |
| C 类 | 192.0.0.0 - 223.255.255.255 | 255.255.255.0 | 中小规模型网络 | 192.168.0.0 - 192.168.255.255 |
| D 类 | 224.0.0.0 - 239.255.255.255 | - | 用于组播和广播 | - |
| E 类 | 240.0.0.0 - 255.255.255.255 | - | 用于实验用途 | - |
公有 IP 地址:能够直接上互联网的 IP 地址。
私有 IP 地址:不能直接上互联网的 IP 地址。
6. 网络相关命令
6.1 查看网卡信息
bash
ifconfig
ifconfig -a
6.2 设置 IP 地址
1. NAT 模式
- Windows 有网,虚拟机就有网
- Windows 有独立的 IP 地址,Ubuntu 的地址是虚拟的
- 因为 Ubuntu 的 IP 地址是虚拟机的,所以不能作为服务器来使用(别人无法通过网络访问这台主机,但主机可以主动访问别人)
- 此模式使用场景:让 Ubuntu 能够上网,但无法作为服务器使用
2. 桥接模式
- Windows 和虚拟机都使用网卡,该网卡会有 2 个 IP 地址,一个供 Windows 使用,一个供 Ubuntu 使用
- Ubuntu 既可以访问别人,也可以在局域网中供别人访问
- 同一台设备(网卡)会占据 2 个 IP 地址,在需要账号登录的场景下,无法同时保证 Windows 和 Ubuntu 能够上网
3. 设置为桥接模式
- 将虚拟机设置为桥接模式
- 将虚拟机网卡桥接到无线网卡下
4. 配置 IP 地址(Ubuntu 18.04)
- 打开网卡配置文件
- 将网卡设置为 DHCP 模式
- 保存退出
- 重启网络配置
- 通过 ifconfig 查看 IP 地址
- 测试与百度是否连通
bash
sudo vim /etc/network/interfaces
bash
auto lo
iface lo inet loopback
auto ens33
iface ens33 inet dhcp
bash
ESC :wq
bash
sudo shutdown -r now
bash
ifconfig
ping www.baidu.com
5. 命令直接设置 IP 地址
如果以上方法均无法设置 IP 地址,可利用命令直接设置 IP 地址(注意:此命令过一段时间就无效了,所以需要隔一段时间就重新设置一次)。
bash
sudo ifconfig 网卡名 IP地址/24 up
sudo ifconfig ens33 192.168.0.125/24 up
7. UDP 通信
7.1 UDP 发端流程
- socket
- sendto
- recvfrom
7.2 函数接口
1. socket
c
int socket(int domain, int type, int protocol);
功能:创建一个用来通信的终端节点套接字
参数:
- domain:协议族 IPV4 AF_INET
- type:
- SOCK_STREAM:流式套接字 TCP
- SOCK_DGRAM:数据报套接字 UDP
- SOCK_RAW:原始套接字
- protocol:0 默认套接字类型对应的协议
返回值:成功返回新的文件描述符,失败返回 -1
2. sendto
c
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
功能:发送消息
参数:
- sockfd:套接字的文件描述符
- buf:发送数据空间的首地址
- len:发送数据的长度
- flags:属性,默认为 0
- dest_addr:目的地址空间的首地址
- addrlen:目的地址的长度
返回值:成功返回发送的字节数,失败返回 -1
3. struct sockaddr_in
c
struct sockaddr_in {
sa_family_t sin_family; /* 协议族 */
in_port_t sin_port; /* 端口号 */
struct in_addr sin_addr; /* IP地址 */
};
/* Internet address. */
struct in_addr {
uint32_t s_addr; /* address in network byte order */
};
4. htons
c
uint16_t htons(uint16_t hostshort);
功能:将本地字节序转换为网络的大端字节序
参数:hostshort:本地字节序
返回值:成功返回网络大端字节序
5. inet_addr
c
in_addr_t inet_addr(const char *cp);
功能:将字符串 IP 地址转换为网络的大端字节序二进制地址
参数:cp:IP 地址字符串首地址
6. bind
c
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
功能:将 IP 地址 + 端口号与套接字绑定
参数:
- sockfd:套接字文件描述符
- addr:绑定的 IP 地址空间首地址
- addrlen:长度
返回值:成功返回 0,失败返回 -1
注意:bind 只能绑定本机的 IP 地址,不能绑定别人的 IP 地址;如果一个端口号已经被占用,不能重复绑定。
7. recvfrom
c
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
功能:接收信息
参数:
- sockfd:套接字文件描述符
- buf:存放数据空间的首地址
- len:最多接收字符的个数
- flags:属性,默认为 0
- src_addr:存放发送端 IP 地址端口号空间的首地址
- addrlen:最多接收 IP 地址的长度
返回值:成功返回接收的字节数,失败返回 -1
8. inet_ntoa
c
char *inet_ntoa(struct in_addr in);
功能:将二进制大端字节序 IP 地址转换为字符串 IP 地址
8. 作业
编写 clientA.c 和 clientB.c 实现双方聊天功能。
- clientA.c 绑定 IP 地址 + 端口
- clientB.c 绑定 IP 地址 + 端口