本文来源电子发烧友社区,作者:李元江, 帖子地址: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中转服务端,实现两个不同网络的设备之间进行远程数据传输,这只是两个设备之间进行远程通信的一种方式。现在不能设置连接wifi和服务端的IP、端口,后面有时间再慢慢进行改进吧。
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。
举报投诉
-
wi-fi
+关注
关注
15文章
2379浏览量
128890 -
HarmonyOS
+关注
关注
80文章
2146浏览量
35569 -
HiSpark
+关注
关注
1文章
156浏览量
7686
发布评论请先 登录
相关推荐
热点推荐
浅谈Wi-Fi 6E与Wi-Fi 7的关键器件——BAW滤波器新技术
,美国联邦通信委员会(FCC)投票通过将6GHz频谱划为免许可频段供Wi-Fi使用,这标志着Wi-Fi正式进入“三频”时代——除Wi-Fi 6及前代技术使用的2.4GHz和5GHz频段
发表于 09-19 18:29
•1320次阅读
LitePoint Wi-Fi测试软件减轻客户设计负担
自Wi-Fi 7于一年多前获得Wi-Fi联盟认证以来,作为最新一代通信技术,Wi-Fi正逐步成为用户实现无所不在无线连接的新选择。随着每一代Wi-F
Texas Instruments CC335x SimpleLink™双频Wi-Fi® 6配套IC数据手册
) 和Wi-Fi 5 (802.11ac)。这些CC335x是Texas Instruments的第10代连接组合芯片。因此,CC335x基于成熟的技术设计而成。这些器件非常适合配备运行TCP/IP的Linux或
Wi-Fi 8:开启极高可靠性 (UHR) 连接的新纪元——1
。2021年,Wi-Fi 6E 横空出世,凭借6GHz 频带的独特优势,使Wi-Fi 正式迈入真三频 (Real Tri-Band) 共存的通信技术时代。2024年,科学家们再次凭借着4096QAM
发表于 06-13 11:09
迅通PTR7002 Wi-Fi 6模块技术解析
驱动库及AT指令集,支持通过SPI或UART与主控芯片通信。开发者可通过配套的SDK 2.1.4版本直接调用Wi-Fi 6的OFDMA和TWT(目标唤醒时间)功能,实现多设备低延时调度。
根据
发表于 06-10 10:38
基于 Wi-Fi 的定位服务
以下捕获使用 location_wifi_get 函数请求 Wi-Fi 定位服务。该事件的总功耗为 125.85mC,日志显示精确度为 30.0m。
Got location:
method
发表于 04-17 15:16
nRF Cloud Wi-Fi 定位服务
、Predictive-GPS、Single-Cell、Multi-Cell 和 Wi-Fi 定位。通过利用 nRF Cloud 的优化定位算法,基于 Nordic SoC 和 模组的产品可在定位用例
发表于 04-17 15:07
Wi-Fi 定位服务
Wi-Fi 是一种著名的无线网络技术,用于设备的局域网和互联网接入。Wi-Fi 通过 Wi-Fi 网络为家庭、办公室和学校等环境提供便捷的无线互联网接入服务。
Wi-Fi 定位是一种
发表于 04-17 15:01
Wi-Fi 7 与频率控制的关系
作者:Poornima Apte 投稿人:DigiKey 北美编辑 2024-12-18 Wi-Fi 需要使用一定范围的无线电频率才能让设备进行通信拨号。多年来,Wi-Fi 一直使用 2.4 GHz
移远通信再扩短距离通信模组版图:Wi-Fi 7/6、Wi-Fi Halow等六款新品助力无线连接升级
在CES 2025期间,全球领先的物联网整体解决方案供应商移远通信对外宣布,将推出六款新型短距离通信模组。该系列模组覆盖Wi-Fi 6/7、Wi-Fi HaLow、蓝牙等多种前沿技术,
发表于 01-09 11:29
•611次阅读
村田: 远距、高速、低功耗的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 HaLow评估套件,加速物联网开发
近日,全球领先的Wi-Fi HaLow解决方案提供商摩尔斯微电子正式推出一款开创性的评估套件——MM6108-EKH05。这款完全整合的开发平台,旨在推动各行业物联网解决方案的快速发展
从Wi-Fi 4到Wi-Fi 7:网速飙升40倍的无线革命
1 Wi-Fi技术的快速发展 每一代新的Wi-Fi协议发布,都会带来更高的无线速率。 从Wi-Fi 4到Wi-Fi 7:无线网络技术显著提升,实现了网速的巨大飞跃。

【HarmonyOS HiSpark Wi-Fi IoT 套件试用连载】九:远程TCP通信
评论