好友
阅读权限10
听众
最后登录1970-1-1
|
本帖最后由 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数据报
[Python] 纯文本查看 复制代码 # -*- 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[8:12])
第四行 = struct.unpack('>4s', ip_header[12:16])
第五行 = struct.unpack('>4s', ip_header[16:20])
IP版本 = 第一行[0] >> 4
头部长度 = 第一行[0] & 15
总长度 = 第一行[2]
TTL = 第三行[0]
协议 = 第三行[1]
首部校验和 = 第三行[2]
源IP地址 = socket.inet_ntoa(第四行[0])
目的IP地址 = socket.inet_ntoa(第五行[0])
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数据报
[Python] 纯文本查看 复制代码 # -*- 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)
源端口 = 头[0]
目的端口 = 头[1]
UDP长度 = 头[2]
检验和 = 头[3]
return {
'源端口': 源端口,
'目的端口': 目的端口,
'UDP长度': UDP长度,
'检验和': 检验和
}
@classmethod
def parse(cls, packet):
udp_header = packet[cls.IP_HEADER_OFFSET:cls.IP_HEADER_OFFSET + cls.UDP_HEADER_LENGTH]
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[4:8])
第三行 = struct.unpack('>L', tcp_header[8:12])
第四行 = struct.unpack('>BBH', tcp_header[12:16])
第五行 = struct.unpack('>HH', tcp_header[16:20])
源端口 = 第一行[0]
目的端口 = 第一行[1]
序列号 = 第二行[0]
确认号 = 第三行[0]
数据偏移 = 第四行[0] >> 4
flags = 第四行[1] & 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
窗口大小 = 第四行[2]
检验和 = 第五行[0]
紧急指针 = 第五行[1]
return {
'源端口': 源端口,
'目的端口': 目的端口,
'序列号': 序列号,
'确认号': 确认号,
'数据偏移': 数据偏移,
'标志位': {
'FIN': FIN,
'SYN': SYN,
'RST': RST,
'PSH': PSH,
'ACK': ACK,
'URG': URG
},
'窗口大小': 窗口大小,
'检验和': 检验和,
'紧急指针': 紧急指针
}
@classmethod
def parse(cls, packet):
tcp_header = packet[cls.IP_HEADER_OFFSET:cls.IP_HEADER_OFFSET + cls.TCP_HEADER_LENGTH]
return cls.parse_tcp_header(tcp_header)
主逻辑(不必在意类名和其继承的类,这就是用于用于完成异步任务的,主逻辑就是process内的代码。需要注意的是,我们在运行时会给类传入一个packet,这就是我们通过监听捕获到的数据包)
[Python] 纯文本查看 复制代码 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
效果
图:IP数据报夹TCP数据报 图:IP数据报夹UDP数据报
总结:本文完成的解析数据报的方法就是取下头部,一个萝卜一个坑地将每个比特位的作用对应上其规则。IP协议是网络层的协议,而UDP和TCP是传输层的协议,所以想要拿到UDP和TCP数据,需要先把IP数据报的头部给摘了。可以看出这一过程在计算机内实现起来并不复杂,通过此方法,我们能剥下层层数据,解析出更高层次的协议内容。 |
免费评分
-
查看全部评分
|