【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(默認持久連接):連接可復用,用于后續請求(節省建立連接的時間),閑置一段時間后自動關閉。