From d2b7f9c085d4bfb2663b2c8f5012b9d004d54a57 Mon Sep 17 00:00:00 2001 From: "zhouzhongping@7wate.com" Date: Mon, 11 Sep 2023 10:38:48 +0800 Subject: [PATCH] =?UTF-8?q?Python=EF=BC=9Asocket=20=E5=BA=95=E5=B1=82?= =?UTF-8?q?=E7=BD=91=E7=BB=9C=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../拓展模块/网络处理/socket 底层网络接口.md | 327 ++++++++++++++++++ .../{网络请求 => 网络处理}/urllib URL 处理模块.md | 0 2 files changed, 327 insertions(+) create mode 100644 wiki/programming-language/Python/进阶/拓展模块/网络处理/socket 底层网络接口.md rename wiki/programming-language/Python/进阶/拓展模块/{网络请求 => 网络处理}/urllib URL 处理模块.md (100%) diff --git a/wiki/programming-language/Python/进阶/拓展模块/网络处理/socket 底层网络接口.md b/wiki/programming-language/Python/进阶/拓展模块/网络处理/socket 底层网络接口.md new file mode 100644 index 00000000..09c476c7 --- /dev/null +++ b/wiki/programming-language/Python/进阶/拓展模块/网络处理/socket 底层网络接口.md @@ -0,0 +1,327 @@ +--- +title: socket 底层网络接口 +description: socket 底层网络接口 +keywords: + - Python + - socket +tags: + - Python + - 标准库 +sidebar_position: 2 +author: 7Wate +date: 2023-09-09 +--- + +## 概述 + +Socket 是计算机网络中用于实现进程间通信的一种技术。简而言之,它是一个端点,用于发送或接收数据。这些数据可以在同一台计算机上的进程之间,或者在不同计算机上的进程之间进行传输。 + +`socket` 是 Python 中的一个标准库,它提供了低级的网络通信功能。基于该库,开发者可以实现 TCP、UDP 以及其他类型的网络协议的客户端和服务端程序。 + +`socket` 库的历史可以追溯到 Unix 操作系统的早期。在 Unix 中,socket 被用作进程间通信(IPC)的一种方式。随着互联网的发展,socket 逐渐被应用于网络通信。Python 的 `socket` 库提供了对这一功能的高级封装,使得开发网络应用变得更为简单。 + +## 工作原理 + +`socket`网络通信最常见的模型是客户端-服务器模型。客户端是请求服务的实体,而服务器是提供服务的实体。Socket 允许这两个实体进行通信。 + +- **客户端**: 创建 Socket -> 连接到服务器 -> 交换数据 -> 关闭 Socket +- **服务器**: 创建 Socket -> 绑定到特定地址和端口 -> 监听连接 -> 接受客户端连接 -> 交换数据 -> 关闭 Socket + +`socket` 主要被用于: + +- 创建网络服务器和客户端。 +- 实现多种网络协议,如 TCP 和 UDP。 +- 进行低级的网络通信,如发送原始套接字数据。 + +它解决了开发者在进行网络通信时的底层细节问题,如地址转换、数据传输等。 + +### 协议类型 + +- **流式 Socket (SOCK_STREAM)**: 提供了一个可靠的、面向连接的字节流。这是最常用的 Socket 类型,TCP 协议就是基于这种 Socket。 +- **数据报 Socket (SOCK_DGRAM)**: 提供了一种无连接的、不可靠的数据传输方式。UDP 协议就是基于这种 Socket。 +- **原始 Socket (SOCK_RAW)**: 允许直接访问底层协议,通常用于开发新的通信协议。 + +### 地址家族 + +- **AF_INET (IPv4)**: 最常用的地址家族,用于 Internet 通信。 +- **AF_INET6 (IPv6)**: 下一代 Internet 地址家族。 +- **AF_UNIX**: 用于同一台机器上的进程间通信。 + +### 生命周期 + +```mermaid +graph LR; + A[创建 Socket] --> B[绑定 Socket到地址和端口]; + B --> C[开始监听传入的连接]; + C --> D[接受连接请求]; + D --> E[进行数据传输]; + E --> F[关闭 Socket]; +``` + +1. **创建**: 使用 `socket.socket()` 创建一个新的 Socket 对象。 +2. **绑定**: 使用 `bind()` 方法将 Socket 绑定到特定的地址和端口。 +3. **监听**: 使用 `listen()` 方法开始监听传入的连接。 +4. **接受连接**: 使用 `accept()` 方法接受一个连接。 +5. **数据传输**: 使用 `send()` 和 `recv()` 方法进行数据传输。 +6. **关闭**: 使用 `close()` 方法关闭 Socket。 + +## 基础操作 + +由于 `socket` 是 Python 的标准库,无需额外安装。 + +### 支持协议 + +`socket` 库支持多种协议,用于不同的网络通信场景。 + +```python +# 服务器 +import socket + +server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +server_socket.bind(('localhost', 8080)) +server_socket.listen(5) + +print("服务器正在监听...") +client_socket, addr = server_socket.accept() +print(f"连接来自 {addr}") + +data = client_socket.recv(1024) +print(f"接收到的数据: {data.decode('utf-8')}") +client_socket.send("谢谢你!".encode('utf-8')) + +client_socket.close() +server_socket.close() +``` + +```python +# 客户端 +import socket + +client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +client_socket.connect(('localhost', 8080)) + +client_socket.send("你好,服务器!".encode('utf-8')) +data = client_socket.recv(1024) +print(f"接收到的数据: {data.decode('utf-8')}") + +client_socket.close() +``` + +### TCP 示例 + +```mermaid +graph LR + +subgraph TCP服务器 + A[创建Socket] --> B[绑定到地址和端口] + B --> C[监听连接请求] + C --> D[接受连接] + D --> E[接收数据] + E --> F[处理数据] + F --> G[发送响应] + G --> E + E --> H[关闭连接] + H --> D +end + +subgraph TCP客户端 + I[创建Socket] --> J[连接到服务器] + J --> K[发送数据] + K --> L[接收响应] + L --> M[处理响应] + M --> K + K --> N[关闭连接] +end + +A --> I + +``` + +#### 服务器 + +```python +import socket + +# 步骤1:创建 TCP Socket +server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + +# 步骤2:绑定 Socket 到一个特定的 IP 地址和端口 +server_address = ('localhost', 12345) +server_socket.bind(server_address) + +# 步骤3:监听传入的连接请求 +server_socket.listen(5) + +print("TCP 服务器启动,等待连接...") + +while True: + # 步骤4:接受客户端的连接请求 + client_socket, client_address = server_socket.accept() + print(f"接受来自 {client_address} 的连接") + + # 步骤5:与客户端建立通信 + while True: + data = client_socket.recv(1024) + if not data: + break + + # 步骤6:接收和发送数据 + data = data.decode('utf-8') + print(f"接收到来自客户端的数据: {data}") + response = f"你好, +``` + +#### 客户端 + +```python +import socket + +# 步骤1:创建 TCP Socket +client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + +# 步骤2:连接到服务器的 IP 地址和端口 +server_address = ('localhost', 12345) +client_socket.connect(server_address) + +while True: + # 步骤3:发送数据给服务器 + message = input("请输入要发送的消息 (输入 'exit' 退出): ") + + if message == 'exit': + break + + client_socket.send(message.encode('utf-8')) + + # 步骤4:接收来自服务器的响应数据 + data = client_socket.recv(1024) + + # 步骤5:处理服务器的响应数据 + data = data.decode('utf-8') + print(f"接收到服务器的响应: {data}") + +# 步骤6:关闭与服务器的连接 +client_socket.close() +``` + +### UDP 示例 + +```mermaid +graph LR + +subgraph UDP服务器 + A[创建Socket] --> B[绑定到地址和端口] + B --> C[接收数据] + C --> D[处理数据] + D --> E[发送响应] + E --> C +end + +subgraph UDP客户端 + F[创建Socket] --> G[发送数据] + G --> H[接收响应] + H --> I[处理响应] + I --> G +end + +A --> F + +``` + +#### 服务端 + +```python +import socket + +# 步骤1:创建 UDP Socket +server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + +# 步骤2:绑定 Socket 到一个特定的 IP 地址和端口 +server_address = ('localhost', 12345) +server_socket.bind(server_address) + +print("UDP 服务器启动,等待数据...") + +while True: + # 步骤3:接收客户端发送的数据 + data, client_address = server_socket.recvfrom(1024) + + # 步骤4:处理客户端数据 + data = data.decode('utf-8') + print(f"接收到来自 {client_address} 的数据: {data}") + + # 步骤5:为客户端发送响应(如果需要) + response = f"你好,客户端!你发送了:{data}" + server_socket.sendto(response.encode('utf-8'), client_address) + +# 步骤6:关闭 Socket(这里永远不会执行到) +server_socket.close() +``` + +#### 客户端 + +```python +import socket + +# 步骤1:创建 UDP Socket +client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + +# 服务器地址和端口 +server_address = ('localhost', 12345) + +while True: + # 步骤2:发送数据给服务器 + message = input("请输入要发送的消息 (输入 'exit' 退出): ") + + if message == 'exit': + break + + client_socket.sendto(message.encode('utf-8'), server_address) + + # 步骤3:接收来自服务器的响应数据 + data, server_address = client_socket.recvfrom(1024) + + # 步骤4:处理服务器的响应数据 + data = data.decode('utf-8') + print(f"接收到服务器的响应: {data}") + +# 步骤5:关闭 Socket +client_socket.close() +``` + +### 常用方法 + +| 方法 | 描述 | +| --------- | -------------------- | +| socket() | 创建一个新的 socket | +| bind() | 绑定到一个地址和端口 | +| listen() | 开始监听连接 | +| accept() | 接受一个新的连接 | +| connect() | 连接到一个服务器 | +| send() | 发送数据 | +| recv() | 接收数据 | +| close() | 关闭 socket | + +## 深入探索 + +### 高级功能 + +#### 非阻塞 sockets + +```python +import socket + +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +s.setblocking(False) +``` + +#### 套接字选项 + +```python +s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +``` + +#### 超时 + +```python +s.settimeout(5.0) +``` diff --git a/wiki/programming-language/Python/进阶/拓展模块/网络请求/urllib URL 处理模块.md b/wiki/programming-language/Python/进阶/拓展模块/网络处理/urllib URL 处理模块.md similarity index 100% rename from wiki/programming-language/Python/进阶/拓展模块/网络请求/urllib URL 处理模块.md rename to wiki/programming-language/Python/进阶/拓展模块/网络处理/urllib URL 处理模块.md