你是否需要一个关于用Python实现网络校验和计算的案例

访客 网络编程 1

本文目录导读:

  1. IPv4头部校验和计算
  2. TCP/UDP校验和计算(包含伪头部)
  3. 校验和验证函数

这是一个关于用Python实现网络校验和计算的实用案例,包含IPv4头部校验和与TCP/UDP校验和两种常见场景。

IPv4头部校验和计算

def calculate_ip_checksum(header):
    """
    计算IPv4头部校验和
    参数: header - bytes类型,IP头部数据(20字节)
    返回: int类型,校验和值
    """
    # 将校验和字段置零
    header_list = list(header)
    # 第10-11字节是校验和字段(0-indexed)
    header_list[10] = 0
    header_list[11] = 0
    # 按16位分组求和
    checksum = 0
    for i in range(0, len(header_list), 2):
        word = (header_list[i] << 8) + header_list[i+1]
        checksum += word
    # 处理进位
    while checksum > 0xFFFF:
        checksum = (checksum & 0xFFFF) + (checksum >> 16)
    # 取反得到校验和
    checksum = ~checksum & 0xFFFF
    return checksum
# 示例:计算IP头部校验和
def test_ip_checksum():
    # 构建一个示例IP头部(不含校验和)
    # 版本4,头部长度5(20字节),服务类型0,总长度20
    # 标识12345,标志和偏移0,TTL64,协议TCP(6),源地址192.168.1.1,目的地址192.168.1.2
    ip_header = bytes([
        0x45, 0x00,  # 版本和头部长度,服务类型
        0x00, 0x14,  # 总长度20
        0x30, 0x39,  # 标识12345
        0x40, 0x00,  # 标志和偏移
        0x40, 0x06,  # TTL64,协议TCP
        0x00, 0x00,  # 校验和(待计算)
        0xC0, 0xA8, 0x01, 0x01,  # 源地址192.168.1.1
        0xC0, 0xA8, 0x01, 0x02   # 目的地址192.168.1.2
    ])
    checksum = calculate_ip_checksum(ip_header)
    print(f"IPv4头部校验和: 0x{checksum:04X}")
    # 验证:将计算出的校验和放回头部,重新计算应该为0
    ip_header_with_checksum = bytearray(ip_header)
    ip_header_with_checksum[10] = (checksum >> 8) & 0xFF
    ip_header_with_checksum[11] = checksum & 0xFF
    verify_sum = calculate_ip_checksum(bytes(ip_header_with_checksum))
    print(f"验证结果(应为0): 0x{verify_sum:04X}")
if __name__ == "__main__":
    test_ip_checksum()

TCP/UDP校验和计算(包含伪头部)

import struct
def calculate_tcp_checksum(ip_src, ip_dst, tcp_segment):
    """
    计算TCP校验和
    参数:
        ip_src - 源IP地址字符串,如"192.168.1.1"
        ip_dst - 目的IP地址字符串
        tcp_segment - bytes类型,TCP段数据(包含TCP头部和数据)
    返回: int类型,校验和值
    """
    # 解析IP地址
    src_bytes = bytes(map(int, ip_src.split('.')))
    dst_bytes = bytes(map(int, ip_dst.split('.')))
    # 构建伪头部 (12字节)
    pseudo_header = struct.pack('!4s4sBBH', 
        src_bytes, 
        dst_bytes, 
        0,          # 保留
        6,          # TCP协议号
        len(tcp_segment)  # TCP段长度
    )
    # 组合伪头部和TCP段进行校验和计算
    data = pseudo_header + tcp_segment
    # 如果数据长度为奇数,补一个0字节
    if len(data) % 2 != 0:
        data += b'\x00'
    # 计算校验和
    checksum = 0
    for i in range(0, len(data), 2):
        word = (data[i] << 8) + data[i+1]
        checksum += word
    # 处理进位
    while checksum > 0xFFFF:
        checksum = (checksum & 0xFFFF) + (checksum >> 16)
    # 取反
    checksum = ~checksum & 0xFFFF
    return checksum
# UDP校验和类似,只是协议号不同
def calculate_udp_checksum(ip_src, ip_dst, udp_datagram):
    """
    计算UDP校验和
    参数:
        ip_src - 源IP地址字符串
        ip_dst - 目的IP地址字符串
        udp_datagram - bytes类型,UDP数据报(包含UDP头部和数据)
    返回: int类型,校验和值
    """
    src_bytes = bytes(map(int, ip_src.split('.')))
    dst_bytes = bytes(map(int, ip_dst.split('.')))
    # UDP伪头部 (协议号17)
    pseudo_header = struct.pack('!4s4sBBH', 
        src_bytes, 
        dst_bytes, 
        0,          # 保留
        17,         # UDP协议号
        len(udp_datagram)
    )
    data = pseudo_header + udp_datagram
    if len(data) % 2 != 0:
        data += b'\x00'
    checksum = 0
    for i in range(0, len(data), 2):
        word = (data[i] << 8) + data[i+1]
        checksum += word
    while checksum > 0xFFFF:
        checksum = (checksum & 0xFFFF) + (checksum >> 16)
    checksum = ~checksum & 0xFFFF
    return checksum
# 测试示例
def test_tcp_checksum():
    # 构建一个简单TCP段(假设来自HTTP请求)
    # 源端口12345,目的端口80,序列号1000,确认号2000
    # 头部长度5(20字节),标志SYN(0x02),窗口大小65535
    tcp_header = struct.pack('!HHLLBBHHH',
        12345,      # 源端口
        80,         # 目的端口
        1000,       # 序列号
        2000,       # 确认号
        0x50,       # 数据偏移(5*4=20字节)
        0x02,       # 标志位 (SYN)
        65535,      # 窗口大小
        0,          # 校验和(待计算)
        0           # 紧急指针
    )
    # TCP数据(可选,这里为空)
    tcp_data = b''
    tcp_segment = tcp_header + tcp_data
    # 将校验和字段置零(第16-17字节)
    tcp_segment_list = bytearray(tcp_segment)
    tcp_segment_list[16] = 0
    tcp_segment_list[17] = 0
    tcp_segment = bytes(tcp_segment_list)
    checksum = calculate_tcp_checksum(
        "192.168.1.1", 
        "192.168.1.2", 
        tcp_segment
    )
    print(f"TCP校验和: 0x{checksum:04X}")
def test_udp_checksum():
    # 构建一个简单UDP数据报
    # 源端口12345,目的端口53(DNS),长度8(头部)+ 数据
    udp_data = b'Hello World'
    udp_length = 8 + len(udp_data)  # UDP头部8字节
    udp_header = struct.pack('!HHHH',
        12345,      # 源端口
        53,         # 目的端口
        udp_length, # 长度
        0           # 校验和(待计算)
    )
    udp_datagram = udp_header + udp_data
    # 将校验和字段置零(第6-7字节)
    udp_list = bytearray(udp_datagram)
    udp_list[6] = 0
    udp_list[7] = 0
    udp_datagram = bytes(udp_list)
    checksum = calculate_udp_checksum(
        "192.168.1.1",
        "192.168.1.2",
        udp_datagram
    )
    print(f"UDP校验和: 0x{checksum:04X}")
if __name__ == "__main__":
    print("=== TCP校验和测试 ===")
    test_tcp_checksum()
    print("\n=== UDP校验和测试 ===")
    test_udp_checksum()

校验和验证函数

def verify_checksum(data, checksum_type='ip'):
    """
    验证校验和是否正确
    参数:
        data - bytes类型,包含校验和字段的完整数据
        checksum_type - 'ip', 'tcp', 或 'udp'
    返回: bool,校验和是否正确
    """
    if checksum_type == 'ip':
        # IP头部校验和验证:整个头部重新计算应为0
        calc_sum = calculate_ip_checksum(data)
        return calc_sum == 0
    else:
        # TCP/UDP需要提供源和目的IP(这里简化仅做示例)
        raise ValueError("TCP/UDP验证需要额外的IP地址信息")
# 使用示例
if __name__ == "__main__":
    print("\n=== 通用校验和验证示例 ===")
    # 构建正确的IP头部
    ip_header = bytes([
        0x45, 0x00, 0x00, 0x14,
        0x30, 0x39, 0x40, 0x00,
        0x40, 0x06, 0x00, 0x00,  # 校验和先置0
        0xC0, 0xA8, 0x01, 0x01,
        0xC0, 0xA8, 0x01, 0x02
    ])
    # 计算并设置校验和
    checksum = calculate_ip_checksum(ip_header)
    ip_header_with_csum = bytearray(ip_header)
    ip_header_with_csum[10] = (checksum >> 8) & 0xFF
    ip_header_with_csum[11] = checksum & 0xFF
    # 验证
    result = verify_checksum(bytes(ip_header_with_csum), 'ip')
    print(f"校验和验证结果: {'正确' if result else '错误'}")

这个案例演示了:

  1. IPv4头部校验和 - 简单直接的16位累加和取反
  2. TCP/UDP校验和 - 包含伪头部(源IP、目的IP、协议号、段长度)
  3. 校验和验证 - 验证计算是否正确

实际应用中,这些函数可以用于网络抓包分析、协议实现验证、数据完整性检查等场景。

标签: 校验和

抱歉,评论功能暂时关闭!