2023_open_source_contest_preliminary_1st_issue3
|
@ -134,7 +134,7 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
|||
endif
|
||||
|
||||
ifeq ($(CONFIG_USER_TEST_FTPCLIENT),y)
|
||||
SRC_FILES +=
|
||||
SRC_FILES += test_ftpclient/test_ftpclient.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_USER_TEST_LORA_P2P),y)
|
||||
|
|
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 112 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 89 KiB |
After Width: | Height: | Size: 102 KiB |
After Width: | Height: | Size: 102 KiB |
After Width: | Height: | Size: 104 KiB |
After Width: | Height: | Size: 100 KiB |
After Width: | Height: | Size: 75 KiB |
After Width: | Height: | Size: 6.7 KiB |
|
@ -0,0 +1,70 @@
|
|||
# 基于矽璓已实现的Lwip,在ARM上实现FTP协议的Client功能并测试验证 ##
|
||||
|
||||
## 1. 简介
|
||||
基于XiUOS中的Lwip协议和提供的接口,实现了FTP客户端的基本功能,包括登录(验证用户账号和密码)、文件目录显示(ls)、文件目录进入(cd)、文件下载等。
|
||||
|
||||
按照题目要求,FTP服务器端搭建在我们队员的个人电脑上,系统版本为Windows10专业版,利用Windows自带的Internet Information Services (IIS) 6.0 管理器对自定义FTP站点进行了创建及管理。
|
||||
此外,我们还借助FileZilla Server Interface在实现过程中辅助监测连接与传输情况,但最后提交代码所实现的数据上传下载实现过程不涉及FileZilla使用。
|
||||
|
||||
## 2. 函数功能设计说明
|
||||
`FillServerAddr`:Bind the server IP address <br />
|
||||
`CreateControlConnection`:Create a control connection <br />
|
||||
`CreateDataConnection`:Create a data connection <br />
|
||||
`GetReplyMsg`:Get a reply message <br />
|
||||
`SendControlCommand`:Send control command <br />
|
||||
`LoginServer`:Logging In to the FTP Server <br />
|
||||
`PasvInitiateFileDownload`:Before downloading the file, send the PASV command to enter passive mode, and the FTP server will open a new port for receiving the file data. <br />
|
||||
`FileDownload`:Download the file from the server <br />
|
||||
`ListCurrentDirectory`:Implement the ls command to display the files and directories in the current directory <br />
|
||||
`ChangeDirectory`:Run the cd command to go to the target directory <br />
|
||||
`Quit`:Log out of the server <br />
|
||||
`TestFTPClient`:The function we used to test FTP client, realized . <br />
|
||||
|
||||
|
||||
## 3. 测试程序说明
|
||||
在ARM终端上实现了FTP Client的功能,
|
||||
|
||||
|
||||
## 4. 运行结果(##需结合运行测试截图按步骤说明##)
|
||||
① 编译及开启本地FTP服务器准备<br />
|
||||
 <br />
|
||||
menuconfig中使能LwIP网络协议栈
|
||||
|
||||
 <br />
|
||||
打开menuconfig之后,将test ftp client开启(y),保存后退出
|
||||
|
||||
 <br />
|
||||
使用
|
||||
“make BOARD=edu-arm32 distclean <br />
|
||||
make BOARD=edu-arm32 menuconfig <br />
|
||||
make BOARD=edu-arm32”命令,编译XiZi-edu-arm32.bin成功,编译得到的“XiZi-edu-arm32.bin”文件我们已附在文件夹中,供评委检验。 <br />
|
||||
|
||||
 <br />
|
||||
打开控制面板,选择“程序”,点击“启用或关闭Windows功能”。选择"Internet Information Services"下的FTP服务器中的FTP服务复选框,同时勾选web管理工具下的IIS管理控制台。<br />
|
||||
|
||||
 <br />
|
||||
win+R输入inetmgr打开IIS管理器,设置站点名称、IP地址、存储物理路径、SSL设置(方便起见可设置无SSL)、身份验证(设置匿名或授权访问均可,可自行生成所需SSL证书)等。
|
||||
|
||||
 <br />
|
||||
之后关闭电脑防火墙以防数据被误拦截,在身份验证时输入账号密码登录FTP服务器,通过身份验证,本地FTP服务器准备即告完成。
|
||||
|
||||
② 测试ARM终端数据下载
|
||||
 <br />
|
||||
首先展示本地FTP服务器存放的测试文件,每个文件均为自动化脚本生成,大小为严格的4KB。 <br />
|
||||
|
||||
 <br />
|
||||
启动本地FTP服务器,确保连接。 <br />
|
||||
|
||||
 <br />
|
||||
首先通过ls命令,展示ARM终端现有的文件情况,可以看到目前仅有2个之前生成的测试用文件,我们可以将其忽略。 <br />
|
||||
|
||||
 <br />
|
||||
 <br />
|
||||
 <br />
|
||||
 <br />
|
||||
 <br />
|
||||
 <br />
|
||||
输入执行TestFTPClient命令,ARM终端作为客户端开始访问服务器端下载指定的10个大小为4KB的.txt文件。对于每个文件的数据端口访问及接受数据、下载情况,打印出的提示信息中均有详细解释。 <br />
|
||||
|
||||
 <br />
|
||||
下载完成后,再次使用ls命令展示ARM终端作为客户端访问服务器端下载指定的10个大小为4KB的.txt文件,可以看到,相比最开始,终端上多了10个大小为4KB的文件,即一开始存放在本地服务器上的文件。 <br />
|
After Width: | Height: | Size: 73 KiB |
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 119 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 108 KiB |
After Width: | Height: | Size: 121 KiB |
|
@ -0,0 +1,313 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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: Based on the protocol Lwip in XiUOS and the interface provided, this
|
||||
file realized the basic functions of the FTP client, including login (verifying
|
||||
user account and password), file directory display (ls), file directory entry (cd),
|
||||
file download, etc.
|
||||
* @version: 1.0
|
||||
* @author: Oscar
|
||||
* @date: 2023/8/25
|
||||
*/
|
||||
|
||||
#include <transform.h>
|
||||
#include "test_ftpclient.h"
|
||||
|
||||
struct sockaddr_in ftp_server_ctrl_addr; // Saves information about the control connection
|
||||
struct sockaddr_in ftp_server_data_addr; // Saves data connection information
|
||||
int sockfd_ctrl; // The socket that controls the connection
|
||||
int sockfd_data; // The socket for the data connection
|
||||
char server_ip_str[20]; // ip address of the FTP server
|
||||
int server_port; // Port number of the FTP server
|
||||
char msg_buffer[MAX_BUF_LEN]; // Message sent to the FTP server
|
||||
char data_buffer[MAX_BUF_LEN]; // Send or receive data from the FTP server
|
||||
|
||||
/**
|
||||
* @description: Bind the server IP address
|
||||
* @param ip - ip address
|
||||
* @param port - server port
|
||||
* @param str_server_addr - struct for save ip information
|
||||
* @return void
|
||||
*/
|
||||
void FillServerAddr(const char* ip, unsigned short int port,struct sockaddr_in* str_server_addr)
|
||||
{
|
||||
memset(str_server_addr, 0,sizeof(struct sockaddr_in));
|
||||
str_server_addr->sin_family = AF_INET;
|
||||
str_server_addr->sin_port = htons(port);
|
||||
str_server_addr->sin_addr.s_addr = inet_addr(ip);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Create a control connection
|
||||
* @return 0 means success, -1 means fail
|
||||
*/
|
||||
int CreateControlConnection()
|
||||
{
|
||||
sockfd_ctrl = socket(AF_INET, SOCK_STREAM, 0); // create socket descriptor
|
||||
if(sockfd_ctrl == -1){
|
||||
printf("[Error] Create socket failed!\n");
|
||||
return -1;
|
||||
}
|
||||
printf("[Info] create socket success.\nbegin to connect.\n");
|
||||
|
||||
if(connect(sockfd_ctrl,(struct sockaddr *)&ftp_server_ctrl_addr,sizeof(struct sockaddr)) == 0){ // connect to the server
|
||||
printf("Successfully connect to server:ip:%s,port:%d\n",
|
||||
inet_ntoa(ftp_server_ctrl_addr.sin_addr) ,ntohs(ftp_server_ctrl_addr.sin_port));
|
||||
}else{
|
||||
printf("[Error] control connect failed!\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Create a data connection
|
||||
* @return 0 means success, -1 means fail
|
||||
*/
|
||||
int CreateDataConnection()
|
||||
{
|
||||
sockfd_data = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sockfd_data == -1){
|
||||
printf("[Error] Create socket failed!");
|
||||
return -1;
|
||||
}
|
||||
if (connect(sockfd_data, (struct sockaddr*)&ftp_server_data_addr, sizeof(struct sockaddr_in)) == 0){
|
||||
printf("[Info] Successfully connect to server:ip:%s,port:%d\n", inet_ntoa(ftp_server_data_addr.sin_addr), ntohs(ftp_server_data_addr.sin_port));
|
||||
}else{
|
||||
printf("[Error] data connect failed!\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Get a reply message
|
||||
* @return void
|
||||
*/
|
||||
int GetReplyMsg()
|
||||
{
|
||||
int receive_byte_count, reply;
|
||||
memset(msg_buffer, 0, MAX_BUF_LEN);
|
||||
receive_byte_count = lwip_read(sockfd_ctrl, msg_buffer, MAX_BUF_LEN);
|
||||
reply = atoi(msg_buffer);
|
||||
printf("[Info] receive bytes: %d, Server reply: %s\n", receive_byte_count, msg_buffer);
|
||||
return reply;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Send control command
|
||||
* @param send_msg - message need send
|
||||
* @return void
|
||||
*/
|
||||
void SendControlCommand(const char* send_msg)
|
||||
{
|
||||
send(sockfd_ctrl, send_msg, strlen(send_msg), 0);
|
||||
printf("[Info] Send tcp msg: %s\n", send_msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Logging In to the FTP Server
|
||||
* @param username - server login username
|
||||
* @param password - server login password
|
||||
* @return 0 means success, -1 means fail
|
||||
*/
|
||||
int LoginServer(char *username, char *password)
|
||||
{
|
||||
if (NULL == username || NULL == password) {
|
||||
printf("[Error] username or password can not be NULL\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(msg_buffer, "USER %s\r\n", username);
|
||||
SendControlCommand(msg_buffer);
|
||||
GetReplyMsg();
|
||||
sprintf(msg_buffer, "PASS %s\r\n", password);
|
||||
SendControlCommand(msg_buffer);
|
||||
if (230 == GetReplyMsg())
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Before downloading the file, send the PASV command to enter passive mode, and the FTP server will open a new port for receiving the file data.
|
||||
* @return the new port for data connection
|
||||
*/
|
||||
int PasvInitiateFileDownload()
|
||||
{
|
||||
int passive_port = -1;
|
||||
SendControlCommand("PASV\r\n");
|
||||
GetReplyMsg();
|
||||
char *ip_and_port_str = strrchr(msg_buffer, '(');
|
||||
int ip_first, ip_second, ip_third, ip_fourth, high_port, low_port;
|
||||
sscanf(ip_and_port_str, "(%d,%d,%d,%d,%d,%d)", &ip_first, &ip_second, &ip_third, &ip_fourth, &high_port, &low_port);
|
||||
passive_port = high_port * 256 + low_port;
|
||||
return passive_port;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Download the file from the server
|
||||
* @param filename - name of download file
|
||||
* @return void
|
||||
*/
|
||||
void FileDownload(char *filename)
|
||||
{
|
||||
if (NULL == filename) {
|
||||
printf("[Error] file name can not be NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
SendControlCommand("TYPE I\r\n");
|
||||
GetReplyMsg();
|
||||
sprintf(msg_buffer,"SIZE %s\r\n",filename);
|
||||
SendControlCommand(msg_buffer);
|
||||
GetReplyMsg();
|
||||
int file_size = atoi(msg_buffer + 4);
|
||||
printf("[Info] %s filesize: %d\n", filename, file_size);
|
||||
|
||||
// passive
|
||||
int passive_port = PasvInitiateFileDownload();
|
||||
if (passive_port > 0)
|
||||
FillServerAddr(server_ip_str, passive_port, &ftp_server_data_addr);
|
||||
sprintf(msg_buffer,"RETR %s\r\n",filename);
|
||||
SendControlCommand(msg_buffer);
|
||||
if (CreateDataConnection() < 0){
|
||||
printf("[Error] unable to connect data port\n");
|
||||
return;
|
||||
}
|
||||
GetReplyMsg();
|
||||
|
||||
// create file and write message to file
|
||||
int file_fd = PrivOpen(filename,O_RDWR | O_CREAT);
|
||||
if (file_fd < 0){
|
||||
printf("[Error] error to open file!\n");
|
||||
}
|
||||
printf("[Info] begin to download %s\n",filename);
|
||||
int download_bytes_count = 0, current_download_bytes_count = 0;
|
||||
memset(data_buffer,0,sizeof(data_buffer));
|
||||
while ((current_download_bytes_count = lwip_read(sockfd_data,data_buffer,MAX_BUF_LEN)) > 0){
|
||||
PrivWrite(file_fd,data_buffer, current_download_bytes_count);
|
||||
download_bytes_count += current_download_bytes_count;
|
||||
printf("== %d/%d bytes received\n", download_bytes_count, file_size);
|
||||
}
|
||||
printf("[Info] total %d bytes received. download %s succeed.\n", download_bytes_count, filename);
|
||||
lwip_close(sockfd_data);
|
||||
PrivClose(file_fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Implement the ls command to display the files and directories in the current directory
|
||||
* @return void
|
||||
*/
|
||||
void ListCurrentDirectory()
|
||||
{
|
||||
int passive_port = PasvInitiateFileDownload();
|
||||
if (passive_port > 0)
|
||||
FillServerAddr(server_ip_str, passive_port, &ftp_server_data_addr);
|
||||
SendControlCommand("LIST\r\n");
|
||||
if (CreateDataConnection() < 0){
|
||||
printf("[Error] unable to connect data port\n");
|
||||
return;
|
||||
}
|
||||
printf("[Info] Recving data! please wait....\n");
|
||||
int receive_bytes_count = lwip_read(sockfd_data, data_buffer, MAX_BUF_LEN);
|
||||
printf("%s\n", data_buffer);
|
||||
lwip_close(sockfd_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Run the cd command to go to the target directory
|
||||
* @param pathname - target directory
|
||||
* @return void
|
||||
*/
|
||||
void ChangeDirectory(char *pathname)
|
||||
{
|
||||
if (NULL == pathname) {
|
||||
printf("[Error] path name can not be NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sprintf(msg_buffer,"CWD %s\r\n",pathname);
|
||||
SendControlCommand(msg_buffer);
|
||||
GetReplyMsg();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Log out of the server
|
||||
* @return void
|
||||
*/
|
||||
void Quit()
|
||||
{
|
||||
SendControlCommand("QUIT\r\n");
|
||||
GetReplyMsg();
|
||||
lwip_close(sockfd_ctrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Test FTP client.
|
||||
*/
|
||||
void TestFTPClient(int argc, char* argv[])
|
||||
{
|
||||
printf("-------------------Config Network-------------------\n");
|
||||
// Set an ip address for the development board
|
||||
char board_ipaddr[] = { 192, 168, 1, 103 }; // ip address of the development board to be set
|
||||
char board_netmask[] = { 255, 255, 255, 0 }; // Subnet mask of the development board
|
||||
char board_gwaddr[] = { 192, 168, 1, 0 }; // Development board gateway
|
||||
lwip_config_tcp(0, board_ipaddr, board_netmask, board_gwaddr);
|
||||
|
||||
// connect
|
||||
printf("-------------------Connect-------------------\n");
|
||||
char connect_ip_addr[] = "192.168.1.100";// ftp server ipaddr
|
||||
int connect_port = 21; // ftp server port
|
||||
sprintf(server_ip_str,connect_ip_addr);
|
||||
server_port = connect_port;
|
||||
FillServerAddr(server_ip_str, server_port, &ftp_server_ctrl_addr);
|
||||
CreateControlConnection();
|
||||
GetReplyMsg();
|
||||
|
||||
// login, set username and password here
|
||||
printf("-------------------Login-------------------\n");
|
||||
char username[] = "linha";
|
||||
char password[] = "guoji123";
|
||||
if (LoginServer(username, password) == 0){
|
||||
printf("success login.\n");
|
||||
}
|
||||
else{
|
||||
printf("login fail.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// TestFTPClient
|
||||
printf("-------------------TestFTPClient-------------------\n");
|
||||
|
||||
printf("-------------------List Directory-------------------\n");
|
||||
ListCurrentDirectory(); // ls
|
||||
|
||||
printf("-------------------Change Directory-------------------\n");
|
||||
char change_to_directory[] = "file";
|
||||
ChangeDirectory(change_to_directory); // cd file
|
||||
|
||||
printf("-------------------List 10 files need to download-------------------\n");
|
||||
ListCurrentDirectory(); // ls
|
||||
|
||||
printf("-------------------Download 10 files-------------------\n");
|
||||
char test_files[][10] = {"foo.txt", "baz.txt", "bar.txt", "tab.txt", "tap.txt", "out.txt", "hot.txt", "egg.txt", "cat.txt", "num.txt"};
|
||||
for (int i = 0; i < 10; i++) {
|
||||
FileDownload(test_files[i]); // download
|
||||
}
|
||||
|
||||
printf("-------------------Quit-------------------\n");
|
||||
Quit(); // quit
|
||||
}
|
||||
PRIV_SHELL_CMD_FUNCTION(TestFTPClient, a simple test FTPClient sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2023 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.h
|
||||
* @brief: Based on the protocol Lwip in XiUOS and the interface provided, this
|
||||
file realized the basic functions of the FTP client, including login (verifying
|
||||
user account and password), file directory display (ls), file directory entry (cd),
|
||||
file download, etc.
|
||||
* @version: 1.0
|
||||
* @author: Oscar
|
||||
* @date: 2023/8/25
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys_arch.h>
|
||||
#include "lwip/sockets.h"
|
||||
|
||||
#define MAX_BUF_LEN 4096 // Maximum cache bytes 4k
|
||||
|
||||
// Bind the server IP address
|
||||
void FillServerAddr(const char* ip, unsigned short int port, struct sockaddr_in* pServer_addr);
|
||||
|
||||
// Create a control connection
|
||||
int CreateControlConnection();
|
||||
|
||||
// Create a data connection
|
||||
int CreateDataConnection();
|
||||
|
||||
// Get a reply message
|
||||
int GetReplyMsg(void);
|
||||
|
||||
// Send control command
|
||||
void SendControlCommand(const char* send_msg);
|
||||
|
||||
// Logging In to the FTP Server
|
||||
int LoginServer(char* username, char* password);
|
||||
|
||||
// Before downloading the file, send the PASV command to enter passive mode, and the
|
||||
// FTP server will open a new port for receiving the file data.
|
||||
int PasvInitiateFileDownload();
|
||||
|
||||
// Download the file from the server
|
||||
void FileDownload(char* filename);
|
||||
|
||||
// Implement the ls command to display the files and directories in the current
|
||||
// directory
|
||||
void ListCurrentDirectory();
|
||||
|
||||
// Run the cd command to go to the target directory
|
||||
void ChangeDirectory(char* pathname);
|
||||
|
||||
// Log out of the server
|
||||
void Quit(void);
|