【0】复习
Modbus:modbus tcp modbus rtu
Modbus TCP:
特点:主从问答(控制 采集信息) 应用层协议(基于TCP通信)、默认端口502
组成:报文头(7 事物2 协议2 长度2 单元表示1) 功能码(01 02 03 04 05 06 15 16) 数据
总结:读数据、写单个 写多个
【1】Modbus RTU
-
与Modbus TCP的区别
在一般工业场景使用modbus RTU的场景还是更多一些,modbus RTU基于串行协议进行收发数据,包括RS232/485等工业总线协议。
与modbus TCP不同的是RTU没有报文头MBAP字段,但是在尾部增加了两个CRC检验字节(CRC16),因为网络协议中自带校验,所以在TCP协议中不需要使用CRC校验码。
RTU和TCP的总体使用方法基本一致,只是在创建modbus对象时有所不同,TCP需要传入网络socket信息;而RTU需要传入串口相关信息。
2.特点
- 遵循主从问答的通信方式
- 采用串口的方式进行通信
设置串口参数时要求:
波特率为9600(波特率是指每秒钟传输的比特数)
8位数据位 (数据位是指每个字符中包含的比特数)
1位停止位 (停止位是指在每个字符传输结束后添加的比特数)
无流控 (流控是指在数据传输过程中控制数据流量的一种机制,无流控表示在该设置下没有额外的控制机制来控制数据流量)
3.modbus rtu协议格式
地址码 功能码 数据 校验码
地址码(1字节):从机ID
功能码(1字节):同modbus tcp(01 02 03 04 05 06 0f 10H)
数据:起始地址、地址、数量、数据、字节计数
校验码(2字节):对地址码、功能码、数据进行校验,由函数生成
4.练习题
主机--》从机:
01 03 00 00 00 01 84 0a
01 :从机id
03 :功能码
00 00 :起始地址
00 01 :数量
84 0a:校验码
从机--》主机:
01 03 02 0014 b8 44
01 :从机id
03 :功能码
02 :字节计数
00 14 :数据
b8 44 :校验码
参考示例:值得收藏 Modbus RTU 协议详解-CSDN博客
【2】Modbus 库
官方文档:libmodbus
1.库的安装
库的安装配置(共四步)
1. 在linux中解压压缩包
tar -xvf libmodbus-3.1.7.tar.gz
2. 进入源码目录,创建文件夹(存放头文件、库文件)
cd libmodbus-3.1.7
mkdir install
3. 执行脚本configure,进行安装配置(指定安装目录)
./configure --prefix=$PWD/install
4. 执行make和make install
make//编译
make install//安装
执行完成后会在install文件夹下生产对应的头文件、库文件件夹install,用于存放产生的头文件、库文件等
库的使用
要想编译方便,可以将头文件和库文件放到系统路径下
sudo cp include/modbus/*.h /usr/include
sudo cp lib/* -r /lib -d
后期编译时,可以直接gcc xx.c -lmodbus
头文件默认搜索路径:/usr/include 、/usr/local/include
库文件默认搜索路径:/lib、/usr/lib
2. 函数接口
modbus_t* modbus_new_tcp(const char *ip, int port) 功能:以TCP方式创建Modbus实例,并初始化 参数: ip :ip地址 port:端口号 返回值:成功:Modbus实例 失败:NULL int modbus_set_slave(modbus_t *ctx, int slave) 功能:设置从机ID 参数: ctx :Modbus实例 slave:从机ID 返回值:成功:0 失败:-1 int modbus_connect(modbus_t *ctx) 功能:和从机(slave)建立连接 参数: ctx:Modbus实例 返回值:成功:0 失败:-1 void modbus_free(modbus_t *ctx) 功能:释放Modbus实例 参数:ctx:Modbus实例 void modbus_close(modbus_t *ctx) 功能:关闭套接字 参数:ctx:Modbus实例 int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest) 功能:读取线圈状态,可读取多个连续线圈的状态(对应功能码为0x01) 参数: ctx :Modbus实例 addr :寄存器起始地址 nb :寄存器个数 dest :得到的状态值 返回值:成功:读到的数量 失败:-1 int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest) 功能:读取输入状态,可读取多个连续输入的状态(对应功能码为0x02) 参数: ctx :Modbus实例 addr :寄存器起始地址 nb :寄存器个数 dest :得到的状态值 返回值:成功:返回nb的值 失败:-1 int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest) 功能:读取保持寄存器的值,可读取多个连续保持寄存器的值(对应功能码为0x03) 参数: ctx :Modbus实例 addr :寄存器起始地址 nb :寄存器个数 dest :得到的寄存器的值 返回值:成功:读到寄存器的个数 失败:-1 int modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest) 功能:读输入寄存器的值,可读取多个连续输入寄存器的值(对应功能码为0x04) 参数: ctx :Modbus实例 addr :寄存器起始地址 nb :寄存器个数 dest :得到的寄存器的值 返回值:成功:读到寄存器的个数 失败:-1 int modbus_write_bit(modbus_t *ctx, int addr, int status); 功能:写入单个线圈的状态(对应功能码为0x05) 参数: ctx :Modbus实例 addr :线圈地址 status:线圈状态 返回值:成功:1 失败:-1 int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *src); 功能:写入多个连续线圈的状态(对应功能码为15) 参数: ctx :Modbus实例 addr :线圈地址 nb :线圈个数 src :多个线圈状态 返回值:成功:写入的数量 失败:-1 int modbus_write_register(modbus_t *ctx, int addr, int value); 功能: 写入单个寄存器(对应功能码为0x06) 参数: ctx :Modbus实例 addr :寄存器地址 value :寄存器的值 返回值:成功:1 失败:-1 int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src); 功能:写入多个连续寄存器(对应功能码为16) 参数: ctx :Modbus实例 addr :寄存器地址 nb :寄存器的个数 src :多个寄存器的值 返回值:成功:写入的数量 失败:-1
float modbus_get_float_dcba(const uint16_t *src)
功能:读取浮点类型的数据
参数:src:读到数据的存放数组
返回值:转换后的浮点类型
【3】HTTP协议
1.http简介
HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于Web Browser(浏览器)到Web Server(服务器)进行数据交互的传输协议。
HTTP是应用层协议
HTTP是一个基于TCP通信协议传输来传递数据(HTML 文件, 图片文件, 查询结果等)
HTTP协议工作于B/S架构上,浏览器作为HTTP客户端通过URL主动向HTTP服务端即WEB服务器发送所有请求,Web服务器根据接收到的请求后,向客户端发送响应信息。
HTTP默认端口号为80,但是你也可以改为其他端口
2.http特点
HTTP是无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并给客户应答后,即断开连接。采用这种方式可以节省传输时间。
(需要注意一点:HTTP协议本身是无连接的,即每个请求和响应都是独立的。但是http是基于TCP协议的连接管理方式,想要与长连接和短连接用于优化HTTP请求和响应的传输效率。长连接是指在一个TCP连接上可以发送多个HTTP请求和响应,而不需要每次请求都建立和关闭一个新的TCP连接。短连接是指每个HTTP请求和响应都使用一个新的TCP连接。)
HTTP是媒体独立:这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。客户端以及服务器指定使用适合的MIME-type内容类型。
HTTP是无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。无状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
HTTP 协议同学可能都知道,HTTP 协议是以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了 Web 浏览器和网站服务器之间的传输报文,就可以直接读懂其中的信息,因此 HTTP 协议不适合传输一些敏感信息,比如信用开号、密码等。 为了解决 HTTP 协议的这一缺陷,需要使用另一种协议:HTTPS 协议。 HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的 HTTP 通道,简单来说就是 HTTP 的安全版。即在 HTTP 下加入 SSL 协议,SSL 依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。 HTTPS 和 HTTP 的区别主要为以下三点: ● 1.http 是超文本传输协议,信息是明文传输;https 协议是由 http + ssl 协议构建的可进行加密传输、身份认证的网络协议,信息是密文传输,比 http 协议安全。 ● 2.https 协议需要到 ca 申请证书,一般免费证书很少,需要缴费 ● 3.http 和 https 使用的默认端口也不一样,前者是 80,后者是 443
3.http协议格式
区分地址栏
1)请求数据格式
客户端发送一个HTTP请求到服务器的请求消息包括以下格式:请求行、请求头部、空行(把数据和前面分开)和请求数据四个部分组成,下图给出了请求报文的一般格式。
请求行:
请求行是由请求方法字段、url字段、http协议版本字段3个部分组成。请求格式如:
url:路径
http的请求方式:
http协议中共定义了八种数据的请求方法。分别是:OPTIONS、HEAD、GET、POST、PUT、DELETE、TRACE、CONNECT;我们在实际应用中常用的也就是 get 和 post,其他请求方式也都可以通过这两种方式间接的来实现。
(增POST 删DELETE 改PUT 查GET)
格式:请求方法 请求URL HTTP版本
示例:GET /api/temperature HTTP/1.1
HTTP/1.0:每次请求需建立新的 TCP 连接(短连接),效率低。
HTTP/1.1:默认使用 “持久连接”(一个 TCP 连接可处理多个请求),支持管道化(客户端可连续发送多个请求),新增缓存机制(如Cache-Control)。
HTTP/2:引入二进制帧、多路复用(一个 TCP 连接并行处理多个请求,避免队头阻塞)、服务器推送等,大幅提升性能。
HTTP/3:基于 QUIC 协议(UDP 之上的可靠传输),解决 TCP 队头阻塞问题,进一步优化弱网环境下的性能。
GET方法和POST方法的区别? 都是请求数据格式
Post(处理数据,服务器处理完后返回客户端,一般处理复杂一点的数据)
GET通常用来从服务器上获得数据,而非修改信息;POST用来向服务器传递数据。
- 请求数据时带参数时;GET请求的数据会附加在URL之后,以?分割URL和传输数据,多个参数用&连接。POST请求会把请求的数据放置在HTTP请求包的包体中。因此,GET请求的数据会暴露在地址栏中,而POST请求则不会。
get请求可能没有请求数据,也可能有请求数据,但是请求数据不会在请求格式里请求数据处,会在地址栏中(也会在请求格式的url后面以?分割),post请求,有数据会在请求格式里请求数据处,一定不会在地址栏中(也不会在url之后跟着)
2、 传输数据的大小;在HTTP规范中,没有对URL的长度和传输的数据大小进行限制。但是在实际开发过程中,对于GET,特定的浏览器和服务器对URL的长度有限制。因此,在使用GET请求时,传输数据会受到URL长度的限制。对于POST,由于不是URL传值,理论上是不会受限制的,但是实际上各个服务器会规定对POST提交数据大小进行限制,Apache、IIS都有各自的配置。
3、GET请求返回的内容可以被浏览器缓存起来。而每次提交的POST,浏览器在你按 下F5的时候会跳出确认框,浏览器不会缓存POST请求返回的内容
4、GET对数据进行查询,POST主要对数据进行增删改!简单说,GET是只读,POST是写
5、对于参数的数据类型,get只接受ASCII字符,而post没有限制。
请求头部
也被称作消息报头,请求头是由一些键值对组成,每行一对,关键字和值用英文冒号“:”分隔。允许客户端向服务器发送一些附加信息或者客户端自身的信息,典型的请求头如下:
Accept:作用:描述客户端希望接收的响应数据类型;示例:Accept:text/html
Accept-Charset:作用:浏览器可以接受的字符编码集;示例:Accept-Charset:utf-8
Connection:作用:表示是否需要持久连接,注意HTTP1.1默认进行持久连接;示例:Connection:close
Content-Length:作用:请求的内容长度:示例:Content-Length:348
Content-Type:作用:描述客户端发送的 body 数据类型
Accept-Language:作用:浏览器可接受的语言;示例:Accept-Language:en
空行
最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头。
请求体
请求数据:请求数据不在GET方法中使用,而是在POST方法中使用。POST方法适用于需要客户填写表单的场合。与请求数据相关的最常使用的请求头是Content-Type和Content-Length。
请求体:可选,存放需要提交的数据(仅POST/PUT等方法常用)。
示例(JSON 格式):
{"device_id": "sensor_001", "temperature": 25.5, "humidity": 60}
2)响应数据格式
HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。
状态行:由三部分组成,HTTP协议的版本号、状态码、以及对状态码的文本描述。例如:HTTP/1.1 (协议版本)200 (状态码)OK (CRLF) 。(200表示请求已经成功)
状态行:包含 3 部分,格式:HTTP版本 状态码 原因短语
示例:HTTP/1.1 200 OK
状态码:3 位数字,表示请求处理结果:
1xx(信息):请求已接收,继续处理(如 100 Continue)。
2xx(成功):请求正常处理(如 200 OK)。
3xx(重定向):需要进一步操作(如 302 Found,临时重定向)。
4xx(客户端错误):请求有误(如 404 Not Found,资源不存在;400 Bad Request,参数错误)。
5xx(服务器错误):服务器处理失败(如 500 Internal Server Error)。
响应头:类似请求头,描述响应的附加信息。
常见字段:
Content-Type:响应体的数据类型(如application/json、text/html)。
Content-Length:响应体长度。
Server:服务器标识(如Server: Nginx)。
Cache-Control:缓存策略(如Cache-Control: max-age=3600,缓存 1 小时)。
响应体:服务器返回的实际数据(如网页 HTML、JSON 接口数据、图片二进制流)。
示例(JSON 响应):
{"code": 0, "msg": "success", "data": {"max_temp": 30.0}}
- 200 OK:请求成功,服务器成功处理了请求并返回所请求的资源。
- 301 Moved Permanently:请求的资源已永久移动到新的URL,客户端应更新其链接。
- 302 Found:请求的资源暂时移动到新的URL,客户端应继续使用原始URL。
- 400 Bad Request:服务器无法理解请求的语法,通常是由于客户端发送的请求不正确导致的。
- 401 Unauthorized:请求要求身份验证,客户端需要提供有效的身份凭证。
- 403 Forbidden:服务器拒绝请求,客户端没有访问所请求资源的权限。
- 404 Not Found:请求的资源不存在,服务器无法找到所请求的资源。
- 500 Internal Server Error:服务器内部错误,无法完成请求的处理。
- 503 Service Unavailable:服务器当前无法处理请求,通常是由于服务器过载或维护导致
HTTP 通信完整过程
(以 “嵌入式设备向服务器发送传感器数据” 为例)
假设场景:ESP32(客户端)通过 HTTP POST 向云平台(服务器api.iot-platform.com)发送温湿度数据。
1. 前置步骤:DNS 解析
客户端需要先将服务器域名(api.iot-platform.com)解析为 IP 地址(如120.53.xx.xx),通过 DNS 服务器完成。
2. 建立 TCP 连接(三次握手)
HTTP 基于 TCP,通信前需先建立连接:
- 客户端→服务器:发送 SYN 包(请求建立连接)。
- 服务器→客户端:返回 SYN+ACK 包(同意连接)。
- 客户端→服务器:发送 ACK 包(确认连接)。
连接建立后,双方可开始传输 HTTP 数据。
3. 客户端发送 HTTP 请求
ESP32 构造 POST 请求报文并发送,示例:
POST /api/upload HTTP/1.1
Host: api.iot-platform.com
User-Agent: ESP32-HTTP-Client
Content-Type: application/json
Content-Length: 56
{"device_id": "esp32_001", "temp": 25.3, "humi": 58.2}
4. 服务器处理请求并返回响应
- 服务器接收请求,解析 URL(/api/upload)和请求体,验证数据合法性。
- 处理完成后,返回响应报文(状态码 200 表示成功):
HTTP/1.1 200 OK
Server: Nginx
Content-Type: application/json
Content-Length: 30
{"code": 0, "msg": "upload success"}
5. 关闭连接(四次挥手,可选)
- 若为 HTTP/1.0(短连接):数据传输完成后,TCP 连接关闭(四次挥手)。
- 若为 HTTP/1.1(默认持久连接):连接可复用,用于后续请求(节省建立连接的时间),闲置一段时间后自动关闭。