本部分计算机网络笔记用于学习和应用。

计算机网络基础

TCP和UDP的区别

特性 TCP (传输控制协议) UDP (用户数据报协议)
连接方式 面向连接 无连接
可靠性 提供可靠的数据传输,保证数据完整性 不保证数据的可靠性
流量控制 支持流量控制和拥塞控制 不支持流量控制
数据顺序 保证数据的顺序 不保证数据的顺序
速度 较慢,由于需要建立连接和确认 较快,没有建立连接的延迟
适用场景 适合需要可靠传输的应用,如网页、文件传输 适合实时应用,如视频会议、在线游戏
  • TCP数据包的结构

    • 头部:通常为20字节,包含以下字段:

      • 源端口(16位):发送端的端口号。
      • 目的端口(16位):接收端的端口号。
      • 序列号(32位):用于数据重组和控制。
      • 确认号(32位):期望收到的下一个字节的序列号。
      • 数据偏移(4位):头部长度。
      • 保留位(6位):保留用于未来使用。
      • 控制位(6位):包括URG、ACK、PSH、RST、SYN、FIN等,用于控制连接。
      • 窗口大小(16位):流量控制中的窗口大小。
      • 校验和(16位):用于检测传输中的错误。
      • 紧急指针(16位):指示紧急数据的偏移量(如果URG标志设置)。
      • 选项:可选字段,长度可变。

      数据部分:包含实际传输的数据。

  • UDP数据包结构

    • 头部: 固定为8字节,包含以下字段:
      • 源端口(16位):发送端的端口号。
      • 目的端口(16位):接收端的端口号。
      • 长度(16位):UDP头部和数据部分的总长度。
      • 校验和(16位):用于检测传输中的错误。
    • 数据部分:包含实际传输的数据。

TCP的三次握手和四次挥手机制

一、TCP 三次握手(连接建立)

三次握手的目的是为了保证客户端和服务器双方都确认对方收到了自己的请求,成功建立可靠的连接。过程如下:

  1. 第一次握手

    • 客户端向服务器发送一个 SYN(同步)报文,表示要建立连接。此时客户端进入 SYN_SENT 状态。
  2. 第二次握手

    • 服务器收到客户端的 SYN 报文后,确认收到,回复一个 SYN-ACK 报文,表示同意建立连接并确认 SYN。此时服务器进入 SYN_RCVD 状态。
  3. 第三次握手

    • 客户端收到服务器的 SYN-ACK 报文后,发送一个 ACK(确认)报文,确认服务器的响应。此时,客户端进入 ESTABLISHED(连接已建立)状态,服务器收到 ACK 后也进入 ESTABLISHED 状态。

这三次握手的主要目的是确认双方的发送、接收能力和初始化序列号的同步。

二、TCP 四次挥手(连接关闭)

四次挥手的目的是保证双方都确认连接已经正常关闭。其步骤如下:

  1. 第一次挥手

    • 当客户端想要关闭连接时,发送一个 FIN(结束)报文,表示不再发送数据。此时客户端进入 FIN_WAIT_1 状态。
  2. 第二次挥手

    • 服务器收到 FIN 报文后,确认收到,回复一个 ACK 报文。此时服务器进入 CLOSE_WAIT 状态,客户端收到 ACK 后进入 FIN_WAIT_2 状态。
  3. 第三次挥手

    • 服务器在确认客户端不再发送数据后,也发送一个 FIN 报文,表示自己也不再发送数据。此时服务器进入 LAST_ACK 状态。
  4. 第四次挥手

    • 客户端收到服务器的 FIN 报文后,发送 ACK 报文确认。此时客户端进入 TIME_WAIT 状态,等待一段时间(通常为 2 倍的报文最大生存时间,即 2MSL)以确保服务器接收到了 ACK,之后客户端进入 CLOSED 状态,连接关闭。

服务器收到 ACK 后,也进入 CLOSED 状态,至此连接完全关闭。

使用TCP/IP协议进行通信(基于python)

服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import socket

# 创建TCP服务器的socket对象
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 绑定IP地址和端口号
server_socket.bind(('localhost', 12345))

# 开始监听
server_socket.listen(5)
print("TCP服务器启动,等待客户端连接...")

# 等待客户端连接
client_socket, addr = server_socket.accept()
print(f"连接建立,客户端地址: {addr}")

# 接收数据
data = client_socket.recv(1024)
print(f"收到的数据: {data.decode()}")

# 发送响应
client_socket.send("你好,客户端!".encode())

# 关闭连接
client_socket.close()
server_socket.close()

TCP客户端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import socket

# 创建TCP客户端的socket对象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 连接服务器
client_socket.connect(('localhost', 12345))

# 发送数据
client_socket.send("你好,服务器!".encode())

# 接收服务器的响应
data = client_socket.recv(1024)
print(f"从服务器收到的响应: {data.decode()}")

# 关闭连接
client_socket.close()

使用TCP/IP协议进行网络聊天(基于python)

服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import socket
import threading

clients = []
usernames = []

def handle_client(client_socket):
while True:
try:
# 接收客户端发送的数据
message = client_socket.recv(1024)
if message:
broadcast(message, client_socket)
else:
remove_client(client_socket)
break
except:
continue

def broadcast(message, client_socket):
for client in clients:
if client != client_socket:
try:
client.send(message)
except:
remove_client(client)

def remove_client(client_socket):
index = clients.index(client_socket)
clients.remove(client_socket)
username = usernames[index]
usernames.remove(username)
broadcast(f"{username} 退出了聊天!".encode(), client_socket) # 传递 client_socket

def start_server():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 12345))
server_socket.listen(5)
print("聊天服务器启动,等待连接...")

while True:
client_socket, addr = server_socket.accept()
print(f"客户端 {addr} 连接。")

# 让客户端输入用户名
client_socket.send("请输入用户名:".encode())
username = client_socket.recv(1024).decode()
usernames.append(username)
clients.append(client_socket)
broadcast(f"{username} 加入了聊天!".encode(), client_socket) # 传递 client_socket

thread = threading.Thread(target=handle_client, args=(client_socket,))
thread.start()

if __name__ == "__main__":
start_server()

TCP客户端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import socket
import threading

def receive_messages(client_socket):
while True:
try:
message = client_socket.recv(1024)
if message:
print(message.decode())
else:
break
except:
print("连接到服务器失败。")
break

def start_client():
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('localhost', 12345))

# 输入用户名
username = input("请输入用户名:")
client_socket.send(username.encode())

thread = threading.Thread(target=receive_messages, args=(client_socket,))
thread.start()

while True:
message = input()
if message.lower() == 'exit':
break
client_socket.send(f"{username}: {message}".encode())

client_socket.close()

if __name__ == "__main__":
start_client()


Vlan

1. 什么是 VLAN?

  • VLAN(虚拟局域网)是通过交换机对物理网络进行逻辑划分的技术。
  • 它将一个物理局域网分割成多个广播域,实现不同部门或业务之间的隔离。
  • 目的:减少广播风暴、增强安全性和简化管理。

2. 什么是 VXLAN?

  • VXLAN(虚拟扩展局域网)是一种覆盖网络技术,用于跨数据中心或大规模云环境扩展 VLAN。
  • 通过在 UDP 封装中传输二层帧,实现不同物理网络间的二层连接。
  • 解决传统 VLAN 数量限制(4096)的问题,支持更大规模虚拟网络。

3. 学 VLAN 前需要了解的基本概念

  • 交换机工作在 OSI 模型的第二层(数据链路层),通过 MAC 地址转发数据。
  • VLAN 是通过交换机划分逻辑网络,基于端口或标签(802.1Q)区分。
  • 了解广播域、MAC 表、三层设备和路由概念。

4. Ping 用的是 ICMP 协议吗?

  • 是的,ping 使用的是 ICMP 协议,用于网络连通性测试。

5. 是否可以通过修改自己的 VLAN ID 访问其他 VLAN?

  • 不能随意修改 VLAN ID 来访问其他 VLAN。
  • 不同 VLAN 之间通信需要三层设备(路由器或三层交换机)进行路由转发。

6. 为什么不同 VLAN 之间通信需要三层设备?

  • VLAN 在二层(数据链路层)形成隔离的广播域,数据包无法跨 VLAN 直接传递。
  • 三层设备(路由器或三层交换机)根据 IP 层地址做路由,转发不同 VLAN 之间的数据。

7. 数据链路层和其它层的复习

  • OSI 模型包括七层:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。
  • 交换机工作在数据链路层,通过 MAC 地址转发。
  • 路由器工作在网络层,通过 IP 地址转发。
  • VLAN 隔离广播域属于数据链路层行为。

8. VLAN 发包和收包的示例

  • 主机 A 在 VLAN 10 发送数据包给同 VLAN 的主机 B,数据包直接通过交换机转发。
  • 主机 A 在 VLAN 10 发送数据包给 VLAN 20 的主机 C,必须经过三层设备路由转发。

9. 三层交换机的概念和其他层3

  • 三层交换机结合了交换机(二层)和路由器(三层)的功能。
  • 支持在交换机上做 VLAN 间路由,提高转发效率。
  • OSI 层中还有物理层、传输层等,但三层交换机主要关注二层和三层。

10. 三层交换机的出现是否为了解决 VLAN 互访?

  • 是的,三层交换机让 VLAN 之间能够高效通信,解决了 VLAN 隔离带来的互访问题。

11. 为什么还要划分 VLAN,而不是把所有设备放一块?

  • VLAN 划分基于实际业务和管理需求:
    • 减少广播域大小,提高性能;
    • 提高网络安全,防止未经授权访问;
    • 简化网络管理和故障定位;
    • 满足合规要求和数据隔离需求。

12. 三层交换机是否有权限划分?研发部访问财务部怎么办?

  • 三层交换机支持通过 ACL(访问控制列表)实现细粒度访问控制。
  • 可以配置允许研发 VLAN 访问财务 VLAN 的特定资源,限制其他访问。
  • 三层交换机同时保证 VLAN 隔离和灵活访问。

关于 VMware 的 NAT 网络实现,以及它是否基于 VLAN,给你做个简洁的解释:


13. VMware NAT 网络是如何实现的?

  • VMware NAT(网络地址转换)网络,是指虚拟机通过 VMware 提供的 NAT 服务,使用主机(宿主机)的 IP 地址对外通信。
  • VMware 在宿主机上创建一个虚拟的 NAT 网关(通常是虚拟的网络适配器 + NAT 服务进程),充当虚拟机和外部网络(如互联网)之间的路由器和地址转换器。
  • 虚拟机配置在一个私有子网中(通常是 192.168.x.x),它们的流量先发给这个 NAT 网关,网关用宿主机的 IP 和端口进行地址转换,实现虚拟机访问外网。

VMware NAT 网络和 VLAN 关系?

  • VMware 的 NAT 网络本质是 基于虚拟子网和虚拟路由的实现,而不是直接基于 VLAN 技术。
  • 虚拟机之间通过 VMware 虚拟交换机(VMware Virtual Switch)连接,这些虚拟交换机有不同模式:桥接(Bridged)、NAT、仅主机(Host-only)。
  • NAT 模式下虚拟机都在同一个虚拟私有网络中,虚拟交换机本身不会使用 VLAN 标签来隔离流量。
  • 如果需要划分 VLAN,可以在虚拟交换机或物理交换机层面进行 VLAN 配置,但 VMware NAT 模式默认不涉及 VLAN 标签。

简单总结

项目 VMware NAT 网络 VLAN
实现方式 私有虚拟子网 + NAT 网关 二层网络虚拟化,基于交换机端口或标签隔离
作用 让虚拟机共享宿主机公网 IP 访问外网 网络隔离,安全和广播域划分
是否必须使用 VLAN

如果你想用 VLAN 在 VMware 环境里做更细粒度的网络隔离:

  • 可以在 虚拟交换机(vSwitch)上配置 VLAN ID,然后给虚拟机的网卡指定 VLAN 标签。
  • 物理交换机要支持并配置相应 VLAN。
  • 这样虚拟机之间流量就可以基于 VLAN 隔离,和物理网络 VLAN 互通或隔离。