dingallen216 发表于 2021-8-30 17:28

计算机网络——小实验:解析IP、TCP、UDP数据报

本帖最后由 dingallen216 于 2021-8-30 17:32 编辑

第一章链接:https://www.52pojie.cn/thread-1500148-1-1.html
第二章链接:https://www.52pojie.cn/thread-1500750-1-1.html第三章链接:https://www.52pojie.cn/thread-1501401-1-1.html第四章链接:https://www.52pojie.cn/thread-1502111-1-1.html
计算机网络概述、物理层、数据链路层、网络层的笔记都在上面这些内容里了,看到传输层和应用层的时候,全是些耳熟能详的内容,什么TCP三次握手,什么HTTP协议,干脆就放弃了做无用的笔记 。本文参考****的课程,做了一个解析IP、UDP、TCP数据报的小实验。本实验基于Python。

解析IP数据报
# -*- encoding=utf-8 -*-

import struct
import socket

class IPParser:

    IP_HEADER_LENGTH = 20

    @classmethod
    def parse_ip_header(cls, ip_header):

      第一行 = struct.unpack('>BBH', ip_header[:4])
      第三行 = struct.unpack('>BBH', ip_header)
      第四行 = struct.unpack('>4s', ip_header)
      第五行 = struct.unpack('>4s', ip_header)

      IP版本 = 第一行 >> 4
      头部长度 = 第一行 & 15
      总长度 = 第一行
      TTL = 第三行
      协议 = 第三行
      首部校验和 = 第三行
      源IP地址 = socket.inet_ntoa(第四行)
      目的IP地址 = socket.inet_ntoa(第五行)

      return {
            'IP版本': IP版本,
            '头部长度': 头部长度,
            '总长度': 总长度,
            'TTL': TTL,
            '协议': 协议,
            '首部校验和': 首部校验和,
            '源IP地址': 源IP地址,
            '目的IP地址': 目的IP地址
      }

    @classmethod
    def parse(cls, packet):
      ip_header = packet[:20]
      return cls.parse_ip_header(ip_header)
易语言了都,属于是。应该不需要解说。

解析UDP、TCP数据报
# -*- encoding=utf-8 -*-

import struct

class TransParser:
    IP_HEADER_OFFSET = 20
    UDP_HEADER_LENGTH = 8
    TCP_HEADER_LENGTH = 20


class UDPParser(TransParser):

    @classmethod
    def parse_udp_header(cls, udp_header):

      头 = struct.unpack('>HHHH', udp_header)
      源端口 = 头
      目的端口 = 头
      UDP长度 = 头
      检验和 = 头

      return {
            '源端口': 源端口,
            '目的端口': 目的端口,
            'UDP长度': UDP长度,
            '检验和': 检验和
      }

    @classmethod
    def parse(cls, packet):
      udp_header = packet
      return cls.parse_udp_header(udp_header)


class TCPParser(TransParser):

    @classmethod
    def parse_tcp_header(cls, tcp_header):

      第一行 = struct.unpack('>HH', tcp_header[:4])
      第二行 = struct.unpack('>L', tcp_header)
      第三行 = struct.unpack('>L', tcp_header)
      第四行 = struct.unpack('>BBH', tcp_header)
      第五行 = struct.unpack('>HH', tcp_header)

      源端口 = 第一行
      目的端口 = 第一行
      序列号 = 第二行
      确认号 = 第三行
      数据偏移 = 第四行 >> 4
      flags = 第四行 & int('00111111',2)
      FIN = flags & 1
      SYN = (flags >> 1) & 1
      RST = (flags >> 2) & 1
      PSH = (flags >> 3) & 1
      ACK = (flags >> 4) & 1
      URG = (flags >> 5) & 1
      窗口大小 = 第四行
      检验和 = 第五行
      紧急指针 = 第五行

      return {
            '源端口': 源端口,
            '目的端口': 目的端口,
            '序列号': 序列号,
            '确认号': 确认号,
            '数据偏移': 数据偏移,
            '标志位': {
                'FIN': FIN,
                'SYN': SYN,
                'RST': RST,
                'PSH': PSH,
                'ACK': ACK,
                'URG': URG
            },
            '窗口大小': 窗口大小,
            '检验和': 检验和,
            '紧急指针': 紧急指针
      }

    @classmethod
    def parse(cls, packet):
      tcp_header = packet
      return cls.parse_tcp_header(tcp_header)

主逻辑(不必在意类名和其继承的类,这就是用于用于完成异步任务的,主逻辑就是process内的代码。需要注意的是,我们在运行时会给类传入一个packet,这就是我们通过监听捕获到的数据包)
class ProcessTask(AsyncTask):

    def __init__(self, packet, *args, **kwargs):
      self.packet = packet
      super(ProcessTask, self).__init__(func=self.process, *args, **kwargs)

    def process(self):
      headers = {
            '网络层': None,
            '传输层': None
      }
      ip_header = IPParser.parse(self.packet)
      headers['网络层'] = ip_header
      if ip_header['协议'] == 17:
            udp_header = UDPParser.parse(self.packet)
            headers['传输层'] = udp_header
      elif ip_header['协议'] == 6:
            tcp_header = TCPParser.parse(self.packet)
            headers['传输层'] = tcp_header

      return headers

效果
https://pic1.zhimg.com/80/v2-f8d8f7f00ebeeb2320281ce6cea6088f_720w.png图:IP数据报夹TCP数据报
https://pic1.zhimg.com/80/v2-e0e89eda561b73ebea7d6db172246eef_720w.png图:IP数据报夹UDP数据报

总结:本文完成的解析数据报的方法就是取下头部,一个萝卜一个坑地将每个比特位的作用对应上其规则。IP协议是网络层的协议,而UDP和TCP是传输层的协议,所以想要拿到UDP和TCP数据,需要先把IP数据报的头部给摘了。可以看出这一过程在计算机内实现起来并不复杂,通过此方法,我们能剥下层层数据,解析出更高层次的协议内容。

WSlibre 发表于 2021-8-30 20:24

谢谢分享

小朋友呢 发表于 2021-8-30 20:28

老铁这是看的哪位大神视频学的,可以推荐下吗

dingallen216 发表于 2021-8-30 21:00

小朋友呢 发表于 2021-8-30 20:28
老铁这是看的哪位大神视频学的,可以推荐下吗

***** 咚咚锵

小朋友呢 发表于 2021-8-31 10:09

dingallen216 发表于 2021-8-30 21:00
***** 咚咚锵

老铁前面的字被****号了

dingallen216 发表于 2021-8-31 12:07

小朋友呢 发表于 2021-8-31 10:09
老铁前面的字被****号了

被屏蔽的是mu课网
页: [1]
查看完整版本: 计算机网络——小实验:解析IP、TCP、UDP数据报