在互联网时代,网络通信是软件开发中不可或缺的一部分。而 Python 作为一门功能强大、语法简洁的编程语言,其内置的 socket
模块为我们提供了基础而灵活的网络通信能力。
本文将带你深入了解 Python 中的网络编程,涵盖 TCP 服务器与客户端的创建、UDP 通信的实现、以及 socket 模块的核心方法与属性。无论你是刚入门网络编程的新手,还是希望巩固基础的开发者,这篇文章都会为你提供实用价值。
🧭 一、基础知识回顾:客户端/服务器架构与套接字
在开始编写代码之前,我们需要理解几个关键概念:
- 客户端/服务器架构:客户端主动发起请求,服务器被动等待并响应请求。
- 套接字(Socket):是网络通信的基本单元,可以理解为连接两个程序的"管道"。
- 协议类型:
SOCK_STREAM
:使用 TCP 协议,面向连接,保证数据顺序和完整性。SOCK_DGRAM
:使用 UDP 协议,无连接,速度快但不保证数据送达。
在 Python 中,我们使用 socket
模块来创建和操作套接字。其核心函数是:
python
socket.socket(socket_family, socket_type, protocol=0)
其中:
socket_family
可以是AF_INET
(IPv4)或AF_INET6
(IPv6)socket_type
是SOCK_STREAM
(TCP)或SOCK_DGRAM
(UDP)
例如,创建一个 TCP 套接字:
python
tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
📡 二、实现 TCP 服务器与客户端通信
🧱 1. TCP 服务器的创建流程
TCP 服务器一般遵循如下流程:
python
ss = socket() # 创建服务器套接字
ss.bind() # 绑定地址和端口
ss.listen() # 监听连接
while True: # 无限循环
cs = ss.accept() # 接受客户端连接
while True: # 通信循环
cs.recv() # 接收数据
cs.send() # 发送数据
cs.close() # 关闭客户端连接
ss.close() # 可选关闭服务器套接字
📦 示例:TCP 时间戳服务器
python
from socket import *
from time import ctime
HOST = ''
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST, PORT)
tcpSerSock = socket(AF_INET, SOCK_STREAM)
tcpSerSock.bind(ADDR)
tcpSerSock.listen(5)
while True:
print('等待连接...')
tcpCliSock, addr = tcpSerSock.accept()
print('来自', addr, '的连接')
while True:
data = tcpCliSock.recv(BUFSIZE)
if not data:
break
tcpCliSock.send(bytes(f'[{ctime()}] {data.decode()}', 'utf-8'))
tcpCliSock.close()
📲 2. TCP 客户端的实现
TCP 客户端流程相对简单,包括连接服务器、收发数据、关闭连接。
python
cs = socket()
cs.connect((host, port)) # 连接服务器
while True:
send_data = input('> ')
if not send_data:
break
cs.send(bytes(send_data, 'utf-8'))
recv_data = cs.recv(1024)
print(recv_data.decode('utf-8'))
cs.close()
📦 示例:TCP 时间戳客户端
python
from socket import *
HOST = 'localhost'
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST, PORT)
tcpCliSock = socket(AF_INET, SOCK_STREAM)
tcpCliSock.connect(ADDR)
while True:
data = input('> ')
if not data:
break
tcpCliSock.send(data.encode())
response = tcpCliSock.recv(BUFSIZE)
print(response.decode())
tcpCliSock.close()
📡 三、实现 UDP 服务器与客户端通信
UDP 的通信过程更加简洁,因为它是无连接的协议。
🧱 1. UDP 服务器流程
python
ss = socket(AF_INET, SOCK_DGRAM)
ss.bind((host, port))
while True:
data, addr = ss.recvfrom(bufsize)
ss.sendto(data, addr)
📦 示例:UDP 时间戳服务器
python
from socket import *
from time import ctime
HOST = ''
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST, PORT)
udpSerSock = socket(AF_INET, SOCK_DGRAM)
udpSerSock.bind(ADDR)
while True:
print('等待消息...')
data, addr = udpSerSock.recvfrom(BUFSIZE)
reply = f'[{ctime()}] {data.decode()}'
udpSerSock.sendto(reply.encode(), addr)
📲 2. UDP 客户端实现
python
cs = socket(AF_INET, SOCK_DGRAM)
while True:
data = input('> ')
if not data:
break
cs.sendto(data.encode(), (host, port))
response, server = cs.recvfrom(1024)
print(response.decode())
cs.close()
📦 示例:UDP 时间戳客户端
python
from socket import *
HOST = 'localhost'
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST, PORT)
udpCliSock = socket(AF_INET, SOCK_DGRAM)
while True:
msg = input('> ')
if not msg:
break
udpCliSock.sendto(msg.encode(), ADDR)
data, server = udpCliSock.recvfrom(BUFSIZE)
print(data.decode())
udpCliSock.close()
⚙️ 四、常用 socket 模块属性一览
除了 socket()
函数,socket
模块还提供了一些常用的属性,帮助我们更好地进行网络编程。
属性名 | 含义 |
---|---|
socket.AF_INET |
IPv4 地址族 |
socket.AF_INET6 |
IPv6 地址族 |
socket.SOCK_STREAM |
TCP 类型套接字 |
socket.SOCK_DGRAM |
UDP 类型套接字 |
socket.gethostname() |
获取本机主机名 |
socket.gethostbyname(hostname) |
获取主机名对应的 IP 地址 |
socket.gethostbyaddr(ip) |
获取 IP 地址对应的主机名信息 |
socket.htonl(x) |
将 32 位整数从主机字节序转换为网络字节序 |
socket.ntohl(x) |
反向转换 |
这些属性可以帮助我们更灵活地处理网络通信过程中涉及的地址、协议、数据格式等。
🧠 五、总结:Python 网络编程的核心要点
通过本文的学习,你应该已经掌握了以下核心内容:
- Socket 套接字的创建与使用方式,包括 TCP 和 UDP。
- TCP 服务器与客户端通信流程,涉及连接、数据交换、关闭连接。
- UDP 的无连接通信机制,适用于对实时性要求更高的场景。
- Python 3 与 Python 2 的编码差异,如
bytes
和str
的转换。 - socket 模块的常用属性和函数,便于开发中灵活使用。
📚 六、拓展建议
如果你想进一步提升网络编程能力,以下是一些推荐方向:
- 学习
asyncio
模块,实现异步网络通信。 - 了解
select
、poll
、epoll
实现多路复用网络模型。 - 探索基于
Twisted
或Tornado
的高性能网络服务开发。 - 使用
socketserver
模块简化 TCP/UDP 服务器的实现。
📌 结语:
网络编程是构建现代分布式系统、微服务、即时通讯等应用的基础。Python 的 socket
模块虽然基础,但正是这种"低层次"的控制能力,让我们能更深入地理解网络通信的本质。