网络问题与基础理论

📱 虚拟机网络修复

当虚拟机突然没有网络标志时,可以使用以下命令快速修复:

bash 复制代码
nmcli network off
nmcli network on

这两个命令会重启网络管理器服务,通常可以解决临时的网络连接问题。

🌐 网络基础理论

1. 认识网络(了解)

网络:指多台设备之间进行通信和资源共享的系统。现代网络技术使得不同地理位置的计算机能够相互连接和交换数据。

Internet发展史:从ARPANET到现代互联网的演进过程。

2. IP地址详解

2.1 基本概念
  • IP地址:Internet中主机的唯一标识符
  • 通信前提:Internet中的主机要与别的机器通信必须有一个IP地址
  • 地址长度:IPv4为32位,IPv6为128位
  • 表示形式:常用点分十进制形式,如192.168.1.217,最终都会转换为32位无符号整数
  • 地址分类:A、B、C、D、E五类
2.2 IP地址二级划分

二级划分公式:IP地址 = 网络号 + 主机号

  • 网络号:标识设备所在的网络段(局域网)
  • 主机号:标识在本网段内的具体设备ID,同一局域网内不能重复


IP地址取值范围
类别 地址范围 用途说明
A类 1.0.0.0 ~ 126.255.255.255 大型网络,政府机构等
B类 128.0.0.0 ~ 191.255.255.255 中型网络,大学、大型企业
C类 192.0.0.0 ~ 223.255.255.255 小型网络,小型企业、家庭
D类 224.0.0.0 ~ 239.255.255.255 组播地址(Multicast)
E类 240.0.0.0 ~ 255.255.255.255 保留地址,实验和研究使用
2.3 特殊地址

以下地址不会分配给主机使用:

1. 网络地址

用于标识网络的地址,有效网络号,主机号全为0。

示例转换

  • 192.168.30.182 → 192.168.30.0
  • 128.1.2.3 → 128.1.0.0
  • 12.1.2.5 → 12.0.0.0
2. 广播地址

用于给局域网内所有主机发送数据,有效的网络号,主机号全为1。

示例转换

  • 192.168.30.182 → 192.168.30.255
  • 128.1.2.3 → 128.1.255.255
  • 12.1.2.5 → 12.255.255.255
3. 其他特殊地址
  • 0.0.0.0:在服务器中表示监听本机上所有的IPv4地址,接受来自任意源IP地址的数据包,常用于服务器程序监听所有网络接口的连接请求。
  • 127.0.0.1:回环地址/本机地址,一般用于测试。所有发往该类地址的数据包都应该被loop back原样送回,即当在计算机上访问127.0.0.1时,实际上是在与自己进行网络通信。
练习

问题:C类地址,同一网段最多可以连接多少个主机?

答案:254个(排除网络地址和广播地址)

2.4 子网掩码

作用:将IP地址划分为网络地址和主机地址两部分。

特点
  1. 子网掩码长度和IP地址长度完全一样,由32位二进制组成
  2. 网络号全为1,主机号全为0
默认子网掩码
  • A类:255.0.0.0
  • B类:255.255.0.0
  • C类:255.255.255.0
练习

问题:子网掩码255.255.255.0,该网段可以容纳多少台主机?

答案:254台

计算公式
  • IP地址 & 子网掩码 = 网络地址
  • IP地址 & ~子网掩码 = 主机号
2.5 三级划分
  • 二级划分 = 网络号 + 主机号
  • 三级划分 = 网络号 + 子网号 + 主机号

三级划分的子网掩码:网络号和子网号都是1,主机号是0。

子网划分练习

场景:某公司有四个部门:行政、研发1、研发2、营销,每个部门各40台计算机接入公司局域网交换机。如果要在192.168.1.0网段为每个部门划分子网,子网掩码应该怎么设置?每个子网的地址范围分别是什么?(4个部门之间不能通信)

分析

  1. 192.168.1.0属于C类地址
  2. 默认子网掩码:255.255.255.0
  3. 划分4个网段需要将2位二进制从主机号划分成子网号(2²=4)
  4. 高两位分别可以是:00、01、10、11
  5. 三级划分后的子网掩码:255.255.255.192(二进制:11111111.11111111.11111111.11000000)

各部门地址范围

部门 二进制范围 十进制范围(去除网络地址和广播地址)
部门1(行政) 192.168.1.00 000000 ~ 192.168.1.00 111111 192.168.1.1 ~ 192.168.1.62
部门2(研发1) 192.168.1.01 000000 ~ 192.168.1.01 111111 192.168.1.65 ~ 192.168.1.126
部门3(研发2) 192.168.1.10 000000 ~ 192.168.1.10 111111 192.168.1.129 ~ 192.168.1.190
部门4(营销) 192.168.1.11 000000 ~ 192.168.1.11 111111 192.168.1.193 ~ 192.168.1.254

补充:DNS(域名系统)

由于使用IP地址来指定计算机不方便人们记忆,且输入时容易出错,因此使用字符表示网络中计算机名称的方法应运而生。这种命名方法就像每个人的名字,这就是域名(Domain Name)

DNS相关概念
  • 域名服务器(Domain Name Server):用来处理IP地址和域名之间的转换
  • 域名系统(Domain Name System,DNS):将域名翻译成IP地址的软件系统
  • 特性:一个域名可以绑定多个IP地址
  • 公共DNS:可以在网络中配置自己的DNS服务器,如114.114.114.114、8.8.8.8
域名结构

以域名www.baidu.com.cn为例,从右向左看:

  1. cn:高级域名,也叫一级域名,通常分配给主干节点,取名为国家名,cn代表中国
  2. com :网络名,属于二级域名,通常表示组织或部门。中国互联网二级域名共40个:
    • edu:教育部门
    • com:商业部门
    • gov:政府部门
    • mil:军队
    • 等等
  3. baidu:机构名,属于三级域名,表示百度公司
  4. www:万维网(World Wide Web),也叫环球信息网,是一种特殊的信息结构框架

🌍 网络模型

3.1 网络体系结构

网络采用分而治之的方法设计,将网络的功能划分为不同板块,以分层的形式有机组合在一起。

  • 每层实现不同的功能,其内部实现方法对外部其他层次来说是透明的
  • 每层向上层提供服务,同时使用下层提供的服务
  • 网络体系结构即指网络的层次结构和每层所使用协议的集合

两类非常重要的体系结构:OSI模型与TCP/IP模型

3.2 OSI七层模型

OSI模型是最理想的参考模型,分为七层:

  1. 物理层:传输的是bit流(0与1的数据),物理信号,没有格式
  2. 数据链路层:格式变为帧(把数据分成包,一帧一帧的数据进行发送)
  3. 网络层:路由器中有算法,IP协议(主机到主机),路由转发
  4. 传输层:端口号,数据传输到具体哪个进程程序(端到端)
  5. 会话层:通信管理,负责建立或断开通信链接
  6. 表示层:确保一个系统应用层发送消息可以被另一个系统的应用层读取,编码转换,数据解析,管理数据加密、解密
  7. 应用层:指定特定应用协议,文件传输,文件管理,电子邮件等

记忆口诀:物→链(联)→网→输(叔)→会→示(使)→用

3.3 TCP/IP四层模型

各层功能
  • 网络接口层和物理层:屏蔽硬件差异(驱动),向上提供统一的操作接口
  • 网络层:提供端对端的传输,可以理解为通过IP寻址机器
  • 传输层:决定数据交给机器的哪个任务(进程)去处理,通过端口寻址
  • 应用层:应用协议和应用程序的集合

3.4 常见网络协议

层次 协议 说明
网络接口和物理层 PPP 拨号协议(老式电话线上网方式)
网络接口和物理层 ARP 地址解析协议,IP→MAC地址转换
网络接口和物理层 RARP 反向地址转换协议,MAC→IP地址转换
网络层 IP(IPv4/IPv6) 网络互联协议,负责数据包的路由和转发
网络层 ICMP Internet控制消息协议,用于网络诊断和错误报告
网络层 IGMP Internet组管理协议,用于组播通信
传输层 TCP 传输控制协议,面向连接、可靠的字节流服务
传输层 UDP 用户数据报协议,无连接、不可靠的数据报服务
传输层 SCTP 流控制传输协议,结合TCP和UDP的优点
应用层 HTTP/HTTPS 超文本传输协议/安全超文本传输协议
应用层 FTP 文件传输协议
应用层 SMTP/POP3/IMAP 电子邮件相关协议
应用层 DNS 域名系统,域名与IP地址转换
应用层 DHCP 动态主机配置协议,自动分配IP地址

🔌 SOCKET编程

4.1 Socket基本概念

**Socket(套接字)**是网络通信的端点,是应用层与传输层之间的接口。它提供了进程间通信的机制,允许不同主机上的进程通过网络进行数据交换。

Socket通信模型
  • 面向连接的Socket:基于TCP协议,提供可靠的数据传输
  • 无连接的Socket:基于UDP协议,提供快速但不保证可靠的数据传输

4.2 Socket通信流程

TCP Socket通信流程
  1. 服务器端
    1. 创建Socket
    2. 绑定IP地址和端口
    3. 监听连接请求
    4. 接受客户端连接
    5. 收发数据
    6. 关闭连接
  2. 客户端
    1. 创建Socket
    2. 连接服务器
    3. 收发数据
    4. 关闭连接
UDP Socket通信流程
  1. 服务器端
    1. 创建Socket
    2. 绑定IP地址和端口
    3. 接收数据
    4. 发送数据
    5. 关闭Socket
  2. 客户端
    1. 创建Socket
    2. 发送数据
    3. 接收数据
    4. 关闭Socket

4.3 Socket编程示例(C语言)

TCP服务器端示例
c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 8888
#define BUFFER_SIZE 1024

int main() {
    int server_fd, client_fd;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_len = sizeof(client_addr);
    char buffer[BUFFER_SIZE];
    
    // 1. 创建Socket
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd == -1) {
        perror("socket创建失败");
        exit(EXIT_FAILURE);
    }
    
    // 2. 绑定地址和端口
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);
    
    if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("绑定失败");
        close(server_fd);
        exit(EXIT_FAILURE);
    }
    
    // 3. 监听连接
    if (listen(server_fd, 5) < 0) {
        perror("监听失败");
        close(server_fd);
        exit(EXIT_FAILURE);
    }
    
    printf("服务器启动,等待客户端连接...\n");
    
    // 4. 接受客户端连接
    client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &client_len);
    if (client_fd < 0) {
        perror("接受连接失败");
        close(server_fd);
        exit(EXIT_FAILURE);
    }
    
    printf("客户端连接成功:%s:%d\n", 
           inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
    
    // 5. 接收数据
    memset(buffer, 0, BUFFER_SIZE);
    int bytes_received = recv(client_fd, buffer, BUFFER_SIZE - 1, 0);
    if (bytes_received < 0) {
        perror("接收数据失败");
    } else {
        printf("收到客户端消息:%s\n", buffer);
        
        // 6. 发送响应
        char response[BUFFER_SIZE];
        snprintf(response, BUFFER_SIZE, "服务器已收到:%s", buffer);
        send(client_fd, response, strlen(response), 0);
    }
    
    // 7. 关闭连接
    close(client_fd);
    close(server_fd);
    
    return 0;
}
TCP客户端示例
c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 8888
#define BUFFER_SIZE 1024

int main() {
    int sockfd;
    struct sockaddr_in server_addr;
    char buffer[BUFFER_SIZE];
    
    // 1. 创建Socket
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("socket创建失败");
        exit(EXIT_FAILURE);
    }
    
    // 2. 设置服务器地址
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr);
    
    // 3. 连接服务器
    if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("连接服务器失败");
        close(sockfd);
        exit(EXIT_FAILURE);
    }
    
    // 4. 发送数据
    char *message = "Hello Server!";
    send(sockfd, message, strlen(message), 0);
    
    // 5. 接收响应
    memset(buffer, 0, BUFFER_SIZE);
    int bytes_received = recv(sockfd, buffer, BUFFER_SIZE - 1, 0);
    if (bytes_received < 0) {
        perror("接收响应失败");
    } else {
        printf("服务器响应:%s\n", buffer);
    }
    
    // 6. 关闭Socket
    close(sockfd);
    
    return 0;
}
UDP服务器端示例
c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 8888
#define BUFFER_SIZE 1024

int main() {
    int sockfd;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_len = sizeof(client_addr);
    char buffer[BUFFER_SIZE];
    
    // 1. 创建UDP Socket
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1) {
        perror("socket创建失败");
        exit(EXIT_FAILURE);
    }
    
    // 2. 绑定地址和端口
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);
    
    if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("绑定失败");
        close(sockfd);
        exit(EXIT_FAILURE);
    }
    
    printf("UDP服务器启动...\n");
    
    // 3. 接收数据
    memset(buffer, 0, BUFFER_SIZE);
    int bytes_received = recvfrom(sockfd, buffer, BUFFER_SIZE - 1, 0,
                                 (struct sockaddr*)&client_addr, &client_len);
    if (bytes_received < 0) {
        perror("接收数据失败");
    } else {
        printf("收到客户端消息:%s\n", buffer);
        
        // 4. 发送响应
        char response[BUFFER_SIZE];
        snprintf(response, BUFFER_SIZE, "服务器已收到:%s", buffer);
        sendto(sockfd, response, strlen(response), 0,
               (struct sockaddr*)&client_addr, client_len);
    }
    
    // 5. 关闭Socket
    close(sockfd);
    
    return 0;
}
UDP客户端示例
c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 8888
#define BUFFER_SIZE 1024

int main() {
    int sockfd;
    struct sockaddr_in server_addr;
    char buffer[BUFFER_SIZE];
    
    // 1. 创建UDP Socket
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1) {
        perror("socket创建失败");
        exit(EXIT_FAILURE);
    }
    
    // 2. 设置服务器地址
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr);
    
    // 3. 发送数据
    char *message = "Hello UDP Server!";
    sendto(sockfd, message, strlen(message), 0,
           (struct sockaddr*)&server_addr, sizeof(server_addr));
    
    // 4. 接收响应
    memset(buffer, 0, BUFFER_SIZE);
    socklen_t server_len = sizeof(server_addr);
    int bytes_received = recvfrom(sockfd, buffer, BUFFER_SIZE - 1, 0,
                                 (struct sockaddr*)&server_addr, &server_len);
    if (bytes_received < 0) {
        perror("接收响应失败");
    } else {
        printf("服务器响应:%s\n", buffer);
    }
    
    // 5. 关闭Socket
    close(sockfd);
    
    return 0;
}

4.4 Socket编程注意事项

  • 端口选择:避免使用0-1023的知名端口,建议使用1024-65535的端口
  • 异常处理:网络通信中可能发生各种异常,需要妥善处理
  • 资源释放:确保Socket、流等资源在使用后正确关闭
  • 并发处理:服务器端通常需要支持多客户端并发连接
  • 缓冲区大小:合理设置缓冲区大小,避免内存浪费或数据丢失

4.5 网络编程最佳实践

  1. 使用线程池:处理并发连接时使用线程池,避免频繁创建销毁线程
  2. 设置超时:为Socket操作设置合理的超时时间,避免无限等待
  3. 数据校验:重要数据应添加校验机制,确保数据完整性
  4. 日志记录:记录关键操作和异常信息,便于问题排查
  5. 安全考虑:对用户输入进行验证,防止注入攻击
相关推荐
Oflycomm1 小时前
IPC网络摄像机与安防监控:Wi-Fi 6模组、AOV低功耗与边缘AI的产业落地
网络·人工智能·安防监控·wifi6·ipc网络摄像机
0x531 小时前
Java网络编程(四)
java·网络
tanglinS1 小时前
工业陶瓷在半导体设备里都用哪里?氮化铝基板与氮化硅结构件的静电无尘角色
大数据·运维·人工智能·自动化·材质
highreport1 小时前
HighReport报表工具定时调度和邮件定时发送
运维·服务器·数据库
TonyLee0172 小时前
Claude Code + DeepSeek:服务器安装与使用笔记
linux·服务器·deepseek·claude code
St_rive2 小时前
Pytest skip&&skipif跳过⽤例
运维·服务器·pytest
buhuizhiyuci2 小时前
【Linux 篇】数字世界的水流蓄水池 —— IO 缓冲区机制深度实战解析
linux·运维·服务器·c++
贝锐2 小时前
多校区互通、临时联网、远程运维,校园网络升级用蒲公英更省心!
运维·组网
骇客野人2 小时前
Linux 服务器 Python 版 MCP 服务部署整体方案(适配 Claude/Cursor/自研Agent)
linux·服务器·python