19.1 网络编程基础
19.1.1 网络与协议
网络是由多个计算机通过通信设备连接而成的系统,用于实现数据交换和资源共享。在网络中,数据的传输需要遵循一定的规则,这些规则被称为协议。
常见的网络协议包括:
- TCP/IP 协议簇:是互联网的核心协议,包括 IP(网际协议)、TCP(传输控制协议)、UDP(用户数据报协议)等。
- HTTP/HTTPS:用于万维网(WWW)的数据传输,HTTP 是超文本传输协议,HTTPS 是加密的 HTTP。
- FTP:文件传输协议,用于在网络上传输文件。
本章主要介绍基于 TCP 和 UDP 的网络编程,以及 HTTP 协议的基本使用。
19.1.2 IP 地址与端口
- IP 地址:用于标识网络中的设备,如计算机、服务器等。IPv4 地址是 32 位的整数,通常表示为 4 个十进制数(如192.168.1.1);IPv6 地址是 128 位的整数,用于解决 IPv4 地址不足的问题。
- 端口:用于标识设备上的进程(应用程序),范围是 0-65535。其中 0-1023 是知名端口(如 HTTP 的 80 端口、HTTPS 的 443 端口),1024-65535 是动态端口,可用于自定义应用程序。
一个网络连接由IP 地址 + 端口唯一标识,例如127.0.0.1:8080表示本地计算机上的 8080 端口。
19.1.3 客户端与服务器
网络通信通常涉及客户端(Client)和服务器(Server):
- 服务器:提供服务的程序,通常处于监听状态,等待客户端的连接请求。
- 客户端:请求服务的程序,主动向服务器发起连接请求,与服务器进行数据交换。
例如,浏览器是客户端,当你访问网站时,浏览器向网站服务器发起请求,服务器返回网页数据。
19.2 Socket 编程
Socket(套接字)是网络编程的接口,用于实现不同设备之间的通信。Python 的标准库socket提供了 Socket 编程的功能,支持 TCP 和 UDP 协议。
19.2.1 Socket 的基本操作
使用 Socket 进行网络编程的基本步骤:
- 创建 Socket 对象。
- 配置 Socket(如绑定 IP 地址和端口、监听连接等)。
- 进行数据传输(发送和接收数据)。
- 关闭 Socket。
Socket 的主要方法:
- socket():创建 Socket 对象。
- bind():绑定 IP 地址和端口。
- listen():监听连接(仅服务器)。
- accept():接受连接请求(仅服务器),返回客户端 Socket 和地址。
- connect():连接服务器(仅客户端)。
- send()/recv():发送 / 接收数据。
- close():关闭 Socket。
19.3 TCP 编程
TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层协议。TCP 通信需要先建立连接(三次握手),然后进行数据传输,最后断开连接(四次挥手),确保数据的可靠传输。
19.3.1 TCP 服务器
示例:创建一个简单的 TCP 服务器,接收客户端发送的消息并返回响应。
import socket
# 创建TCP Socket对象(AF_INET表示IPv4,SOCK_STREAM表示TCP)
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定IP地址和端口(空字符串表示监听所有网络接口,端口8080)
server_address = ('', 8080)
print(f"绑定到{server_address},等待连接...")
server_socket.bind(server_address)
# 开始监听,最多允许5个连接请求在队列中
server_socket.listen(5)
try:
while True:
# 接受客户端连接(阻塞等待)
client_socket, client_address = server_socket.accept()
try:
print(f"接收到来自{client_address}的连接")
# 接收客户端发送的数据(最多1024字节)
data = client_socket.recv(1024)
print(f"收到数据:{data.decode('utf-8')}")
# 向客户端发送响应
response = "已收到你的消息:" + data.decode('utf-8')
client_socket.sendall(response.encode('utf-8'))
finally:
# 关闭客户端Socket
client_socket.close()
print(f"与{client_address}的连接已关闭")
except KeyboardInterrupt:
print("服务器已停止")
finally:
# 关闭服务器Socket
server_socket.close()
19.3.2 TCP 客户端
示例:创建 TCP 客户端,向服务器发送消息并接收响应。
import socket
# 创建TCP Socket对象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 连接服务器
server_address = ('localhost', 8080)
print(f"连接到{server_address}...")
client_socket.connect(server_address)
try:
# 向服务器发送消息
message = "你好,服务器!"
print(f"发送消息:{message}")
client_socket.sendall(message.encode('utf-8'))
# 接收服务器的响应
data = client_socket.recv(1024)
print(f"收到响应:{data.decode('utf-8')}")
except ConnectionRefusedError:
print("连接失败,服务器可能未启动")
finally:
# 关闭Socket
client_socket.close()
print("连接已关闭")
运行步骤:
- 先运行服务器程序,服务器开始监听 8080 端口。
- 再运行客户端程序,客户端连接服务器并发送消息。
- 服务器收到消息后返回响应,客户端接收响应。
- 按Ctrl+C停止服务器。
19.4 UDP 编程
UDP(User Datagram Protocol,用户数据报协议)是一种无连接的、不可靠的传输层协议。UDP 通信不需要建立连接,直接发送数据报,不保证数据的可靠传输,但传输速度较快,适合实时性要求高的场景(如视频通话、游戏)。
19.4.1 UDP 服务器
示例:创建 UDP 服务器,接收客户端发送的数据报并返回响应。
import socket
# 创建UDP Socket对象(SOCK_DGRAM表示UDP)
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 绑定IP地址和端口
server_address = ('', 8080)
print(f"绑定到{server_address},等待数据...")
server_socket.bind(server_address)
try:
while True:
# 接收数据报(最多1024字节),返回数据和客户端地址
data, client_address = server_socket.recvfrom(1024)
print(f"从{client_address}收到数据:{data.decode('utf-8')}")
# 向客户端发送响应
response = "已收到你的数据:" + data.decode('utf-8')
server_socket.sendto(response.encode('utf-8'), client_address)
except KeyboardInterrupt:
print("服务器已停止")
finally:
# 关闭Socket
server_socket.close()
19.4.2 UDP 客户端
示例:创建 UDP 客户端,向服务器发送数据报并接收响应。
import socket
# 创建UDP Socket对象
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_address = ('localhost', 8080)
message = "你好,UDP服务器!"
try:
# 向服务器发送数据报
print(f"发送数据:{message}")
sent = client_socket.sendto(message.encode('utf-8'), server_address)
# 接收服务器的响应
data, server_address = client_socket.recvfrom(1024)
print(f"从{server_address}收到响应:{data.decode('utf-8')}")
except ConnectionRefusedError:
print("发送失败,服务器可能未启动")
finally:
# 关闭Socket
client_socket.close()
print("Socket已关闭")
UDP 与 TCP 的主要区别:
- TCP 是面向连接的,UDP 是无连接的。
- TCP 保证数据可靠传输(重传丢失的数据包),UDP 不保证。
- TCP 传输速度较慢,UDP 传输速度较快。
- TCP 适合传输大量数据(如文件),UDP 适合实时通信(如视频、语音)。
19.5 HTTP 编程
HTTP(Hypertext Transfer Protocol,超文本传输协议)是用于万维网的应用层协议,基于 TCP 传输数据,采用客户端 - 服务器模式。常见的 HTTP 请求方法有GET(获取资源)和POST(提交数据)。
Python 的标准库urllib和第三方库requests可以用于发送 HTTP 请求,requests库使用更简单,推荐使用。
19.5.1 安装 requests 库
使用 pip 安装requests:
pip install requests
19.5.2 发送 GET 请求
GET请求用于从服务器获取资源(如网页、API 数据)。
示例:使用requests发送 GET 请求
import requests
# 发送GET请求
url = "https://www.baidu.com"
response = requests.get(url)
# 打印响应状态码(200表示成功)
print(f"状态码:{response.status_code}")
# 打印响应内容的前100个字符
print("响应内容:", response.text[:100])
# 获取响应头
print("响应头:", response.headers['Content-Type'])
示例:发送带参数的 GET 请求
import requests
# 请求参数
params = {
"q": "Python", # 搜索关键词
"page": 1 # 页码
}
# 发送带参数的GET请求
url = "https://www.bing.com/search"
response = requests.get(url, params=params)
print(f"请求URL:{response.url}") # 打印实际请求的URL
print(f"状态码:{response.status_code}")
19.5.3 发送 POST 请求
POST请求用于向服务器提交数据(如表单提交、API 数据提交)。
示例:使用requests发送 POST 请求
import requests
# 要提交的数据
data = {
"username": "test",
"password": "123456"
}
# 发送POST请求
url = "https://httpbin.org/post" # 一个用于测试的API
response = requests.post(url, data=data)
# 解析JSON响应(httpbin.org会返回提交的数据)
result = response.json()
print("提交的数据:", result['form'])
19.5.4 处理 JSON 响应
很多 API 返回 JSON 格式的数据,可以使用response.json()方法解析。
示例:获取 JSON 格式的 API 数据
import requests
# 获取GitHub用户信息的API
url = "https://api.github.com/users/octocat"
response = requests.get(url)
if response.status_code == 200:
user_info = response.json()
print(f"用户名:{user_info['login']}")
print(f"仓库数量:{user_info['public_repos']}")
print(f"创建时间:{user_info['created_at']}")
else:
print(f"请求失败,状态码:{response.status_code}")
19.6 示例:简单的 Web 服务器
Python 的标准库http.server可以快速创建一个简单的 Web 服务器,用于测试静态网页。
示例:创建 Web 服务器
from http.server import HTTPServer, SimpleHTTPRequestHandler
# 服务器地址和端口
server_address = ('', 8000)
# 创建服务器,使用SimpleHTTPRequestHandler处理请求
httpd = HTTPServer(server_address, SimpleHTTPRequestHandler)
print(f"Web服务器启动在 http://localhost:8000")
print("按Ctrl+C停止服务器")
try:
# 启动服务器(无限循环处理请求)
httpd.serve_forever()
except KeyboardInterrupt:
# 按Ctrl+C停止服务器
httpd.shutdown()
print("服务器已停止")
运行服务器后,在浏览器中访问http://localhost:8000,可以查看服务器所在目录的文件和文件夹。SimpleHTTPRequestHandler会处理 HTTP GET 请求,返回对应的文件内容(如 HTML 文件、图片等)。
19.7 小结
本章介绍了 Python 网络编程的基础知识,包括 TCP 和 UDP 协议的 Socket 编程,以及使用requests库发送 HTTP 请求。
- TCP 编程:适合需要可靠传输的场景,服务器需要bind()、listen()、accept(),客户端需要connect(),双方通过send()和recv()交换数据。
- UDP 编程:适合实时性要求高的场景,不需要建立连接,通过sendto()和recvfrom()发送和接收数据报。
- HTTP 编程:使用requests库可以方便地发送 GET 和 POST 请求,处理网页和 API 数据。
网络编程是 Python 的重要应用领域,掌握这些基础知识可以帮助你开发网络应用、调用 API 接口、创建客户端 / 服务器程序等。下一章将介绍 Python 的测试与调试方法,帮助你编写更可靠的代码。