文档章节

应用层协议设计的反面教材

zhangyujsj
 zhangyujsj
发布于 2016/09/13 16:52
字数 1321
阅读 129
收藏 0

1 糟糕设计之一:消息格式“包头+数据+包尾”

  与UDP不同,TCP通信属于流式通信,没有消息边界,所以需要应用层自行对报文进行界定分离。实际项目1中,包头为{{两个字节,包尾为}}两个字节,例如{{t=123}}。其格式为:

  开始边界+消息1+结束边界+开始边界+消息2+结束边界+开始边界+消息3+结束边界+....

  由于TCP是安全的传输层协议,除非特别需要,应用层无需再做校验。消息边界只需要一个标识即可,基本格式为:

  消息1+边界+消息2+边界+消息3+边界+...

  无论从节约网络带宽,还是从简化报文解析代码,第一种设计都是非常的愚蠢!

  无独有偶,项目2中基于串口的通信应用层协议也采用了这种设计格式。

  当问其设计人员为何如此设计时,说一直就是这么设计的,自己也不知道这么设计的原因,还美滋滋地说一直没有什么问题,真想揍他一拳。

  2 糟糕设计之二:用结构体代码而不是文本描述消息结构

  项目2中,根本无协议的描述文本,只有一个包含结构体定义的头文件供协议的使用者参考。

  通信就会涉及到多个机器,所以通信协议必须要能跨平台。而我们知道

  struct A

  {

  char x;

  int y;

  };

  在不同编译器,不同平台,不同编译选项下会有不同的二进制布局。况且协议使用者也可能看不懂C系语言代码。更搞笑的是,头文件中竟然没有强制结构体单字节对齐。

  问到协议的设计者设计思路时,说我们公司一直这样啊,一直没问题啊。之所以没有问题,是因为使用这个协议的所有机器都是同一CPU型号,同一开发环境,同一操作系统。

  3 糟糕设计之三:传送二进制浮点数

  浮点数的二进制格式并不是只有一种,不同平台采用不同的方式存放。这要比大端小端的整数差别更加严重。所以跨平台传送二进制浮点数是非常不安全的。而在项目2中,消息中大量使用了二进制浮点数。

  要传送浮点数,通常有两种解决方式:

  文本化。也就是传送描述浮点数的字符串,我们知道字符串是完全跨平台的,尤其是在UTF-8这样全球统一字符编码的情况下。

  转换为整数。例如1.2,可以用整数12代替,只是要规定单位为0.1即可。

  4 糟糕设计之三:大量备用字段

  项目二的消息结构体类似如下:

  struct A

  {

  char name[16];

  int age;

  int spare1;

  short spare2;

  short spare3;

  int spare4;

  };

  大量的备用字段充斥在结构体中。少量的备用字段可以理解,如此大量的后备力量,真是深远谋虑啊。真不知道协议使用者在看到spare时会不会吐。如果真的需要这么多备用字段,完全可以重新定义一个消息结构了。

  5 糟糕设计之四:照猫画虎的握手和校验

  握手和校验是保证安全完整通信的基本手段,但是其实现却非常不简单,看看TCP的实现代码就知道了,需要考虑各种异常情况。项目二中串口设备和主机之间照猫画虎地定义了一个握手协议。开机后 设备向主机一直发送AA,主机收到AA后向设备发送AA,设备收到AA后向主机发送55,主机收到55后向设备发送55。这个简单的握手存在很多问题,随便说几个:

  完全没有必要握手。一般的串口设备无需知道主机的工作状态,主机如果想了解设备状态,发个询问报文即可。

  如果主机发送AA后程序退出,那么串口设备永远也等不到来自主机的55。

  如果主机中途关掉,在运行时可能收到来自串口设备的AA,而此时的AA其实只是消息报文的一个字节,而不是握手信号。

  只要仔细想想,还有很多类似的情况需要处理。而且实际使用过程中,确实发生了上面的情况,致使必须重启串口设备或主机。

  还是项目2中,基于UDP的应用层协议自行设计了校验。其实这也无可厚非,比如著名的tftp就是这样的协议。只是设计者考虑不周,各种问题频出,最终的结果是这些校验字段根本就没有实际使用,白白浪费了网络带宽。需要说明的是,这个协议的设计者还是国内很大的一家公司,当然是国企,你懂的。

本文转载自:http://m.netofthings.cn/show.aspx?articleid=6679

共有 人打赏支持
zhangyujsj
粉丝 24
博文 358
码字总数 224241
作品 0
广州
私信 提问
我就当反面教材吧

1. 个人简介 从2015年开始投入工作,到现在快三年时间都在干运维工作,从事的都是低端的运维。这三年里,自学了Java编程,然后没坚持下去,又学了学html,也只是粗浅的掌握。感觉就是东学西学...

枕着稻香
2017/12/23
0
1
我想要的语言

一,要远离汇编。在我眼里任何接近机器层次的是汇编,比如内存管理,比如文件读写。 二,不使用class这种法克东西。class是一种不仅帮不了设计对象,反而还阻碍设计对象的东西。任何有class...

句龙胤
2016/06/05
98
2
《TCP IP详解卷1:协议 》原书第2版下载

本书是《TCP/IP详解》第1卷的第2版,主要讲述TCP/IP协议,结合大量实例讲述TCP/IP协议族的定义原因,以及在各种不同的操作系统中的应用及工作方式。第2版在保留Stevens卓越的知识体系和写作风...

ddddd8
2017/12/15
0
0
要旗帜鲜明的打到 @eechen 这种mysqler -- 两个凡是

过去几年, 两个凡是已经落地一系列产品线 @eechen 不但不坚持和提倡两个反思, 一意孤行,还在弄mysql的单表CRUD 大家要以 @eechen 作为反面教材, 时刻警醒 过去提倡和坚持两个凡是的, 已...

宏哥
2016/08/30
503
6
线程和进程区别

用简单的例子说明, 你如果想同时拨电话给 A, B,那么可以这么做. 用两个电话, 分别拨出,然后分别对他们说话 -- 多线程设计,线程共享全局数据 找小张,小王,让他们分别打电话给A,B -- 多进程设计...

宏哥
2012/06/30
3K
32

没有更多内容

加载失败,请刷新页面

加载更多

大数据剖析热点新闻:996、巴黎圣母院、奔驰维权为什么成为本周热搜

智能大数据专家表示:每一段重要的时期都会有一串隐秘的数字密码,请往下看: 本周共有50条新闻,作为嗅嗅的样本进行数据分析,得出以下统计图: 1.新闻热词折线统计图 在新闻标题及正文中,...

forespider
23分钟前
0
0
Coding and Paper Letter(六十四)

资源整理。 1 Coding: 1.交互式瓦片编辑器。 tile playground 2.R语言包autokeras,autokeras的R接口。autokeras是一个开源的自动机器学习的软件。 autokeras 3.斯坦福网络分析平台,用于网络...

胖胖雕
今天
1
0
最简单的cd命令是个大坑!

BASH Shell 是大多 Linux 发行版的默认 shell,BASH 有一些自己的内置命令,cd 就是其中的一个。 在centos6里面,系统中不存在 cd 的二进制文件。但是你仍然可以运行该命令,这是因为 cd 是 ...

gaolongquan
今天
1
0
spring获取bean的几种方式

使用jdk:1.8、maven:3.3.3 spring获取Bean的方式 pom.xml文件内容: <?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="......

Vincent-Duan
今天
3
0
一段话系列-Linux中IO的同步、异步、阻塞、非阻塞

首先我们框定一下背景,我们探讨的是Linux系统下的IO模型。 同步和异步是针对内核操作数据而言的,同步是指内核串行顺序操作数据,异步是指内核并行(或并发)操作数据,然后通过回调的方式通...

EasyProgramming
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部