本文來源電子發燒友社區,作者:李元江, 帖子地址:https://bbs.elecfans.com/jishu_2028163_1_1.html
一、數據傳輸過程
復制代碼
復制代碼
2、TCP數據接收和發送任務
復制代碼
3、連接服務器切換
復制代碼
三、演示情況
四、總結
一、數據傳輸過程
該過程與局域網內的TCP服務端與客戶端數據傳輸過程很類似。局域網內是這樣的,兩個設備在同一個局域網內,一個作為TCP服務端,一個作為TCP客戶端,這樣這兩個設備就是進行局域網內的數據通信。但是兩個設備不在同一個網絡內,數據傳輸在上面的方法是行不通的。這時可以借助一個在公網的TCP中轉服務端,實現兩個設備的遠程數據傳輸。數據傳輸過程為兩個設備都作為TCP客戶端,一個設備把數據傳輸到服務端,然后服務端把數據傳輸到另一個設備。但是這也要求,這兩個設備的網絡是可以連接到公網的,否則是無法連接到公網的TCP服務端。
二、軟件設計
首先我們需要一個在公網的TCP客戶端。如果各位自己有云服務器的,可以自行搭建一個TCP中轉服務端。我使用的客戶端是別人用于測試的客戶端。軟件方面需要考慮幾個問題:
-
連接服務器的切換在我的上幾個帖子上,需要連接其他服務器獲取時間數據或者獲取天氣數據。這時,我們需要在進行連接服務器切換,確保獲取的數據正常。
-
連接狀態檢測我們還需要進行連接狀態檢查,如果與TCP服務端斷開,是無法正常進行數據交互的。
-
連接重連如果檢查到連接斷開,或者沒有連接成功,需要重新嘗試進行與服務端的連接。
新建tcp_connect.c tcp_connect.h文件,里面主要是與TCP連接、TCP連接斷開、TCP數據發送、數據接收相關的函數。注意:TCPIPADDR、TCPPORT是公網TCP客戶端IP地址和端口號。其實這幾個函數是在之前的tcp例程中拆分出來的,把一個函數劃分為四個函數而已。
-
設置接收超時之前的例程中,沒有加入接收超時機制,如果沒有接收到數據,會一直呈現阻塞狀態,其他任務可能會出現無法正常運行的狀態,所以我們需要加入超時機制,超過一定時間沒接收到數據,也會推出退出接收過程。timeval 在頭文件中。//設置接收超時struct timeval timeout={2,0};//1sif (setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(struct timeval)) == -1){ printf("setsockopt failed!rn"); //goto do_cleanup;}
-
tcp_connect.c
- #include "tcp_connect.h"
- //#define TCPIPADDR "192.168.3.9"
- //#define TCPPORT 5678
- #define TCPIPADDR "115.29.109.104"
- #define TCPPORT 6545
- ?
- static int sockfd;
- static int netId;
- static struct sockaddr_in serverAddr = {0};
- ?
- TCP_STATIC connect_status = DISCONNECTED;
- //extern char sendData[30];
- ?
- bool TcpConnect(void)
- {
- bool connectflag = false;
- WifiDeviceConfig config = {0};
- ?
- // 準備AP的配置參數
- strcpy(config.ssid, PARAM_HOTSPOT_SSID);
- strcpy(config.preSharedKey, PARAM_HOTSPOT_PSK);
- config.securityType = PARAM_HOTSPOT_TYPE;
- osDelay(10);
- netId= ConnectToHotspot(&config);
- ?
- sockfd = socket(AF_INET, SOCK_STREAM, 0); // TCP socket
- ?
- serverAddr.sin_family = AF_INET;// AF_INET表示IPv4協議
- serverAddr.sin_port = htons(TCPPORT);// 端口號,從主機字節序轉為網絡字節序
- if (inet_pton(AF_INET, TCPIPADDR , &serverAddr.sin_addr) <= 0) {??// 將主機IP地址從“點分十進制”字符串 轉化為 標準格式(32位整數)
- printf("inet_pton failed!rn");
- goto do_cleanup;
- }
- ?
- //設置接收超時
- struct timeval timeout={2,0};//1s
- if (setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout,sizeof(struct timeval)) == -1)
- {
- printf("setsockopt failed!rn");
- //goto do_cleanup;
- }
- ?
- // 嘗試和目標主機建立連接,連接成功會返回0 ,失敗返回 -1
- if (connect(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) {
- printf("connect failed!rn");
- goto do_cleanup;
- }
- printf("connect to server %s success!rn",TCPIPADDR);
- connectflag = true;
- connect_status = CONNECTED;
- do_cleanup:
- return connectflag;
- }
- ?
- bool TcpDisconnect(void){
- ?
- close(sockfd);
- DisconnectWithHotspot(netId);
- connect_status = DISCONNECTED;
- return true;
- }
- ?
- bool TcpSend(char *data,int len){
- // printf("send start!n");
- int retval = send(sockfd, data , len, 0);
- if (retval < 0) {
- //printf("send request failed!rn");
- return false;
- }
- else{
- // printf("send OK!n");
- return true;
- }
- }
- ?
- extern char revData[30];
- bool TcpRev(void){
- int retval =0;
- retval = recv(sockfd, &revData, sizeof(revData), 0);
- if (retval <= 0) {
- // printf("rev from server failed or done, %ld!rn", retval);
- return false;
- }
- revData[retval] = '';
- return true;
- }
-
tcp_connect.h
- #ifndef __TCP_CONNECT_H
- #define __TCP_CONNECT_H
- ?
- ?
- #include
- #include
- #include
- ?
- #include "net_demo.h"
- #include "net_common.h"
- #include "net_params.h"
- #include "wifi_connecter.h"
- #include "ohos_init.h"
- #include "cmsis_os2.h"
- ?
- typedef enum{
- DISCONNECTED = 0,
- CONNECTED,
- }TCP_STATIC;
- ?
- extern TCP_STATIC connect_status;
- ?
- bool TcpConnect(void);
- bool TcpDisconnect(void);
- bool TcpSend(char *data,int len);
- bool TcpRev(void);
- ?
- #endif/*__TCP_CONNECT_H*/
新建tcptask.c 這里面這要是新建兩個任務,一個是數據發送任務,一個是數據發送任務。
-
數據發送任務在數據發送任務中,如果與服務端連接狀態正常,會每隔兩秒發送一次數據到服務端。這里有連接狀態檢查和連接重連機制,如果數據發送不成功,則把連接狀態看為是未連接狀態。在未連接狀態,每隔兩秒會嘗試重新連接服務端,直到再一次成功連接上服務端。
-
數據接收任務為了保證能夠隨時接收到服務端發送過來的數據,該任務會每10ms調度一次。在連接狀態為已連接情況下,會執行TCP數據接收函數。
- #include
- #include
- #include
- ?
- #include "tcp_connect.h"
- #include "ohos_init.h"
- #include "cmsis_os2.h"
- ?
- char sendData[]="hellow tcp!";
- char revData[30]="";
- typedef enum{
- GET_NORMAL =0 ,
- GET_PROPRESS,
- GET_SUC,
- GET_FAIL,
- }GET_STATUS;
- ?
- extern GET_STATUS Get_Status;
- ?
- static void TcpSendTask(void *arg)
- {
- sleep(3);
- uint8_t i = 0;
- while(1){
- if(TcpConnect())
- {
- printf("Tcp Connect Sucn");
- break;
- }
- else{
- i++;
- }
- if(i>10)
- break;
- }
- if(i>10)
- printf("Tcp Connect failn");
- ?
- (void)arg;
- while(1)
- {
- if(connect_status == CONNECTED)
- {
- if(!TcpSend(sendData,sizeof(sendData)-1)){
- connect_status = DISCONNECTED;
- TcpDisconnect();
- }
- }
- else{
- if(Get_Status == GET_NORMAL){
- if(TcpConnect()){
- printf("Tcp Connect Sucn");
- }
- }
- }
- sleep(2);
- }
- }
- ?
- static void TcpSendTaskHandle(void)
- {
- osThreadAttr_t attr;
- attr.name = "TcpSendTask";
- attr.attr_bits = 0U;
- attr.cb_mem = NULL;
- attr.cb_size = 0U;
- attr.stack_mem = NULL;
- attr.stack_size = 4096;
- attr.priority = osPriorityNormal;
- if (osThreadNew(TcpSendTask, NULL, &attr) == NULL) {
- printf("[TcpSendTaskHandle] Falied to create TcpSendTask!n");
- }
- }
- APP_FEATURE_INIT(TcpSendTaskHandle);
- ?
- ?
- static void TcpRevTask(void *arg){
- (void)arg;
- while(1)
- {
- if(connect_status == CONNECTED)
- {
- if(TcpRev()){
- printf("%s",revData);
- }
- }
- usleep(10000);
- }
- }
- ?
- static void TcpRevTaskHandle(void)
- {
- osThreadAttr_t attr;
- attr.name = "TcpRevTask";
- attr.attr_bits = 0U;
- attr.cb_mem = NULL;
- attr.cb_size = 0U;
- attr.stack_mem = NULL;
- attr.stack_size = 4096;
- attr.priority = osPriorityNormal;
- if (osThreadNew(TcpRevTask, NULL, &attr) == NULL) {
- printf("[TcpRevTaskHandle] Falied to create TcpRevTask!n");
- }
- }
- APP_FEATURE_INIT(TcpRevTaskHandle);
前面也說了,在獲取時間或者天氣數據時,需要進行連接服務端的切換,確保能接收到正確的數據。在keytask.c文件進行修改。在獲取時間和天氣函數前加上TCP服務斷開函數,獲取完之后,加上TCP連接函數。
- if((voltage>0.45 && voltage<0.65)&&(!keyflag))
- {
- keyflag = true;
- if(connect_status == CONNECTED)
- TcpDisconnect();
- //OledShowString(16,7,"Sync time...",1);
- //getNtpTime();
- //OledFillScreen(0);
- switch (Now_Screen){
- case TIMESCREEN:
- //OledShowString(16,7,"Sync time...",1);
- Get_Status = GET_PROPRESS;
- if(getNtpTime()){
- Get_Status = GET_SUC;
- }
- //OledFillScreen(0);
- else
- {
- //OledShowString(0,7,"Get fail...",1);
- Get_Status = GET_FAIL;
- }
- break;
- case NOWSCREEN:
- //OledShowString(0,7,"Get Weather...",1);
- Get_Status = GET_PROPRESS;
- if(getWeather())
- //OledFillScreen(0);
- Get_Status = GET_SUC;
- else
- {
- //OledShowString(0,7,"Get fail...",1);
- Get_Status = GET_FAIL;
- }
- break;
- case TOSCREEN:
- Get_Status = GET_PROPRESS;
- if(getWeather())
- Get_Status = GET_SUC;
- else
- {
- Get_Status = GET_FAIL;
- }
- break;
- case ATOSCREEN:
- Get_Status = GET_PROPRESS;
- if(getWeather())
- Get_Status = GET_SUC;
- else
- {
- Get_Status = GET_FAIL;
- }
- break;
- ?
- default:
- break;
- }
- TcpConnect();
- }
在手機端需要安裝網絡調試助手,附件里有我在大學時自己做的一個APP,里面包含網絡調試功能。感興趣的可以自己下載安裝,就是界面很丑,有時間再進行好好進行優化。
連接到服務端,該服務端與wifiiot連接的服務端IP和端口一致。
手機數據接收情況,每隔兩秒會接收到wifiiot發送過來的“hello tcp!”信息。
手機端發送123456,wifiiot成功接收到數據,并通過串口打印出來。
通過公網的TCP中轉服務端,實現兩個不同網絡的設備之間進行遠程數據傳輸,這只是兩個設備之間進行遠程通信的一種方式?,F在不能設置連接wifi和服務端的IP、端口,后面有時間再慢慢進行改進吧。
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
wi-fi
+關注
關注
14文章
2147瀏覽量
124612 -
HarmonyOS
+關注
關注
79文章
1979瀏覽量
30274 -
HiSpark
+關注
關注
1文章
156瀏覽量
6938
發布評論請先 登錄
相關推薦
Wi-Fi 8要來了!未來Wi-Fi技術演進方向揭秘
產品銷售中,雖然Wi-Fi 7產品的銷量份額快速從年初的個位數百分比增長至14%,但Wi-Fi 6產品的銷量份額依然穩定在60%左右。如果從存量設備來看,那么Wi-Fi 7路由器的占比將遠遠小于這個數。 ? 智能手機等終端設備已
村田: 遠距、高速、低功耗的Wi-Fi HaLow?通信模塊
株式會社村田制作所開發了實現1公里以上的遠距離高速數據傳輸并支持Wi-Fi?標準“Wi-Fi HaLow?”的通信模塊“Type 2HK”和“Type 2HL”。本產品配備了使用Arm
華為海思正式進入Wi-Fi FEM賽道?
轉載自——鐘林談芯
昨天在網上看到一份九聯UNR050 BE3600無線路由器拆機報告,Wi-Fi主芯片是海思新款Wi-Fi7芯片Hi1155,速率2.5G。
在海思AP Wi-Fi芯
發表于 12-11 17:42
從Wi-Fi 4到Wi-Fi 7:網速飆升40倍的無線革命
1 Wi-Fi技術的快速發展 每一代新的Wi-Fi協議發布,都會帶來更高的無線速率。 ? 從Wi-Fi 4到Wi-Fi 7:無線網絡技術顯著提升,實現了網速的巨大飛躍。 ? ?
Wi-Fi 7與Wi-Fi 6E有什么區別
也許很多人還在考慮是否要將使用的Wi-Fi設備升級到Wi-Fi 6或Wi-Fi 6E,而這些標準的繼任者卻已經開始“登堂入室”了。Wi-Fi 7是新一代
DA16200 超低功耗 Wi-Fi 模塊開發套件 Pro數據手冊
電子發燒友網站提供《DA16200 超低功耗 Wi-Fi 模塊開發套件 Pro數據手冊.rar》資料免費下載
發表于 05-30 17:53
?1次下載
DA16200 超低功耗 Wi-Fi 模塊開發套件數據手冊
電子發燒友網站提供《DA16200 超低功耗 Wi-Fi 模塊開發套件數據手冊.rar》資料免費下載
發表于 05-30 17:13
?0次下載
驗證物聯網Wi-Fi HaLow用例的MM6108-EKH08開發套件來啦
驗證物聯網Wi-Fi HaLow用例的MM6108-EKH08開發套件來啦 MM6108-EKH08開發套件專為驗證物聯網Wi-Fi HaLow用例而設計。該
XMC4700是否可以通過SDIO接口與Wi-Fi模塊通信?
XMC4700 數據表中的外設列表顯示\"SD 和多媒體卡接口(SDMMC),用于數據存儲記憶卡\" ,但是否可以通過 SDIO 接口與 Wi-Fi 模塊通信?
Wi-Fi 模塊可與 SDIO 接口
發表于 03-06 07:26
Wi-Fi HaLow和傳統Wi-Fi的區別
Wi-Fi HaLow和傳統Wi-Fi的區別? Wi-Fi是一種無線網絡技術,可以連接到互聯網或局域網,為用戶提供無線上網的便利。隨著科技的發展和互聯網的普及,Wi-Fi也在不斷演進和
康普攜手Wi-Fi聯盟,RUCKUS Wi-Fi 7系列接入點成Wi-Fi
康普高級副總裁兼網絡、智能蜂窩和安全解決方案總裁Bart Giordano對此表示: “我們非常榮幸能與Wi-Fi Alliance形成長期合作伙伴關系,將我們的RUCKUS Wi-Fi 7 接入點平臺作為Wi-Fi CERT
BT Wi-Fi模式是否可以通過ModustoolBox對套件進行編程來實現?
想配置用于分析 CYW43439 的 CY8CPROTO-062S2-43439 原型開發套件。
瀏覽文檔我無法弄清楚如何在不同的 Wi-Fi 和藍牙模式(電源模式、連接模式等)下配置套件。
在
發表于 01-22 06:19
評論