apppublic/aidocs/sockPackage.md
2025-10-05 11:23:33 +08:00

8.5 KiB
Raw Blame History

Socket 通信模块技术文档

本项目提供了一个基于 Python 的简单 TCP 客户端/服务器通信框架,支持多线程并发处理客户端连接,并封装了后台任务调用机制。适用于本地测试、轻量级网络服务开发等场景。


目录


依赖说明

import os
import time
import threading
import sys
import socket

所需标准库模块:

  • socket:用于实现 TCP 网络通信。
  • threading:支持多线程并发处理多个客户端连接。
  • time:用于延时控制和测试。
  • 其他为通用系统操作支持。

核心功能概览

组件 功能
get_free_local_addr() 获取当前机器可用的 IP 地址(通过 DNS 请求探测)
background / BackgroundCall() 异步执行函数的线程包装器
SocketServer 多线程 TCP 服务器,可接受并异步处理多个客户端连接
SocketClient TCP 客户端,用于连接服务器、发送和接收数据
自定义异常 SocketServerError, SocketClientError 提供清晰错误分类

工具函数

get_free_local_addr()

获取本机在联网状态下对外通信所使用的 IP 地址和临时端口。

函数签名

def get_free_local_addr():

返回值

  • (ip: str, port: int):元组形式返回本机出口 IP 和操作系统分配的临时端口号。

实现原理

通过创建一个 UDP 套接字连接到公共 DNS 服务器 8.8.8.8:80,不实际发送数据,仅用于确定本地绑定地址。

⚠️ 注意:此方法依赖外网可达性;若无网络或防火墙限制可能失败。

示例

ip, port = get_free_local_addr()
print(ip)  # 输出如 '192.168.1.100'

后台任务类

class background(threading.Thread)

封装一个可在后台运行的函数调用。

属性

属性名 类型 描述
func callable 要执行的目标函数
kw dict 关键字参数传递给目标函数

方法

__init__(self, func, kw)

初始化线程对象。

  • 参数
    • func: 可调用对象(函数)
    • kw: 字典形式的关键字参数 {key: value}
run(self)

重写 Thread.run(),自动调用 self.func(**self.kw)


BackgroundCall(func, datas)

便捷函数:启动一个后台线程执行指定函数。

参数

  • func: 待执行函数
  • datas: 传入该函数的关键字参数字典

行为

  • 创建 background 实例
  • 调用 .start() 启动线程
  • 不阻塞主线程

示例

def echo(data):
    print("Received:", data)

BackgroundCall(echo, {'data': 'Hello'})
# 在后台打印 "Received: Hello"

异常定义

class SocketServerError(Exception)

表示服务器端发生的严重错误,例如绑定地址失败、未就绪运行等。

class SocketClientError(Exception)

表示客户端连接或通信过程中出现的问题,如无法连接、读写出错等。

使用自定义异常便于上层捕获特定错误类型进行处理。


SocketServer 类

多线程 TCP 服务器,监听指定地址和端口,每个新连接由独立线程处理。

类定义

class SocketServer(threading.Thread)

继承自 threading.Thread,以非守护模式运行。


构造函数 __init__(host, port, max_connect=10, callee=None)

参数

参数 类型 默认值 说明
host str 绑定主机地址,如 'localhost''0.0.0.0'
port int 绑定端口号
max_connect int 10 最大挂起连接数listen 队列长度)
callee callable None 处理每个客户端连接的回调函数

回调函数原型

def handler(conn: socket.socket, addr: tuple):
    pass

其中:

  • conn: 客户端连接套接字
  • addr: 客户端地址 (ip, port)

初始化行为

  • 设置守护线程为 False
  • 创建并尝试绑定监听套接字
  • 若成功则 ready = True,否则记录日志但继续构造

方法

setSocketServer()

内部方法:创建并配置服务器套接字。

  • 创建 TCP 套接字 (AF_INET, SOCK_STREAM)
  • 绑定 (host, port)
  • 开始监听(最大连接队列长度为 max_c
  • 成功后设置 self.ready = True

若失败会打印错误信息但不会抛出异常(构造阶段容错)

run()

线程入口函数,循环接受客户端连接。

  • 检查是否 ready,否则抛出 SocketServerError
  • 进入无限循环等待客户端接入
  • 每次接受连接后,使用 BackgroundCallcallee 函数异步执行

单个连接处理完全解耦,不影响主服务循环

stop()

请求停止服务器运行。

  • 设置标志位 keep_running = 0
  • 下一次循环将退出 run() 函数
  • ⚠️ 当前已建立的连接不会被主动关闭

callee(self, conn, addr)(默认回显处理)

内置默认处理函数:持续接收数据并原样返回(回显服务),直到连接断开。

存在一个拼写错误:con.close() 应为 conn.close()

修正建议
def callee(self, conn, addr):
    try:
        while True:
            d = conn.recv(1024)
            if not d:  # 接收到空数据表示连接关闭
                break
            conn.send(d)
    finally:
        conn.close()  # 正确关闭连接

SocketClient 类

TCP 客户端封装,提供连接管理及基本 I/O 操作。

构造函数 __init__(host, port)

自动尝试连接指定服务器。

参数

  • host: 服务器地址
  • port: 端口

行为

  • 创建 TCP 套接字
  • 调用 connect() 方法连接服务器
  • 成功则 ready=True,失败则抛出 SocketClientError

方法

timeout(tim)

设置套接字阻塞模式和超时时间。

  • tim == 0: 非阻塞模式
  • tim > 0: 阻塞模式 + 超时秒数

内部调用 setblocking()settimeout()

connect()

重新建立与服务器的连接。

  • 若失败打印错误信息并抛出 SocketClientError

read(size)

从服务器读取最多 size 字节数据。

  • 成功返回字节串(bytes
  • 失败打印错误并抛出 SocketClientError

write(data)

向服务器发送数据。

  • data 必须是字节串(bytes),若传入字符串需先编码
  • 错误时抛出异常

close()

关闭连接,释放资源。

  • 调用 sock.close()
  • 设置 ready = False

主程序示例

if __name__ == '__main__':
    s = SocketServer('localhost', 12232)
    s.start()
    time.sleep(5)  # 等待服务器启动

    while True:
        c = SocketClient('localhost', 12232)
        msg = 'msg1'
        print("send:", msg)
        c.write(msg.encode())  # 注意:必须 encode 成 bytes
        d = c.read(1024)
        print("get:", d.decode())  # 解码为字符串
        c.close()
        time.sleep(1)

改进建议:添加异常处理防止客户端崩溃中断循环


使用建议与注意事项

推荐实践

  1. 确保数据编码一致性
    c.write(b'msg')           # 字节串
    c.write('msg'.encode())   # 字符串转字节
    
  2. 捕获异常避免中断
    try:
        c = SocketClient(...)
    except SocketClientError:
        time.sleep(1)
        continue
    
  3. 合理设置超时
    c.timeout(5)  # 5秒超时防卡死
    

⚠️ 已知问题

问题 描述 建议修复
con.close() 拼写错误 导致连接未正确关闭 改为 conn.close()
callee 默认函数无异常处理 可能导致线程异常退出 包裹 try...finally
构造中静默忽略异常 难以调试绑定失败原因 抛出或记录详细日志
write() 中错误提示写成了 'recv error' 日志误导 改为 'send error'

🔧 可扩展方向

  • 添加 SSL/TLS 支持
  • 支持 IPv6
  • 增加连接池或心跳检测
  • 提供异步 IO 版本asyncio

许可证

本代码为示例用途,遵循 MIT License(除非另有声明)。


文档版本v1.0
更新日期2025年4月5日