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. thinkphp两表,多表联合查询及分页的连贯操作写法

    ThinkPHP中关联查询(即多表联合查询)可以使用 table() 方法或和join方法,具体使用如下例所示: 1.原生查询示例: 代码如下: $Model = new Model(); $sql  ...

  2. secureCRT连接虚拟机

    1.secureCRT英文版下载 链接:https://pan.baidu.com/s/1LFWD-k2r4ZB7DHQA66QogQ 密码:khmo 破解方式参考 2.虚拟机静态IP设置 参考 3. ...

  3. pat 1042 Shuffling Machine(20 分)

    1042 Shuffling Machine(20 分) Shuffling is a procedure used to randomize a deck of playing cards. Bec ...

  4. 结合Spring Security进行web应用会话安全管理

    在本文中,将为大家说明如何结合Spring Security 和Spring Session管理web应用的会话. 一.Spring Security创建使用session的方法 Spring Sec ...

  5. arm下dlsym返回的符号地址居然不是偶对齐的。

    我们都知道在写汇编函数过程都会偶对齐,而gcc编译器都会将函数编译为cpu字长对齐的地址.arm指令集是固定32位指令长度,thumb指令集是固定16位指令长度, 但是运行在arm下的程序,dlsym ...

  6. Java——内部类详解

    说起内部类,大家肯定感觉熟悉又陌生,因为一定在很多框架源码中有看到别人使用过,但又感觉自己使用的比较少,今天我就带你具体来看看内部类. 内部类基础 所谓内部类就是在类的内部继续定义其他内部结构类. 在 ...

  7. cglib测试例子和源码详解

    目录 简介 为什么会有动态代理? 常见的动态代理有哪些? 什么是cglib 使用例子 需求 工程环境 主要步骤 创建项目 引入依赖 编写被代理类 编写MethodInterceptor接口实现类 编写 ...

  8. nginx(二):基本应用

    配置文件详解 event段配置 worker_connections #; 每个worker进程所能够响应的最大并发请求数量: nginx最大并发响应数=worker_proceses * worke ...

  9. JSONPath小试牛刀之Snack3

    最近在网上看了些JSONPath的入门例子.打算用Snack3这个框架写写例子.json path对`JSON的处理绝对是神器. 1.准备JSON字符串 { "store": { ...

  10. Intellij 生成exe可执行文件

    生成jar包 编写源代码 此处我使用kotlin来编码,主函数实际功能就是输出一行文字. /** * 应用入口 * @author mazaiting */ object TestExe { ​ @J ...