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. [java笔记] 最近学的一些笔记

    1.@Override的用法 2.父类的返回值类型的范围,与子类返回值类型的返回的大小关系: 3.子类方法的权限修饰符,与子类方法的权限修饰符: 4.如果p1是一个对象,p2也是个对象,那么代码p1= ...

  2. [git]关于github的一些用法笔记(入门)

    本视频来自于观看尚硅谷B站教学:https://www.bilibili.com/video/av10475153?from=search&seid=9735863941344749813 而 ...

  3. (C#)WPF:关于INotifyPropertyChanged接口的介绍

    注意:INotifyPropertyChanged接口位于System.CompenentModel名称空间中,想使用INotifyPropertyChanged接口时,头文件需添加“using Sy ...

  4. nyoj 242-计算球体积 (pi*r*r*r*4/3)

    242-计算球体积 内存限制:64MB 时间限制:3000ms 特判: No 通过数:21 提交数:74 难度:1 题目描述: 根据输入的半径值,计算球的体积. 输入描述: 输入数据有多组,每组占一行 ...

  5. 在VMware通过挂载系统光盘搭建本地yum仓库

    1.首先需要有一个VMware虚拟机: 2.进去虚拟机(这里用Linux下deCentOS进行演示): 3.用root账号进行登录,否则在根目录下没有一些操作权限: 4.打开终端: 5,输入命令“cd ...

  6. 精通awk系列(8):awk划分字段的3种方式

    回到: Linux系列文章 Shell系列文章 Awk系列文章 详细分析awk字段分割 awk读取每一条记录之后,会将其赋值给$0,同时还会对这条记录按照预定义变量FS划分字段,将划分好的各个字段分别 ...

  7. 工作日志,error parsing query: unable to find time zone

    工作日志,error parsing query: unable to find time zone 坑 Windows 系统使用influxdb数据库,在执行查询语句时提示 ERR: error p ...

  8. python: __future__的介绍

    __future__ 给旧版本python提供新版本python的特性例如: 在python2.X中可以使用print"" 也可以使用print() 但是加载这个print的新特性 ...

  9. Mysql 存储过程声明及使用

    存储过程(Stored Procedure):是一组用于完成特定数据库功能的sql语句集,该sql语句集经过编译后存储在数据库系统中,在使用的时候,用户通过调用指定已经定义好的存储过程并执行它,从而完 ...

  10. PowerMock学习(六)之Mock Final的使用

    Mock Final mockfinal相对来说就比较简单了,使用powermock来测试使用final修饰的method或class,比较简单,接口调用部分,还是service调用dao. 对于接口 ...