Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
ftp
ota在线升级
分享个使用ftpclient实现ota的例子
发布于 2021-06-26 14:47:08 浏览:1968
订阅该版
分享个使用ftpclient实现ota的例子, 是参考这里实现的 https://kerndev.blog.csdn.net/article/details/89383888 默认将文件下载到download分区 ```c #include
#include
#include
#include
#include "netdb.h" // #include "log.h" // #include "ftp.h" #include
#include
#include
#define DRV_DEBUG #define LOG_TAG "drv.FTP" #include
static int m_socket_cmd; static int m_socket_data; static char m_send_buffer[1024]; static char m_recv_buffer[4096]; static void ftp_quit(void); static void print_progress(size_t cur_size, size_t total_size); int socket_connect(int sock, const char *url, int port) { struct sockaddr_in server_addr; struct hostent *host = RT_NULL; /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */ host = gethostbyname(url); if (host == RT_NULL) { LOG_E("Get host by name failed!"); return -1; } /* 初始化预连接的服务端地址 */ server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); server_addr.sin_addr = *((struct in_addr *)host->h_addr); rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero)); /* 连接到服务端 */ if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) { /* 连接失败 */ LOG_E("Connect fail!\n"); closesocket(sock); return -1; } return 1; } int socket_send(int sock, void *data, int len) { return send(sock, (char *)data, len, 0); } int socket_recv(int sock, void *data, int len) { return recv(sock, (char *)data, len, 0); } //命令端口,发送命令 static int ftp_send_command(char *cmd) { int ret; LOG_I("send command: %s\r\n", cmd); ret = socket_send(m_socket_cmd, cmd, (int)strlen(cmd)); if (ret < 0) { LOG_E("failed to send command: %s", cmd); return 0; } return 1; } //命令端口,接收应答 static int ftp_recv_respond(char *resp, int len) { int ret; int off; len -= 1; for (off = 0; off < len; off += ret) { ret = socket_recv(m_socket_cmd, &resp[off], 1); if (ret < 0) { LOG_E("recv respond error(ret=%d)!\r\n", ret); return 0; } if (resp[off] == '\n') { break; } } resp[off + 1] = 0; LOG_I("respond:%s", resp); return atoi(resp); } //设置FTP服务器为被动模式,并解析数据端口 static int ftp_enter_pasv(char *ipaddr, int *port) { int ret; char *find; int a, b, c, d; int pa, pb; ret = ftp_send_command("PASV\r\n"); if (ret != 1) { return 0; } ret = ftp_recv_respond(m_recv_buffer, 1024); if (ret != 227) { return 0; } find = strrchr(m_recv_buffer, '('); sscanf(find, "(%d,%d,%d,%d,%d,%d)", &a, &b, &c, &d, &pa, &pb); sprintf(ipaddr, "%d.%d.%d.%d", a, b, c, d); *port = pa * 256 + pb; return 1; } //上传文件 int ftp_upload(char *name, void *buf, int len) { int ret; char ipaddr[32]; int port; //查询数据地址 ret = ftp_enter_pasv(ipaddr, &port); if (ret != 1) { return 0; } ret = socket_connect(m_socket_data, ipaddr, port); if (ret != 1) { return 0; } //准备上传 sprintf(m_send_buffer, "STOR %s\r\n", name); ret = ftp_send_command(m_send_buffer); if (ret != 1) { return 0; } ret = ftp_recv_respond(m_recv_buffer, 1024); if (ret != 150) { closesocket(m_socket_data); return 0; } //开始上传 ret = socket_send(m_socket_data, buf, len); if (ret != len) { LOG_E("send data error!\r\n"); closesocket(m_socket_data); return 0; } closesocket(m_socket_data); //上传完成,等待回应 ret = ftp_recv_respond(m_recv_buffer, 1024); return (ret == 226); } //下载文件 int ftp_download(char *name, int len) { int i; int ret; char ipaddr[32]; int port; int curlen = 0; rt_uint32_t tick = 0; const struct fal_partition *dl_part = RT_NULL; //查询数据地址 ret = ftp_enter_pasv(ipaddr, &port); if (ret != 1) { return 0; } //连接数据端口 ret = socket_connect(m_socket_data, ipaddr, port); if (ret != 1) { LOG_E("failed to connect data port\r\n"); return 0; } /* Get download partition information and erase download partition data */ if ((dl_part = fal_partition_find("download")) == RT_NULL) { LOG_E("Firmware download failed! Partition (%s) find error!", "download"); ret = -RT_ERROR; goto __exit; } LOG_I("Start erase flash (%s) partition!", dl_part->name); if (fal_partition_erase(dl_part, 0, len) < 0) { LOG_E("Firmware download failed! Partition (%s) erase error!", dl_part->name); ret = -RT_ERROR; goto __exit; } LOG_I("Erase flash (%s) partition success!", dl_part->name); memset(m_recv_buffer, 0x00, 4096); LOG_I("OTA file size is (%d)", len); //准备下载 sprintf(m_send_buffer, "RETR %s\r\n", name); ret = ftp_send_command(m_send_buffer); if (ret != 1) { return 0; } ret = ftp_recv_respond(m_recv_buffer, 1024); if (ret != 150) { closesocket(m_socket_data); return 0; } //开始下载,读取完数据后,服务器会自动关闭连接 tick = rt_tick_get(); for (curlen = 0; curlen < len; curlen += ret) { ret = socket_recv(m_socket_data, m_recv_buffer, 4096); // LOG_I("download %d/%d.\r\n", curlen + ret, len); if (ret > 0) { /* Write the data to the corresponding partition address */ if (fal_partition_write(dl_part, curlen, m_recv_buffer, ret) < 0) { LOG_E("Firmware download failed! Partition (%s) write data error!", dl_part->name); ret = -RT_ERROR; goto __exit; } // curlen += ret; print_progress(curlen + ret, len); } else { LOG_E("Exit: server return err (%d)!", len); ret = -RT_ERROR; goto __exit; } } // //下载完成 LOG_I("time=%d download %d/%d bytes complete.\r\n", rt_tick_get() - tick, curlen, len); closesocket(m_socket_data); ret = ftp_recv_respond(m_recv_buffer, 4096); if (ret == 226) { ftp_quit(); ret = RT_EOK; } // else // { // ret = -RT_ERROR; // goto __exit; // } if (curlen == len) { LOG_I("Download firmware to flash success."); LOG_I("System now will restart..."); rt_thread_delay(rt_tick_from_millisecond(5)); /* Reset the device, Start new firmware */ extern void rt_hw_cpu_reset(void); rt_hw_cpu_reset(); } __exit: closesocket(m_socket_data); ret = ftp_recv_respond(m_recv_buffer, 4096); return (ret == 226); } //返回文件大小 int ftp_filesize(char *name) { int ret; int size; sprintf(m_send_buffer, "SIZE %s\r\n", name); ret = ftp_send_command(m_send_buffer); if (ret != 1) { return 0; } ret = ftp_recv_respond(m_recv_buffer, 1024); if (ret != 213) { return 0; } size = atoi(m_recv_buffer + 4); return size; } //登陆服务器 int ftp_login(char *addr, int port, char *username, char *password) { int ret; LOG_I("connect...\r\n"); ret = socket_connect(m_socket_cmd, addr, port); if (ret != 1) { LOG_E("connect server failed!\r\n"); return 0; } LOG_I("connect ok.\r\n"); //等待欢迎信息 一共4行 // 220---------- Welcome to Pure-FTPd ---------- // 220-You are user number 1 of 5 allowed. // 220-Local time is now 16:30. Server port: 21. // 220 You will be disconnected after 15 minutes of inactivity. ret = ftp_recv_respond(m_recv_buffer, 1024); ret = ftp_recv_respond(m_recv_buffer, 1024); ret = ftp_recv_respond(m_recv_buffer, 1024); ret = ftp_recv_respond(m_recv_buffer, 1024); if (ret != 220) { LOG_E("bad server, ret=%d!\r\n", ret); closesocket(m_socket_cmd); return 0; } LOG_I("login...\r\n"); //发送USER sprintf(m_send_buffer, "USER %s\r\n", username); ret = ftp_send_command(m_send_buffer); if (ret != 1) { LOG_E("bad ftp_send_command, ret=%d!\r\n", ret); closesocket(m_socket_cmd); return 0; } ret = ftp_recv_respond(m_recv_buffer, 1024); if (ret != 331) { LOG_E("bad ftp_recv_respond, ret=%d!\r\n", ret); closesocket(m_socket_cmd); return 0; } //发送PASS sprintf(m_send_buffer, "PASS %s\r\n", password); ret = ftp_send_command(m_send_buffer); if (ret != 1) { LOG_E("bad ftp_send_command, ret=%d!\r\n", ret); closesocket(m_socket_cmd); return 0; } ret = ftp_recv_respond(m_recv_buffer, 1024); if (ret != 230) { LOG_E("bad ftp_recv_respond, ret=%d!\r\n", ret); closesocket(m_socket_cmd); return 0; } LOG_I("login success.\r\n"); //设置为二进制模式 ret = ftp_send_command("TYPE I\r\n"); if (ret != 1) { closesocket(m_socket_cmd); return 0; } ret = ftp_recv_respond(m_recv_buffer, 1024); if (ret != 200) { closesocket(m_socket_cmd); return 0; } return 1; } void ftp_quit(void) { ftp_send_command("QUIT\r\n"); closesocket(m_socket_cmd); } void ftp_init(void) { // m_socket_cmd = socket_create(); // m_socket_data = socket_create(); if ((m_socket_cmd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { /* 创建失败的错误处理 */ LOG_E("Create Socket error\n"); } if ((m_socket_data = socket(AF_INET, SOCK_STREAM, 0)) == -1) { /* 创建失败的错误处理 */ LOG_E("Create Socket error\n"); } } static void print_progress(size_t cur_size, size_t total_size) { static unsigned char progress_sign[100 + 1]; uint8_t i, per = cur_size * 100 / total_size; if (per > 100) { per = 100; } for (i = 0; i < 100; i++) { if (i < per) { progress_sign[i] = '='; } else if (per == i) { progress_sign[i] = '>'; } else { progress_sign[i] = ' '; } } progress_sign[sizeof(progress_sign) - 1] = '\0'; LOG_I("\033[2A"); LOG_I("Download: [%s] %d%%", progress_sign, per); } void ftp_client() { int ret; ftp_init(); ret = ftp_login("192.168.168.202", 21, "uploadhis", "111111"); int size = ftp_filesize("/datalog/download.bin"); // char *buf = rt_malloc(size); ret = ftp_download("/datalog/download.bin", size); // ftp_quit(); // rt_free(buf); } MSH_CMD_EXPORT(ftp_client, ftp_client sample); ```
1
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
sync
这家伙很懒,什么也没写!
文章
5
回答
412
被采纳
78
关注TA
发私信
相关文章
1
OTA 片上FLASH擦除失败
2
请教一下用私有协议数据包进行OTA的具体的实现流程
3
OTA跳转后基于RTT的app运行失败
4
使用finsh 进行ota成功,线程里开ota失败
5
http_ota 每次下载一半就断线
6
bootloader跳转到app无法正常运行
7
针对腾讯云IOT的软件包OTAbug功能反馈
8
自己写的bootloader无法正常升级基于RTT的程序
9
OTA升级,APP程序下载问题
10
bootloader下载APP后不能正常跳转
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
SFUD
msh
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1443
个答案
289
次被采纳
张世争
805
个答案
174
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
4
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部