Skip to main content

Python 网络编程

Python TCP 编程

本章节主要讲解 TCP 协议简介,TCP 连接流程,建立连接(握手),数据传输,断开连接(挥手),Python Socket 编程基础,服务端开发流程,客户端开发流程,ECHO服务器示例,服务端代码,客户端代码,运行说明,注意事项。

TCP 协议简介

本教程假定你已经学习过 TCP/IP UDP 相关的计算机网络相关知识,这里对这些基础知识只做简单提及。

TCP(传输控制协议)是一种面向连接的、可靠的传输协议。它保证数据的完整性和顺序,是构建网络应用程序的重要基础。

TCP 连接流程

TCP 连接遵循三次握手建立连接,四次挥手断开连接的流程:

建立连接(三次握手)

  1. 客户端发起连接:向服务器发送 SYN 包
  2. 服务器响应:返回 SYN-ACK 包确认连接
  3. 客户端确认:发送 ACK 包,连接建立完成

数据传输

连接建立后,双方可以进行双向数据传输,TCP 协议会自动处理数据包的排序、重传和错误检测。

断开连接(四次挥手)

  1. 主动方发送 FIN 包请求断开
  2. 被动方发送 ACK 确认
  3. 被动方发送 FIN 包
  4. 主动方发送 ACK 确认,连接完全断开

Python Socket 编程基础

Python 使用 socket 模块进行网络编程。对于 TCP 连接,我们使用 socket.SOCK_STREAM 类型。

服务端开发流程

  1. 创建 socket 对象
  2. 绑定地址和端口
  3. 开始监听连接
  4. 接受客户端连接
  5. 接收和发送数据
  6. 关闭连接

客户端开发流程

  1. 创建 socket 对象
  2. 连接到服务器
  3. 发送和接收数据
  4. 关闭连接

ECHO服务器示例

服务端代码

import socket
import threading

def handle_client(client_socket, client_address):
    """处理单个客户端连接"""
    print(f"客户端 {client_address} 已连接")
    
    try:
        while True:
            # 接收客户端数据
            data = client_socket.recv(1024)
            if not data:
                break
            
            message = data.decode('utf-8')
            print(f"收到来自 {client_address} 的消息: {message}")
            
            # 回声:将收到的消息发送回客户端
            response = f"服务器回复: {message}"
            client_socket.send(response.encode('utf-8'))
            
    except Exception as e:
        print(f"处理客户端 {client_address} 时出错: {e}")
    finally:
        client_socket.close()
        print(f"客户端 {client_address} 已断开连接")

def start_server():
    """启动 TCP 服务器"""
    # 创建 socket 对象
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    # 设置 socket 选项,允许重用地址
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    
    # 绑定地址和端口
    host = 'localhost'
    port = 8888
    server_socket.bind((host, port))
    
    # 开始监听,最大连接数为5
    server_socket.listen(5)
    print(f"服务器启动,监听 {host}:{port}")
    
    try:
        while True:
            # 接受客户端连接
            client_socket, client_address = server_socket.accept()
            
            # 为每个客户端创建新线程
            client_thread = threading.Thread(
                target=handle_client,
                args=(client_socket, client_address)
            )
            client_thread.daemon = True
            client_thread.start()
            
    except KeyboardInterrupt:
        print("\n服务器正在关闭...")
    finally:
        server_socket.close()

if __name__ == "__main__":
    start_server()

客户端代码

import socket

def start_client():
    """启动 TCP 客户端"""
    # 创建 socket 对象
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    try:
        # 连接到服务器
        host = 'localhost'
        port = 8888
        client_socket.connect((host, port))
        print(f"已连接到服务器 {host}:{port}")
        
        while True:
            # 获取用户输入
            message = input("请输入消息 (输入 'quit' 退出): ")
            
            if message.lower() == 'quit':
                break
            
            # 发送消息到服务器
            client_socket.send(message.encode('utf-8'))
            
            # 接收服务器响应
            response = client_socket.recv(1024)
            print(f"服务器响应: {response.decode('utf-8')}")
            
    except Exception as e:
        print(f"客户端出错: {e}")
    finally:
        client_socket.close()
        print("客户端已断开连接")

if __name__ == "__main__":
    start_client()

运行说明

  1. 启动服务端:先运行服务端代码,服务器开始监听连接
  2. 启动客户端:运行客户端代码,连接到服务器
  3. 测试通信:在客户端输入消息,观察服务器的回应
  4. 退出程序:客户端输入 'quit' 退出,服务端使用 Ctrl+C 停止

服务端

客户端

注意事项

  • 端口占用:确保使用的端口没有被其他程序占用
  • 防火墙设置:如果测试时连接失败,检查防火墙设置
  • 资源释放:使用 try-finally 确保 socket 资源被正确释放
  • 编码统一:客户端和服务端使用相同的字符编码(如 UTF-8)