通信协议TLV的介绍及在python下的代码实现及仿真
TLV协议是一种通讯协议,一般将数据封装成TLV的形式,即Tag,Length,Value。协议就是指通信双方对数据传输控制的一种规定,规定了数据格式,同步方式,传送速度,传送步骤的问题作出统一的规定。可以理解为两个节点之间为了协同工作,协商一定的规则和约定。例如我们会规定字节序,各个字段类型等。
TLV 是一种可变的格式,其中:
T可以理解为Tag或Type,用于标识标签或者编码格式信息;L定义数值的长度;V表示实际的数值。
T 和 L 的长度固定,一般是2或4个字节,V 的长度由 Length 指定。
图例帧格式如下所示:

由于用到这块,我就自己弄了一个python下的仿真代码,这里就给大家demo一下了:
服务端:
import socket
import threading
import pickle import time
from TLV import *
# 定义保存所有socket的列表
socket_list = []
# 创建socket对象
ss = socket.socket()
# 将socket绑定到本机IP和端口
ss.bind(('localhost', 2333))
# 服务端开始监听来自客户端的连接
ss.listen()
tlv = TLV(t_ext=7, l_ext=7) def server_target(s):
try:
# 采用循环不断地从socket中读取客户端发送过来的数据
while True:
line = input()
if line is None or line == 'exit':
break time.sleep(2)
tlv.add(8,line)
data = pickle.dumps(tlv)
s.send(data)
except Exception:
print(Exception.with_traceback())
while True:
# 此行代码会阻塞,将一直等待别人的连接
s, addr = ss.accept()
#socket_list.append(s)
# 每当客户端连接后启动一个线程为该客户端服务
threading.Thread(target=server_target, args=(s, )).start()
客户端:
import socket
import threading
import pickle
from TLV import *
# 创建socket对象
s = socket.socket()
# 连接远程主机
s.connect(('localhost', 2333)) def read_from_server(s):
try:
data = pickle.loads(s.recv(2048))
# test
tlvp = TLVParser(data.buffer, t_ext=7, l_ext=7)
for avp in tlvp.parse():
print("%d(%d): %s" % (avp["type"], avp["length"], avp["value"]))
# return s.recv(2048).decode('utf-8')
return tlvp
# 如果捕获到异常,则表明该socket对应的客户端已经关闭
except:
# 删除该socket
socket_list.remove(s) # ① def read_server(s):
try:
while True:
contend = read_from_server(s)
if contend is None:
break
except:
print(Exception.with_traceback()) # 客户端启动线程不断地读取来自服务器的数据
threading.Thread(target=read_server, args=(s, )).start() # ①
TLV的实现:
from scapy.all import * class TLVError(Exception):
pass class TLV:
def __init__(self, tl_in_l=False, t_ext=0, l_ext=0):
self.buffer = ""
self.tl_in_l = tl_in_l
self.t_ext = t_ext
self.l_ext = l_ext def _int(self, i, ext):
maxi = 1<<8
if ext > 0:
maxi = (1 << ext)
holdstr = ""
holder = i
extend = 0
count = 1
while holder >= maxi:
count += 1
newnum = (holder & (maxi - 1))
holdstr = chr(newnum | extend) + holdstr
extend = maxi
holder /= maxi holdstr = chr(holder | extend) + holdstr
return holdstr def _t(self, t):
if self.t_ext == 0 and t > 256:
raise TLVError("type > 256 and no extension bit set")
return self._int(t, self.t_ext) def _l(self, l):
if self.l_ext == 0 and l > 256:
raise TLVError("length > 256 and no extension bit set")
return self._int(l, self.l_ext) def add(self, t, v, l=None):
self.buffer += self._t(t)
length = 0 if l is None else l if self.tl_in_l:
length += t if l is None:
length += len(v) self.buffer += self._l(length)
self.buffer += v def __str__(self):
return self.buffer def __repr__(self):
return self.buffer class TLVParser:
def __init__(self, buffer, tl_in_l=False, t_ext=0, l_ext=0):
self.buffer = buffer
self.tl_in_l = tl_in_l
self.t_ext = t_ext
self.l_ext = l_ext
self.offset = 0 def _get_i(self, i_ext):
try:
byte = ord(self.buffer[self.offset])
except IndexError:
raise TLVError("Not enough data")
ext = 1 << (i_ext if i_ext > 0 else 8)
i = 0
while byte & ext:
i += (byte & (ext - 1))
i <<= i_ext
self.offset += 1
try:
byte = ord(self.buffer[self.offset])
except IndexError:
raise TLVError("Not enough data")
i += byte
self.offset += 1
return i def _get_tlv(self):
t = self._get_i(self.t_ext)
l = self._get_i(self.l_ext)
if self.offset + l > len(self.buffer):
raise TLVError("Buffer not long enough to encompass TLV")
v = self.buffer[self.offset:self.offset+l]
self.offset += l
return (t, l, v) def parse(self):
while self.offset < len(self.buffer):
t, l, v = self._get_tlv()
yield {
"type": t,
"length": l,
"value": v,
} # Test/example program for building TLVs and parsing the TLVs
if __name__ == "__main__":
tlv = TLV(t_ext=7, l_ext=7)
tlv.add(10, "Foobar")
tlv.add(16, "Bladibla")
# hexdump(tlv)
tlvp = TLVParser(tlv.buffer, t_ext=7, l_ext=7)
for avp in tlvp.parse():
print ("%d(%d): %s" % (avp["type"], avp["length"], avp["value"]))
具体的代码运行结果就不贴了,对懂得python的同学来说,这个很简单的。
通信协议TLV的介绍及在python下的代码实现及仿真的更多相关文章
- python下的orm基本操作(1)--Mysql下的CRUD简单操作(含源码DEMO)
最近逐渐打算将工作的环境转移到ubuntu下,突然发现对于我来说,这ubuntu对于我这种上上网,收收邮件,写写博客,写写程序的时实在是太合适了,除了刚接触的时候会不怎么完全适应命令行及各种权限管理, ...
- Python下的OpenCV学习 01 —— 在Linux下安装OpenCV
一.OpenCV简要介绍 OpenCV是一个跨平台的计算机视觉库,可以运行在Windows.Linux.MacOS等操作系统上.OpenCV提供了众多语言的接口,其中就包含了Python,Python ...
- Python下划线简介
Python中下划线的5种含义 分享一篇文章:The Meaning of Underscores in Python. 本文介绍了Python中单下划线和双下划线("dunder" ...
- Python下探究随机数的产生原理和算法
资源下载 #本文PDF版下载 Python下探究随机数的产生原理和算法(或者单击我博客园右上角的github小标,找到lab102的W7目录下即可) #本文代码下载 几种随机数算法集合(和下文出现过的 ...
- python下划线的5种含义
本文介绍了Python中单下划线和双下划线("dunder")的各种含义和命名约定,名称修饰(name mangling)的工作原理,以及它如何影响你自己的Python类. 单下划 ...
- python下wxpython程序国际化的实践(中文英文切换)
一.什么是python的国际化(I18N) 有关I18N,百度上解释一大堆,个人比较喜欢这个说法. i18n是 Internationalization 这个英文的简写,因为International ...
- Python下图片的高斯模糊化的优化
资源下载 #本文PDF版下载 Python下图片的高斯模糊化的优化(或者单击我博客园右上角的github小标,找到lab102的W6目录下即可) #本文代码下载 高斯模糊(一维)优化代码(和本文方法集 ...
- 利用python 下paramiko模块无密码登录
利用python 下paramiko模块无密码登录 上次我个大家介绍了利用paramiko这个模块,可以模拟ssh登陆远程服务器,并且可以返回执行的命令结果,这次给大家介绍下如何利用已经建立的密钥 ...
- python下的自动化测试--selenium 验证码输入问题
之前一直在研究scrapy下数据抓取,在研究ajax数据抓取时碰巧研究了一下selenium,确实很实用,不过只做scrapy下的数据抓取,不怎么合适,一是性能的损耗,一直需要开一个浏览器,二是对于爬 ...
随机推荐
- PHP 在Swoole中使用双IoC容器实现无污染的依赖注入
简介: 容器(container)技术(可以理解为全局的工厂方法), 已经是现代项目的标配. 基于容器, 可以进一步实现控制反转, 依赖注入. Laravel 的巨大成功就是构建在它非常强大的IoC容 ...
- nginx+uWSGI+django+virtualenv+superviso发布web服务器
1.环境依赖 yum groupinstall "Development tools" -y yum install zlib-devel bzip2-devel pcre-dev ...
- Arduino 基于 ESP8266 配置WIFI模块
Arduino 基于 ESP8266 配置WIFI模块 使用ESP8266作为服务器,使用浏览器访问该服务器,从而控制LED灯 选择 [文件]->[示例]->[ESP8266WIFI]-& ...
- nyoj 822-画图 (*)
822-画图 内存限制:64MB 时间限制:1000ms 特判: No 通过数:133 提交数:187 难度:0 题目描述: 计算机画图也挺有趣的哈!那我们就来用计算机画幅图吧... 输入描述: 输入 ...
- 【Java】抽象类和接口详解
抽象类 一.抽象类的概述 现在请思考一个问题:假如我现在又Dog.Cat.Pig等实例对象,现在我们把它们都抽象成一个Animal类,这个类应该包含了这些Dog.Cat.Pig等实例对象eat的功能, ...
- 022.掌握Pod-Pod升级和回滚
一 deploymentPod升级和回滚 1.1 deployment升级 若Pod是通过Deployment创建的,可以在运行时修改Deployment的Pod定义(spec.template)或镜 ...
- Linux内核版本 uname命令 GNU项目 Linux发行版
1.内核版本由linux内核社区统一编码和发布,格式如下图: major.minor.patch-build.desc 主版本号.次版本号.对次版本号的修订次数-编译次数.当前版本的特殊信息 次版本号 ...
- 查看Oracle的连接数
select count(*) from v$process --当前连接数 select count(*) from v$process where program='ORACLE.EXE(SHAD ...
- GentOS 7 安装步骤
附上原作者的博客网址: https://blog.csdn.net/qq_42570879/article/details/82853708 1.CentOS下载CentOS是免费版,推荐在官网上直接 ...
- springboot+logback日志输出企业实践(下)
目录 1.引言 2. 输出 logback 状态数据 3. logback 异步输出日志 3.1 异步输出配置 3.2 异步输出原理 4. springboot 多环境下 logback 配置 5. ...