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下的代码实现及仿真的更多相关文章

  1. python下的orm基本操作(1)--Mysql下的CRUD简单操作(含源码DEMO)

    最近逐渐打算将工作的环境转移到ubuntu下,突然发现对于我来说,这ubuntu对于我这种上上网,收收邮件,写写博客,写写程序的时实在是太合适了,除了刚接触的时候会不怎么完全适应命令行及各种权限管理, ...

  2. Python下的OpenCV学习 01 —— 在Linux下安装OpenCV

    一.OpenCV简要介绍 OpenCV是一个跨平台的计算机视觉库,可以运行在Windows.Linux.MacOS等操作系统上.OpenCV提供了众多语言的接口,其中就包含了Python,Python ...

  3. Python下划线简介

    Python中下划线的5种含义 分享一篇文章:The Meaning of Underscores in Python. 本文介绍了Python中单下划线和双下划线("dunder" ...

  4. Python下探究随机数的产生原理和算法

    资源下载 #本文PDF版下载 Python下探究随机数的产生原理和算法(或者单击我博客园右上角的github小标,找到lab102的W7目录下即可) #本文代码下载 几种随机数算法集合(和下文出现过的 ...

  5. python下划线的5种含义

    本文介绍了Python中单下划线和双下划线("dunder")的各种含义和命名约定,名称修饰(name mangling)的工作原理,以及它如何影响你自己的Python类. 单下划 ...

  6. python下wxpython程序国际化的实践(中文英文切换)

    一.什么是python的国际化(I18N) 有关I18N,百度上解释一大堆,个人比较喜欢这个说法. i18n是 Internationalization 这个英文的简写,因为International ...

  7. Python下图片的高斯模糊化的优化

    资源下载 #本文PDF版下载 Python下图片的高斯模糊化的优化(或者单击我博客园右上角的github小标,找到lab102的W6目录下即可) #本文代码下载 高斯模糊(一维)优化代码(和本文方法集 ...

  8. 利用python 下paramiko模块无密码登录

    利用python 下paramiko模块无密码登录   上次我个大家介绍了利用paramiko这个模块,可以模拟ssh登陆远程服务器,并且可以返回执行的命令结果,这次给大家介绍下如何利用已经建立的密钥 ...

  9. python下的自动化测试--selenium 验证码输入问题

    之前一直在研究scrapy下数据抓取,在研究ajax数据抓取时碰巧研究了一下selenium,确实很实用,不过只做scrapy下的数据抓取,不怎么合适,一是性能的损耗,一直需要开一个浏览器,二是对于爬 ...

随机推荐

  1. nyoj 10 skiing (DFS)

    skiing 时间限制:3000 ms  |  内存限制:65535 KB 难度:5   描述 Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当 ...

  2. pat 1116 Come on! Let's C(20 分)

    1116 Come on! Let's C(20 分) "Let's C" is a popular and fun programming contest hosted by t ...

  3. 06_K-近邻算法

    k-近邻算法 算法介绍 定义: 如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一类别,则该样本也属于这个类别. 计算距离公式:欧式距离 (两点之间距离) 需要做标准化 ...

  4. rsync同步基本用法

                                                                                                        ...

  5. 学习记录:《C++设计模式——李建忠主讲》3.“组件协作”模式

    “组件协作”模式:现代软件专业分工之后的第一个结果是“框架与应用程序的划分”,“组件协作”模式通过晚期绑定,来实现框架与应用程序之间的松耦合,是二者之间协作时常用的模式.典型模式:Template M ...

  6. Rio手把手教学:如何打造容器化应用程序的一站式部署体验

    11月19日,业界应用最为广泛的Kubernetes管理平台创建者Rancher Labs(以下简称Rancher)宣布Rio发布了beta版本,这是基于Kubernetes的应用程序部署引擎.它于今 ...

  7. vue项目引入自定义.css的样式文件

    ES6的引入方式: .vue文件中 css文件引入 <template></template> <style scoped> @import "../as ...

  8. Entity Framework Core For MySql查询中使用DateTime.Now的问题

    背景 最近一直忙于手上澳洲线上项目的整体迁移和升级的准备工作,导致博客和公众号停更.本周终于艰难的完成了任务,借此机会,总结一下项目中遇到的一些问题. EF Core一直是我们团队中中小型项目常用的O ...

  9. 选择了uniapp开发app

    7月份打算做一简单app,之前公司做app的时候简单用过Dcloud公司的mui,当时由于uniapp刚出来,最终选择了mui.对uniapp的 了解几乎没有. 做app对我来说几乎是零基础的,当然是 ...

  10. java之初见

    1.Java语言的了解: Java语言最早是由SUN公司创造出来的,1991年,SUN公司的green项目,Oak,随后SUN公司和后来的甲骨文公司又先后发布了java1.0,1.1,1.2,1.3, ...