diff --git a/APP_Framework/Applications/app_test/test_ftpclient/FTP_client.h b/APP_Framework/Applications/app_test/test_ftpclient/FTP_client.h new file mode 100644 index 000000000..c2926b0d6 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_ftpclient/FTP_client.h @@ -0,0 +1,321 @@ +/* +* Copyright (c) 2020 AIIT Ubiquitous Team +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL +v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file: FTP_client.h +* @brief: a application of ftp client function +* @version: 1.0 +* @author: bdislab_Rhodes +* @date: 2023/9/30 +*/ + +#include +#include +#include +#include +#include "mysocket.h" +#include "log.h" + + +static int m_socket_cmd; +static int m_socket_data; +static char m_send_buffer[1024]; +static char m_recv_buffer[1024]; + + +//命令端口,发送命令 +static int FtpSendCommand(char* cmd) +{ + int ret; + LogInfo("send command: %s\r\n", cmd); + ret = SocketSend(m_socket_cmd, cmd, (int)strlen(cmd)); + if (ret < 0) + { + LogInfo("failed to send command: %s", cmd); + return 0; + } + return 1; +} + +//命令端口,接收应答 +static int FtpRecvRespond(char* resp, int len) +{ + int ret; + int off; + len -= 1; + for (off = 0; off < len; off += ret) + { + ret = SocketRecv(m_socket_cmd, &resp[off], 1); + if (ret < 0) + { + LogInfo("recv respond error(ret=%d)!\r\n", ret); + return 0; + } + if (resp[off] == '\n') + { + break; + } + } + resp[off + 1] = 0; + LogInfo("respond:%s", resp); + return atoi(resp); +} + +//设置FTP服务器为被动模式,并解析数据端口 +static int FtpEnterPasv(char* ipaddr, int* port) +{ + int ret; + char* find; + int a, b, c, d; + int pa, pb; + char command_pasv[] = "PASV\r\n"; + ret = FtpSendCommand(command_pasv); + if (ret != 1) + { + return 0; + } + ret = FtpRecvRespond(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 FtpUpload(char* name, void* buf, int len) +{ + int ret; + char ipaddr[32]; + int port; + + //查询数据地址 + ret = FtpEnterPasv(ipaddr, &port); + if (ret != 1) + { + return 0; + } + ret = SocketConnect(m_socket_data, ipaddr, port); + if (ret != 1) + { + return 0; + } + //准备上传 + sprintf(m_send_buffer, "STOR %s\r\n", name); + ret = FtpSendCommand(m_send_buffer); + if (ret != 1) + { + return 0; + } + ret = FtpRecvRespond(m_recv_buffer, 1024); + if (ret != 150) + { + SocketClose(m_socket_data); + return 0; + } + + //开始上传 + ret = SocketSend(m_socket_data, buf, len); + if (ret != len) + { + LogInfo("send data error!\r\n"); + SocketClose(m_socket_data); + return 0; + } + SocketClose(m_socket_data); + + //上传完成,等待回应 + ret = FtpRecvRespond(m_recv_buffer, 1024); + return (ret == 226); +} + +//下载文件 +int FtpDownload(char* name, char* buf, int len) +{ + int i; + int ret; + char ipaddr[32]; + int port; + + //查询数据地址 + ret = FtpEnterPasv(ipaddr, &port); + if (ret != 1) + { + return 0; + } + + //连接数据端口 + ret = SocketConnect(m_socket_data, ipaddr, port); + if (ret != 1) + { + printf("errno = %d",errno); + LogInfo("failed to connect data port\r\n"); + return 0; + } + + //准备下载 + sprintf(m_send_buffer, "RETR %s\r\n", name); + ret = FtpSendCommand(m_send_buffer); + if (ret != 1) + { + return 0; + } + ret = FtpRecvRespond(m_recv_buffer, 1024); + if (ret != 150) + { + SocketClose(m_socket_data); + return 0; + } + + //开始下载,读取完数据后,服务器会自动关闭连接 + for (i = 0; i < len; i += ret) + { + ret = SocketRecv(m_socket_data, ((char*)buf) + i, len); + LogInfo("download %d/%d.\r\n", i + ret, len); + if (ret < 0) + { + LogInfo("download was interrupted.\r\n"); + break; + } + } + + //下载完成 + printf("\n下载完成 : \n %s",buf); + LogInfo("download %d/%d bytes complete.\r\n", i, len); + SocketClose(m_socket_data); + ret = FtpRecvRespond(m_recv_buffer, 1024); + return (ret == 226); +} + + +//返回文件大小 +int FtpFileSize(char* name) +{ + int ret; + int size; + sprintf(m_send_buffer, "SIZE %s\r\n", name); + ret = FtpSendCommand(m_send_buffer); + if (ret != 1) + { + return 0; + } + ret = FtpRecvRespond(m_recv_buffer, 1024); + if (ret != 213) + { + return 0; + } + size = atoi(m_recv_buffer + 4); + return size; +} + +//登陆服务器,成功返回1,失败返回0 +int FtpLogIn(char* addr, int port, char* username, char* password) +{ + int ret; + LogInfo("connect...\r\n"); + ret = SocketConnect(m_socket_cmd, addr, port); + if (ret != 1) + { + LogInfo("connect server failed!\r\n"); + return 0; + } + LogInfo("connect ok.\r\n"); + //等待欢迎信息 + ret = FtpRecvRespond(m_recv_buffer, 1024); + if (ret != 220) + { + LogInfo("bad server, ret=%d!\r\n", ret); + SocketClose(m_socket_cmd); + return 0; + } + ret = FtpRecvRespond(m_recv_buffer, 1024); + if (ret != 220) + { + LogInfo("bad server, ret=%d!\r\n", ret); + SocketClose(m_socket_cmd); + return 0; + } + ret = FtpRecvRespond(m_recv_buffer, 1024); + if (ret != 220) + { + LogInfo("bad server, ret=%d!\r\n", ret); + SocketClose(m_socket_cmd); + return 0; + } + + LogInfo("login...\r\n"); + //发送USER + sprintf(m_send_buffer, "USER %s\r\n", username); + ret = FtpSendCommand(m_send_buffer); + if (ret != 1) + { + SocketClose(m_socket_cmd); + return 0; + } + ret = FtpRecvRespond(m_recv_buffer, 1024); + if (ret != 331) + { + SocketClose(m_socket_cmd); + return 0; + } + + //发送PASS + sprintf(m_send_buffer, "PASS %s\r\n", password); + ret = FtpSendCommand(m_send_buffer); + if (ret != 1) + { + SocketClose(m_socket_cmd); + return 0; + } + ret = FtpRecvRespond(m_recv_buffer, 1024); + if (ret != 230) + { + SocketClose(m_socket_cmd); + return 0; + } + LogInfo("login success.\r\n"); + + //设置为二进制模式 + char command_binary[] = "TYPE I\r\n"; + ret = FtpSendCommand(command_binary); + if (ret != 1) + { + SocketClose(m_socket_cmd); + return 0; + } + ret = FtpRecvRespond(m_recv_buffer, 1024); + if (ret != 200) + { + SocketClose(m_socket_cmd); + return 0; + } + return 1; +} + +void FtpQuit(void) +{ + char command_quit[] = "QUIT\r\n"; + FtpSendCommand(command_quit); + SocketClose(m_socket_cmd); +} + +void FtpInit(void) +{ + m_socket_cmd = SocketCreate(); + m_socket_data = SocketCreate(); +} + diff --git a/APP_Framework/Applications/app_test/test_ftpclient/README.md b/APP_Framework/Applications/app_test/test_ftpclient/README.md new file mode 100644 index 000000000..22a8bf1b7 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_ftpclient/README.md @@ -0,0 +1,105 @@ +# **初赛一级赛题3:基于矽璓已实现的Lwip,在ARM上实现FTP协议的Client功能** + +参赛战队:bdislab_Rhodes + +赛题issue:初赛一级赛题3 + +完成情况:在ARM终端实现FTP Client的功能,即基于XiZi内核移植支持FTP Client库,执行 FTP协议的Client实现在搭建的FTP服务器上下载10个文件。 + +## 1. 简介 + +​ 基于矽璓已实现的Lwip,在ARM上实现FTP协议的Client功能,并从在个人电脑中搭建的FTP server上下载十个文件。 + +## 2. 数据结构设计说明 + +使用ftp_info结构体存储基本信息 + +```c +//配置信息 +typedef struct ftp_info +{ + char* ip;//目的服务器ip + int port;//目的端口号 + char* usrname;//登录ftp服务器使用的用户名 + char* password;//用户名对应的密码 + char** filepath;//要下载的文件路径 +}Client_Info; +``` + +主要实现了以下函数: + +```c +FtpInit();//创建套接字 + +FtpLogIn(char* addr, int port, char* username, char* password);//登录服务器 + +FtpFileSize(char* path);//查询path路径下的文件大小 + +FtpDownload(char* name, char* buf, int len);//下载path路径下的文件到buf + +FtpQuit();//关闭套接字 +``` + +## 3. 测试程序说明 + +测试程序 `TestFTP` 已经注册为 shell 命令,可以调用执行。 + +测试程序主要完成以下流程: + +- 录入基本信息,包括目标ip地址、端口号、用户名、密码、目标文件路径等。 +- 创建套接字 +- 登录服务器 +- 询问目标文件大小 +- 下载目标文件,并将下载到的内容打印出来 +- 关闭套接字 +- 重复上述动作共十次 + +由于程序中目标服务器端口号,用户名,密码以及要下载的文件路径在程序中被提前初始化好了,运行时只需要输入目标服务器的ip地址即可。 + +## 4. 运行结果 + +利用华大提供的烧录工具烧录入ARM教育开发板 + +![image-20231001230717436](image/image-20231001230717436.png) + +利用FileZilla建立FTP服务器 + +![image-20230930215803743](image/image-20230930215803743.png) + +利用xshell通过相应串口连上开发板,并通过Help指令查看帮助,发现TestFTP已成功注册 + +![image-20231001230846140](image/image-20231001230846140.png) + +利用setip指令设置ip + +image-20230930214729100 + +利用showip指令查看ip,设置成功 + +image-20230930214750512 + +使用已注册的TestFTP指令连接FTP服务器并下载十个文件 + +输入建立的FTP服务器ip,连接成功并收到欢迎信息 + +image-20230930214819589 + +发送用户名及密码进行登录,成功登录并发送TYPE I指令进入二进制模式 + +image-20230930215122449 + +从FTP服务器上查询目标文件大小并进行下载,下载完成后输出下载到的内容 + +![image-20230930215346610](image/image-20230930215346610.png) + +第一个文件下载完毕,紧接着下载后续九个文件,部分下载到的内容如下 + +![image-20230930215455339](image/image-20230930215455339.png) + +![image-20230930215507232](image/image-20230930215507232.png) + +![image-20230930215526406](image/image-20230930215526406.png) + +回到FTP服务器的界面可以看到之前收到的命令请求 + +![image-20230930215726004](image/image-20230930215726004.png) \ No newline at end of file diff --git a/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930214729100.png b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930214729100.png new file mode 100644 index 000000000..e312d17c5 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930214729100.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930214750512.png b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930214750512.png new file mode 100644 index 000000000..8ebcbbb7f Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930214750512.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930214819589.png b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930214819589.png new file mode 100644 index 000000000..897437e1b Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930214819589.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930215122449.png b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930215122449.png new file mode 100644 index 000000000..b7e696645 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930215122449.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930215346610.png b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930215346610.png new file mode 100644 index 000000000..a663ec071 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930215346610.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930215455339.png b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930215455339.png new file mode 100644 index 000000000..66f170306 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930215455339.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930215507232.png b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930215507232.png new file mode 100644 index 000000000..57cef0ae9 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930215507232.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930215526406.png b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930215526406.png new file mode 100644 index 000000000..ccea45a65 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930215526406.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930215726004.png b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930215726004.png new file mode 100644 index 000000000..43cb3163f Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930215726004.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930215803743.png b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930215803743.png new file mode 100644 index 000000000..009dbbabb Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20230930215803743.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient/image/image-20231001223346408.png b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20231001223346408.png new file mode 100644 index 000000000..2b682e6e7 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20231001223346408.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient/image/image-20231001230717436.png b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20231001230717436.png new file mode 100644 index 000000000..3d0233994 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20231001230717436.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient/image/image-20231001230846140.png b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20231001230846140.png new file mode 100644 index 000000000..8f2cb4ec0 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient/image/image-20231001230846140.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient/log.h b/APP_Framework/Applications/app_test/test_ftpclient/log.h new file mode 100644 index 000000000..9695a8dca --- /dev/null +++ b/APP_Framework/Applications/app_test/test_ftpclient/log.h @@ -0,0 +1,61 @@ +/* +* Copyright (c) 2020 AIIT Ubiquitous Team +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL +v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file: log.h +* @brief: a application of ftp client function +* @version: 1.0 +* @author: bdislab_Rhodes +* @date: 2023/9/30 +*/ + +#ifndef __my__LOG_H +#define __my__LOG_H + +#include +#include +#include + + + +void LogInfo(const char* format, ...) { + va_list args; + va_start(args, format); + int len = strlen(format); + // 只使用空格作为分隔符 + for (int i = 0; i < len; ++i) { + if (format[i] == '%') { + if (format[i + 1] == 'd') { + int val = va_arg(args, int); + printf("%d",val); + } + else if (format[i + 1] == 's') { + char* s = va_arg(args, char*); + printf("%s",s); + } + i++; + continue; + } + else if (format[i] == ' ') { + printf("%c",' '); + } + else { + printf("%c",format[i]); + } + } + printf("\n"); + va_end(args); +} + +#endif + diff --git a/APP_Framework/Applications/app_test/test_ftpclient/mysocket.h b/APP_Framework/Applications/app_test/test_ftpclient/mysocket.h new file mode 100644 index 000000000..e806de964 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_ftpclient/mysocket.h @@ -0,0 +1,70 @@ +/* +* Copyright (c) 2020 AIIT Ubiquitous Team +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL +v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file: mysocket.c +* @brief: a application of ftp client function +* @version: 1.0 +* @author: bdislab_Rhodes +* @date: 2023/9/30 +*/ + +#ifndef __SOCKET_H +#define __SOCKET_H + +#include +#include + +int SocketCreate(void); +int SocketConnect(int ,char* , int ); +void SocketClose(int ); +int SocketSend(int sock, void* data, int len); +int SocketRecv(int sock, void* data, int len); + + + +int SocketCreate(void) { + return socket(AF_INET, SOCK_STREAM, 0); +} + + +int SocketConnect(int sock, char* addr, int port) { + struct sockaddr_in seraddr; + memset(&seraddr, 0, sizeof(seraddr));//初始化seraddr + seraddr.sin_family = AF_INET; + //本机字节序转换为网络字节序(包括ip与端口号) + //通过传给main的参数获取服务器端口号与ip + seraddr.sin_port = htons(port);//端口号 + seraddr.sin_addr.s_addr = inet_addr(addr);//ip + memset(&(seraddr.sin_zero), 0, sizeof(seraddr.sin_zero)); + printf("test point 1\n"); + return 1+connect(sock, (struct sockaddr*)&seraddr, sizeof(seraddr)); +} + + +void SocketClose(int sock) { + close(sock); +} + + +int SocketSend(int sock, void* buf, int len) { + return send(sock, buf, len, 0); +} + + +int SocketRecv(int sock, void* buf, int len) { + return recv(sock, buf, len, 0); + } + + +#endif diff --git a/APP_Framework/Applications/app_test/test_ftpclient/test_ftpclient.c b/APP_Framework/Applications/app_test/test_ftpclient/test_ftpclient.c new file mode 100644 index 000000000..5731acb1e --- /dev/null +++ b/APP_Framework/Applications/app_test/test_ftpclient/test_ftpclient.c @@ -0,0 +1,107 @@ +/* +* Copyright (c) 2020 AIIT Ubiquitous Team +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL +v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file: test_ftpclient.c +* @brief: a application of ftp client function +* @version: 1.0 +* @author: bdislab_Rhodes +* @date: 2023/9/30 +*/ + +#include"FTP_client.h" +#include + +#define NUM_OF_FILES 10 + +//配置信息 +typedef struct ftp_info +{ + char* ip;//目的服务器ip + int port;//目的端口号 + char* usrname;//登录ftp服务器使用的用户名 + char* password;//用户名对应的密码 + char** filepath;//要下载的文件路径 +}Client_Info; + + +int TestFTP(){ + + //信息初始化 + Client_Info info = {.ip = "192.168.1.102", + .port = 21, + .usrname = "lyq1", + .password = "255967558" + }; + + info.filepath = (char**)malloc(10* sizeof(char*)); + + char *file[] = {"testfile1.txt","testfile2.txt","testfile3.txt","testfile4.txt","testfile5.txt", + "testfile6.txt","testfile7.txt","testpicture1.txt","testpicture2.txt","testpicture3.txt"}; + + info.filepath = file; + + char _ip[15]; + + printf("请输入ip: "); + + scanf("%s",_ip); + + info.ip = _ip; + + printf("ip input = %s\n",info.ip); + + + + //逐个询问filepath中每个文件的大小并下载 + for(int i = 0;imntp->fs->ioctl(fdp, cmd, (void*)va_arg(ap, long)); - va_end(ap); + + ret = fdp->mntp->fs->ioctl(fdp, cmd, (void*)argp); + if (ret < 0) { SYS_ERR("%s: ioctl file failed\n", __func__); KUpdateExstatus(ret);