嵌入式技术论坛
直播中

哔哔哔-

8年用户 1268经验值
擅长:电源/新能源
私信 关注
[经验]

分享一个使用ftpclient实现ota的案例

分享个使用ftpclient实现ota的例子,
默认将文件下载到download分区
#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: %srn", 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)!rn", 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("PASVrn");
    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 %srn", 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!rn");
        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 portrn");
        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 %srn", 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.rn", 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.rn", 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 %srn", 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...rn");
    ret = socket_connect(m_socket_cmd, addr, port);
    if (ret != 1)
    {
        LOG_E("connect server failed!rn");
        return 0;
    }
    LOG_I("connect ok.rn");
    //等待欢迎信息 一共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!rn", ret);
        closesocket(m_socket_cmd);
        return 0;
    }
    LOG_I("login...rn");
    //发送USER
    sprintf(m_send_buffer, "USER %srn", username);
    ret = ftp_send_command(m_send_buffer);
    if (ret != 1)
    {
        LOG_E("bad ftp_send_command, ret=%d!rn", 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!rn", ret);
        closesocket(m_socket_cmd);
        return 0;
    }
    //发送PASS
    sprintf(m_send_buffer, "PASS %srn", password);
    ret = ftp_send_command(m_send_buffer);
    if (ret != 1)
    {
        LOG_E("bad ftp_send_command, ret=%d!rn", 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!rn", ret);
        closesocket(m_socket_cmd);
        return 0;
    }
    LOG_I("login success.rn");
    //设置为二进制模式
    ret = ftp_send_command("TYPE Irn");
    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("QUITrn");
    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 errorn");
    }
    if ((m_socket_data = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        /* 创建失败的错误处理 */
        LOG_E("Create Socket errorn");
    }
}
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] = '';
    LOG_I("33[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);

原作者:sync

更多回帖

发帖
×
20
完善资料,
赚取积分