1、OSI 七层模型及以太网协议族

以太网协议族

2、常见车载应用层协议

车外网常见 MQTT、HTTP、FTP、DNS、DHCP

车内网常见 IPCP、SOMEIP、DOIP、DDS


3、HTTP 协议简介

HTTP 全称为 HyperText Transfer Protocol,即超文本传输协议,它是架设在 TCP (或 UDP )协议之上的应用层协议。

HTTP/2 与 HTTP/1.1 有几处关键的差异点:

- HTTP/2 是二进制协议而不是文本协议。不再可读,也不可无障碍的手动创建。

- HTTP/2 是一个多路复用协议。并行的请求能在同一个连接中处理,移除了 HTTP/1.x 中顺序和阻塞的约束。

- HTTP/2 压缩了请求头。因为请求头在一系列请求中常常是相似的,其降低了传输重复数据的成本。

- 允许服务器在客户端缓存中填充数据,通过一个叫服务器推送的机制来提前请求。


HTTP/3:

HTTP/3 有着与 HTTP 早期版本的相同语义,但在传输层部分使用 QUIC 而不是 TCP。QUIC 旨在为 HTTP 连接设计更低的延迟。类似于 HTTP/2,它是一个多路复用协议,但是 HTTP/2 通过单个 TCP 连接进行数据传输,所以在 TCP 层处理数据包丢失检测和重传会阻塞所有的数据流,而 QUIC 通过 UDP 运行多个数据流,并为每个数据流独立实现数据包丢失检测和重传,因此如果某个数据流发生错误,只会阻塞相应的数据流,其他数据流仍可正常传输。

注意:从 HTTP/2 开始,与 HTTP/1.1 存在较大差异,以下介绍的内容主要针对 HTTP/1.1

以太网报文结构

URI & URL & URN

Web 上可用的每种资源( HTML文档、图像、音频、视频片段、程序等)都由一个通用资源标识符(Uniform Resource Identifier,简称 "URI")进行标识,为了进一步定位资源所在的位置,便衍生出 URL 和 URN 两种表达方式。

URI

简单理解:URN 作用就好像一个人的名字,URL 就像一个人的地址。换句话说:URN 确定了东西的身份,URL 提供了找到它的方式。

在开发 HTTP 相关的接口时,用的最多的是利用 URL 来表达信息,所以下面重点介绍 URL。

针对 HTTP 协议的 URL 常见定义格式如下:

scheme://host[:port]/path/…/[?query-string][#anchor]

  • scheme:协议类型,如 http、https 等。
  • host:HTTP 服务器的 IP 地址或者域名。
  • port:HTTP 服务器的默认端口是 80,在这种情况下端口号可以省略。如果使用了别的端口,则必须显示指明。
  • path:被访问资源的路径
  • query-string:发送给服务器的查询参数
  • anchor:锚点定位,通常此信息是不会被服务端处理的,一般是用在客户端对服务器响应的资源做进一步定位

示例:

URL示例

MIME

MIME(Multipurpose Internet Mail Extensions) 是描述消息内容类型的标准,用来表示文档、文件或字节流的性质和格式。MIME 的组成结构非常简单,由类型与子类型两个字符串组成,中间用 / 分隔,即 type/subtype。

MIME 类型对大小写不敏感,但是传统写法都是小写。

常见 MIME 类型如下表所示:

type

MIME

含义

text

text/plain, text/html, text/css, text/javascript

表明资源是普通文本,理论上是人类可读的

image

image/gif, image/png, image/jpeg, image/bmp, image/webp, image/x-icon

表明资源是某种图像。不包括视频,但动态图(如动态 gif)也划归于 image 类型

audio

audio/midi, audio/mpeg, audio/webm, audio/ogg, audio/wav

表明资源是某种音频文件

video

video/webm, video/ogg

表明资源是某种视频文件

application

application/octet-stream, application/pkcs12, application/xml, application/json, application/pdf, application/x-www-form-urlencoded

表明资源是某种二进制数据

multipart

multipart/form-data

由多种数据格式组成,常用于文件的上传


HTTP 请求报文结构

HTTP 请求报文

  • 请求行【request-line】: 由请求方式、请求地址和 HTTP 协议版本组成
  • 请求头【headers】: 消息报头,用于客户端携带附加信息,允许多个请求头存在,采用 key:value 的形式进行声明
  • 空行【blank-line】: 位于请求行和请求数据之间,空行是必须的
  • 请求体【body】: 非必须,通常只对 POST 请求方式有效


常用的 HTTP 请求头字段

header

含义

Host

客户端请求的域名

Connection

告诉服务端,处理完本请求后,是否关闭连接

User-Agent

客户端使用的浏览器或 APP 类型及版本

Accept

客户端支持哪些 MIME 类型的文档

Accept-Encoding

客户端支持的编码类型,如 gzip

Accept-Language

客户端支持的语言类型,如 zh-CN,en-US

Referer

指明客户端从哪个网页发起请求的,常用于防盗链

Cache-Control

指定缓存机制

Cookie

携带 Cookie 信息


HTTP 响应报文结构

HTTP 响应报文

  • 响应行【status-line】: HTTP 协议版本、响应状态码和状态描述信息
  • 响应头【headers】: 响应报头,用于服务端携带附加信息,允许多个响应头存在,采用 key:value 的形式进行声明
  • 空行【blank-line】:位于响应头和响应实体之间,空行是必须的
  • 响应体【body】:携带服务器返回给客户端(如浏览器)的数据


常用的 HTTP 响应头字段

header

含义

Allow

表明服务器支持哪些请求方法,如 GET,POST,HEAD 等

Content-Encoding

响应内容编码方法

Content-Type

响应内容属于哪种 MIME 类型

Content-Length

响应内容的长度

Date

当前 GMT 时间

Expires

响应内容过期时间,过期后将不再缓存内容

Last-Modified

文档的最后改动时间

Location

告诉客户端到哪里获取文档,一般用于重定向

Refresh

浏览器在多少秒后刷新文档

Server

服务器名字

Set-Cookie

设置和页面关联的 Cookie


常见响应状态码

可通过响应状态码初步定位请求故障原因

status code

description

含义

200

Ok

客户端请求成功

302

Found

请求重定向

400

Bad Request

客户端请求有语法错误,不能被服务器所理解

401

Unauthorized

请求未经授权

403

Forbidden

服务器收到请求,但拒绝提供服务

404

Not Found

请求资源不存在,eg:输入错误的URL

405

Method Not Allowed

请求方式不支持

500

Internal Server Error

服务器内部发生不可预期的错误

502

Bad Gateway

服务器网关异常

503

Server Unavailable

服务器当前不能处理客户端的请求,一段时间后可能恢复正常


HTTP 请求方法

HTTP/1.0:定义了三种请求方法,即 GET、POST、HEAD

HTTP/1.1:新增了五种请求方法,分别为 OPTIONS、PUT、DELETE、TRACE 和 CONNECT

其中 GET 和 POST 是最常用的,其次是 HEAD 和 OPTIONS;像 PUT 和 DELETE 属于危险方法,服务器一般都会禁用;TRACE 和 CONNECT 则非常少见

GET 请求

获取 URL 指定的资源,GET 请求方法是最简单的也是最常用的。使用 GET 方法时,可以将请求参数和对应的值附加在 URI 后面,利用一个问号 (“?”) 将资源的 URI 和请求参数隔开,各个请求参数对之间使用符号 (“&”) 隔开,如 /index?username=jmlee&password=123123。

POST 请求

一般用于提交数据(如提交表单或上传文件)。表单提交使用 POST 相比 GET 安全性更高,且 GET 的 URL 有长度限制,导致携带的数据大小受限。上传大文件必须使用 POST 。

HEAD 请求

与 GET 用法相同,但没有响应体,使用场合没有 GET 多。如下载前使用 HEAD 发送请求,通过 Content-Length 响应字段来了解网络资源的大小;或通过 Last-Modified 响应字段来判断本地缓存资源是否需要更新。

OPTIONS 请求

通过 OPTIONS 方法,可以向服务器询问具体支持哪些方法、通知客户端服务器会使用什么样的方法来处理一些特殊资源。可以说这是一个探测性的方法,客户端通过该方法可以在不访问服务器上实际资源的情况下就知道处理该资源的最优方式。此请求方法常出现在跨域请求的场景中。

PUT 请求

用于向指定资源位置上传其最新内容(原来没有就上传,有就上传并覆盖原来的内容)。

DELETE 请求

请求服务器删除 URI 所标识的资源。

TRACE 请求

回显服务器收到的请求,主要用于测试或诊断,比较少见。

CONNECT 请求

开启与所请求资源之间的双向沟通通道,它可以用来创建隧道。


重点介绍下 GET 和 POST 的区别:

对比项

GET

POST

后退按钮/刷新

无影响

数据会被重新提交(浏览器应该告知用户数据会被重新提交)

书签

可收藏为书签

不可收藏为书签

缓存

能被缓存

不能缓存

编码类型

application/x-www-form-urlencoded

application/x-www-form-urlencoded or multipart/form-data

历史

参数保留在浏览器历史中

参数不会保存在浏览器历史中

对数据长度的限制

当发送数据时,GET 方法通过 URL 添加数据,而 URL 的长度是受限制的(不同浏览器大小存在差异)

无限制,数据会放在请求体中

对数据类型的限制

只允许 ASCII 字符

没有限制,允许二进制数据

安全性

与 POST 相比,GET 的安全性较差,因为所发送的数据是 URL 的一部分。 在发送密码或其他敏感信息时千万不要使用 GET

POST 相比 GET 更安全,因为参数不会被保存在浏览器历史或 web 服务器日志中

可见性

数据在 URL 中对所有人都是可见的

数据不会显示在 URL 中,相对安全


HTTP 的连接管理

在 HTTP/1.x 里有多种连接模型,分别是:短连接、长连接和 Pipeline,其中长连接模型和 Pipeline 模型是从 HTTP/1.1 开始新增的。

  • 短连接模型:每次请求响应之后便关闭连接,相对性能较低。
  • 长连接模型:保持连接以完成多次连续的请求,减少不断重新建立连接的时间。
  • Pipeline 模型(也称流水线模型):多个连续的请求甚至都不用等待立即返回就可以被发送,这样就减少了耗费在网络延迟上的时间。

现在普遍使用的是 HTTP/1.1 的长连接模型,因为 Pipeline 模型存在一些缺陷:

1. 中间经历的代理服务器不可预知,一旦代理服务器不支持 Pipeline 模型,则整个请求链条将受限于代理服务器的性能瓶颈。

2. 正确实现 Pipeline 是比较复杂的:传输中的资源大小、多少有效的 RTT 会被用到以及有效带宽都会直接影响到 Pipeline 的性能。如果无法明确上述参数,重要的消息可能被延迟到不重要的消息后面。

3. 并不是所有的 HTTP 请求都能使用 Pipeline 模型:只有幂等方式,比如 GET、HEAD、PUT 和 DELETE 能够被安全地重试。如果有故障发生时,Pipeline 的内容要能被轻易的重试。

4. Pipeline 受制于队头阻塞(HOL)问题

HTTP 连接模型


HTTP 交互流程

一次完整的 HTTP 请求大致流程如下:

1、客户端和服务端建立连接

2、客户端发送请求

3、服务端接收请求,将处理结果响应给客户端

4、关闭客户端和服务端的连接(HTTP1.1后不会立即关闭连接)

存粹的 HTTP 协议都是基于请求-响应模型进行开发的,通常都由 Client 端主动发起请求,Server 端回复响应

示例:一个 HTTP GET 请求报文格式如下

GET http://developer.mozilla.org/en-US/docs/Web/HTTP/Messages HTTP/1.1
Host: developer.mozilla.org
Accept-Language: fr


4、SOMEIP 与 HTTP 的选择

SOA (Service Oriented Architecture) 是什么?

SOA 其实是一种软件设计理念,所有的功能模块都是建立在服务之上,而服务可简单理解为一系列软件接口的集合,如下定义:

"AirCondition-Service": [ // 空调服务
    "getTempture": { 接口定义 },  // 获取空调温度
    "setTempture": { 接口定义 },  // 设置空调温度
    ...
]

"Power-Service": [  // 动力服务
    "getSpeed": { 接口定义 },  // 获取车速
	  "getTorque": { 接口定义 }, // 获取扭矩
	  ...
]

"GNSS-Service": [  // 位置服务
	 "getCurrentPosition": { 接口定义 }, // 获取位置信息
	 "getRealTime": { 接口定义 },
	 ...
]

我们可以将整车所有的 ECU 看成是一个整体,此时每个 ECU 即为一个个分布式模块,每个服务独立部署(持续集成,灰度发布,热更新)。

当服务划分的粒度足够小,也被称为微服务,即每个服务所承担的功能足够单一,符合软件开发高内聚低耦合的特点

为了实现 SOA,就不得不提 RPC,那 RPC (Remote Procedure Call) 是什么?

直译过来叫远程过程调用,也就是某个请求方(调用者)在本地调用某一软件接口,所调用的接口执行完毕之后返回结果给请求方,在请求方看来整个过程看似和本地方法调用一样。为了实现远程过程调用,通常需实现如下软件架构。

RPC 调用

RPC 一定是要基于以太网吗?

答案是否定的,我们知道传统的 CAN 是基于信号的形式进行通讯交互的,但只要我们在信号的基础上新增一个序列化层,完全可以将其改造成基于服务的形式,只是 CAN 承载的数据负载有限,在中间添加一个序列化层对于上层应用而言成效甚微,用户还是无法随意定义数据负载的内容。举例说明 :

如下信号结构1:

{
    char[2] name;
    int age;
    bool gender;
}

经过序列化层处理之后排列到CAN数据场后的结果如下(理想情况下),总共占用7个字节,还剩1个字节用于存放数据。

字段名

name

age

gender

占用字节数

2byte

4byte

1byte

一旦将其改成信号结构2,序列化层处理之后一下子就把数据场用完了,显然很不灵活,即便采用 CANFD(数据场64Byte)等协议,改善也不是很明显。

{
    char[8] name;
    int age;
    bool gender;
}   

字段名

name

age

gender

占用字节数

8byte

无法承载

无法承载

因此 RPC 需要建立在数据场能够承载足够的内容且传输速率高的通讯协议,环顾现有的通讯技术,显然以太网是比较好的选择,其数据场可承载较大的数据(通常是 1500Byte - 协议头长度),且传输速率高,支持点对点通信,所以现在的 RPC 通常都是建立以太网之上。

我们知道在车载领域,用的比较多的应用层协议有 SOMEIP 和 HTTP,那到底该如何选择 SOMEIP 和 HTTP 呢?

SOMEIP 与 HTTP 对比:

对比项

HTTP 1.1

SOMEIP

序列化方式

文本传输(效率较低)

二进制传输

支持长连接

支持服务发现

支持订阅或消息推送

资源消耗

相对较大

适中

传输数据量

传输层协议

TCP

UDP/TCP

适用范围

各行各业

车载领域

总结:对于车内网的控制器,可采用轻量化的 SOMEIP 协议,对于支持上网的控制器,要求即支持 SOMEIP,也支持 HTTP。HTTP 更多针对请求响应的场景,常以 Restful 的形式表示接口含义,SOMEIP 不仅支持请求响应,还支持服务端周期性通知,更适合一些实时性要求较高的场景。