首页 > 其他分享 >2、关于网络中接受的数据如何序列化和反序列化的思考以及实现

2、关于网络中接受的数据如何序列化和反序列化的思考以及实现

时间:2023-10-28 22:34:43浏览次数:33  
标签:string 网络 思考 input byte 序列化 ascii 日志

1、背景介绍

因工作接触到半导体行业,主要负责 EAP 相关的东西,其中需要实现 SECS/GEM 协议,消息协议使用的是 SECS-II ,其中有一种数据类型是 A 类型,表示字符串类型。需要将接收到的 SECS 指令记录在日志中,以及反解析 SECS 指令。

我们知道,网络中接受到的数据都是 byte,需要自己根据规则来进行序列化和反序列化,像平常我们使用 HTTP 通信时,都是使用第三方通信库,底层的实现已经封装好了。

比如我们规定现在传输过来的数据表示的是ASCII码,那此时byte = 65 表示的是 字符A,我们把这一步叫做序列化,现在需要把 字符A 转换为byte = 65 ,就叫做反序列化。

知道上面的规则定义后,来看看现在的具体需求,需求蛮简单,就是在收到数据后,将其序列化后存储在日志后,方便后续的维护以及排查问题等,还有一个功能是可以将日志中的 SECS 指令导入到模拟器中(其实就是将 日志中的 SECS 指令反序列化为 byte 数据)。

2、数据如何序列化和反序列化的思考

知道需求后,就开始想想怎么来实现。

因为使用的是 golang 作为开发语言,所以接下来讲解都是基于 go ,不过不同语言关于这块应该大差不差。

最简单的想法就是使用 golang 的格式化字符串中的 %S 来序列化数据,这样简单也方便,其实大多数情况下是可以的,不过有一个问题就是,当遇到ASCII中的控制字符时,这种方式就不太行了。

比如 ASCII=10 (LF) - 换行:\n 格式化后,记录日志时就直接换行了,日志会乱七八糟的换行,这种可能还可以接受,如果接收到的数据是6 (ACK) - 应答:不常用 这样的时候,使用%s 得到的结果是看不错效果的,那更加谈不上反序列化了。

那怎么解决呢?

对于 go 有一种简便方式,使用 go 中的格式化方式 %q该值对应的单引号括起来的go语法字符字面值,必要时会采用安全的转义表示.。是不是看着一头雾水,其实就是使用特殊的字符串代替 ASCII 中的控制字符,接下来看看是如何表示的。

控制字符采用以下方式:

ascii: 0 <---> "\x00"
ascii: 1 <---> "\x01"
ascii: 2 <---> "\x02"
ascii: 3 <---> "\x03"
ascii: 4 <---> "\x04"
ascii: 5 <---> "\x05"
ascii: 6 <---> "\x06"
ascii: 7 <---> "\a"  
ascii: 8 <---> "\b"  
ascii: 9 <---> "\t"
ascii: 10 <---> "\n"
ascii: 11 <---> "\v"
ascii: 12 <---> "\f"
ascii: 13 <---> "\r"
ascii: 14 <---> "\x0e"
ascii: 15 <---> "\x0f"
ascii: 16 <---> "\x10"
ascii: 17 <---> "\x11"
ascii: 18 <---> "\x12"
ascii: 19 <---> "\x13"
ascii: 20 <---> "\x14"
ascii: 21 <---> "\x15"
ascii: 22 <---> "\x16"
ascii: 23 <---> "\x17"
ascii: 24 <---> "\x18"
ascii: 25 <---> "\x19"
ascii: 26 <---> "\x1a"
ascii: 27 <---> "\x1b"
ascii: 28 <---> "\x1c"
ascii: 29 <---> "\x1d"
ascii: 30 <---> "\x1e"
ascii: 31 <---> "\x1f"
ascii: 127 <---> "\x7f"

ascii: 92 <---> "\\"

知道了上面的规定后,那后面的编码就简单很多了,下面贴下自己的代码。

3、代码实现

3.1、byte转字符串的方式

package main

import (
	"fmt"
	"unicode"
)

var controlCharters = make([]byte, 33)
var controlCharterMaps = make(map[byte]byte)

func init() {
	for i := 0; i <= 127; i++ {
		if unicode.IsControl(rune(i)) {
			controlCharters = append(controlCharters, byte(i))
			controlCharterMaps[byte(i)] = byte(i)
		}
	}
}
func main() {
	var recvData []byte
	for i := 0; i <= 127; i++ {
		recvData = append(recvData, byte(i))
	}

	fmt.Println(fmt.Sprintf("%q", string(recvData)))
}

输出结果:

\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f

3.2、字符串转byte的方式

package main

import (
	"errors"
	"fmt"
	"strings"
	"unicode"
)

var controlCharters = make([]byte, 33)
var controlCharterMaps = make(map[byte]byte)

func init() {
	for i := 0; i <= 127; i++ {
		if unicode.IsControl(rune(i)) {
			controlCharters = append(controlCharters, byte(i))
			controlCharterMaps[byte(i)] = byte(i)
		}
	}
}
func main() {
	s := "\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f"
	unescaped, err := replaceControlCharacters(s)
	if err != nil {
		fmt.Printf("err: %s", err)
		return
	}

	fmt.Println([]byte(unescaped))
}

// replaceControlCharacters 将 sml 中表示为控制字符以及转义字符(\) 转换为 ascii 字符
func replaceControlCharacters(input string) (string, error) {

	controlCharMap := map[string]string{
		"\\\\":  "\\",
		"\\n":   "\n",
		"\\t":   "\t",
		"\\r":   "\r",
		"\\b":   "\b",
		"\\a":   "\a",
		"\\f":   "\f",
		"\\v":   "\v",
		"\\x00": "\x00",
		"\\x01": "\x01",
		"\\x02": "\x02",
		"\\x03": "\x03",
		"\\x04": "\x04",
		"\\x05": "\x05",
		"\\x06": "\x06",
		"\\x0e": "\x0e",
		"\\x0f": "\x0f",
		"\\x10": "\x10",
		"\\x11": "\x11",
		"\\x12": "\x12",
		"\\x13": "\x13",
		"\\x14": "\x14",
		"\\x15": "\x15",
		"\\x16": "\x16",
		"\\x17": "\x17",
		"\\x18": "\x18",
		"\\x19": "\x19",
		"\\x1a": "\x1a",
		"\\x1b": "\x1b",
		"\\x1c": "\x1c",
		"\\x1d": "\x1d",
		"\\x1e": "\x1e",
		"\\x1f": "\x1f",
		"\\x7f": "\x7f",
	}

	var output strings.Builder
	i := 0

	for i < len(input) {
		if input[i] == '\\' {
			escaped := false
			for key, value := range controlCharMap {
				if strings.HasPrefix(input[i:], key) {
					output.WriteString(value)
					i += len(key)
					escaped = true
					break
				}
			}
			if !escaped {
				return "", errors.New(fmt.Sprintf("illegal control character: %s, origin string: %s", string(input[i]), input))
			}
		} else {
			output.WriteByte(input[i])
			i++
		}
	}

	return output.String(), nil
}

输出方式:

[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127]

从上面可以看出,方式还是很简单的,其实还有很多其他方式可以达到序列化以及反序列化的方式,比如将收到的数据使用 base64 等方式,这样可以的。只不过因为我们的日志还需要给到客户看,使用 base64 并不友好(自己平时看也不方便),所以需要使用上面这种方式。

标签:string,网络,思考,input,byte,序列化,ascii,日志
From: https://www.cnblogs.com/huageyiyangdewo/p/17794781.html

相关文章

  • php-SER-libs-main反序列化靶场部分wp
    什么是序列化/反序列化,为什么要进行序列化/反序列化序列化:有时需要把一个对象在网络上传输,为了方便传输,可以把整个对象转化为二进制串,等到达另一端时,再还原为原来的对象,这个过程称之为串行化(也叫序列化)。反序列化:将序列化的结果还原PHP序列化:把对象转化为二进制的字符......
  • umich cv-5-2 神经网络训练2
    这节课中介绍了训练神经网络的第二部分,包括学习率曲线,超参数优化,模型集成,迁移学习训练神经网络2学习率曲线超参数优化模型集成迁移学习学习率曲线在训练神经网络时,一个常见的思路就是刚开始迭代的时候学习率较大,然后随着迭代次数的增加,学习率逐渐下降,下面我们就来介绍......
  • 系统集成知识点速记口诀-进度网络分析
    关键路径不受约,最长持续时间段,最小浮动和最短,资源优化受约束,平衡延长可用性,平滑不会改进度,范围不变用压缩,加班赶工增成本,快速跟进加风险,假设不成变风险,应急储备来帮忙,蒙特卡洛是(S)曲线,挣值分析也可用,提前是负滞后正。......
  • 企业网络建设之二层网络技术优化方案
    一、概述目前绝大部分大型网络的网络设备数量较多,网络结构较为复杂,然而大部分网络出现问题时,多数是由于二层协议造成的网络中断,影响规模较大,导致用户无法正常业务及上网办公等问题,其实目前的二层网络技术已有一定积累,能够解决绝大部分的二层网络问题,为此结合大型二层网络架构提供技......
  • 抓住重点的思考能力如何训练,批判性思维和金字塔原理
    读教科书感觉有点晦涩,阅读英文文章有时候不能抓住重点,感觉需要训练自己这方面的能力,多看看纸质书。其实我觉得我和别人交流的时候,有那种答非所问的倾向,说明我不善于抓住重点。当然一方面是因为我可能要忽略那些我不想回答的东西,另一方面就是思考能力的缺乏了为什么有人思考问题......
  • 计算机网络:1-3章简答详解
    1.简述计算机网络采用层次结构的主要优点。计算机网络采用层次结构的主要优点包括以下几个方面:模块化设计:层次结构将整个网络系统分解为多个层次,每个层次负责特定的功能。这种模块化设计使得网络的开发、维护和扩展更加容易,因为每个层次可以独立地进行设计和实现。同时,模块化......
  • 运维管理软件:网络设备监控的价值与实现
      随着企业业务的不断发展,各种应用系统的不断上线,网络设备的数量和复杂性也在不断增加。在这样的背景下,如何保证网络设备的稳定性和安全性已成为企业必须面对的问题。而网络设备监控作为一体化运维管理软件的重要组成部分,对于提高企业运维管理水平具有重要的意义。本文将围绕监......
  • umich cv-5-1 神经网络训练1
    这节课中介绍了训练神经网络的第一部分,包括激活函数的选择,权重初始化,数据预处理以及正则化方法训练神经网络1激活函数数据预处理权重初始化正则化方法激活函数这部分主要讨论我们之前提到的几种激活函数的利弊:首先我们看sigmoid函数,这种激活函数有着激活函数中常见......
  • Java反序列化之URLDNS链
    Java反序列化之URLDNS链一、漏洞简介URLDNS链是java原生态的一条利用链,通常用于存在反序列化漏洞进行验证的,因为是原生态,不存在什么版本限制。该链有以下三个特点:不限制jdk版本,使用Java内置类,对第三方依赖没有要求目标无回显,可以通过DNS请求来验证是否存在反序列化漏洞URLD......
  • php反序列化2023/10/28
    题目来源:[第五空间2021]pklovecloud题目代码如下:<?phpinclude'flag.php';classpkshow{functionecho_name(){return"Pkverysafe^.^";}}classacp{protected$cinder;public......