Python 网络编程实战指南:从 TCP_UDP 到 Socket 编程

在互联网时代,网络通信是软件开发中不可或缺的一部分。而 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_typeSOCK_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 网络编程的核心要点

通过本文的学习,你应该已经掌握了以下核心内容:

  1. Socket 套接字的创建与使用方式,包括 TCP 和 UDP。
  2. TCP 服务器与客户端通信流程,涉及连接、数据交换、关闭连接。
  3. UDP 的无连接通信机制,适用于对实时性要求更高的场景。
  4. Python 3 与 Python 2 的编码差异,如 bytesstr 的转换。
  5. socket 模块的常用属性和函数,便于开发中灵活使用。

📚 六、拓展建议

如果你想进一步提升网络编程能力,以下是一些推荐方向:

  • 学习 asyncio 模块,实现异步网络通信。
  • 了解 selectpollepoll 实现多路复用网络模型。
  • 探索基于 TwistedTornado 的高性能网络服务开发。
  • 使用 socketserver 模块简化 TCP/UDP 服务器的实现。

📌 结语:

网络编程是构建现代分布式系统、微服务、即时通讯等应用的基础。Python 的 socket 模块虽然基础,但正是这种"低层次"的控制能力,让我们能更深入地理解网络通信的本质。