update 2023_open_source_contest pr to prepare_for_master
it is OK
|  | @ -270,6 +270,10 @@ menu "test app" | ||||||
|                 bool "Config test red black tree" |                 bool "Config test red black tree" | ||||||
|                 default n |                 default n | ||||||
| 
 | 
 | ||||||
|  |             menuconfig USER_TEST_MODBUS_TCP | ||||||
|  |                 bool "Config test modbus_tcp" | ||||||
|  |                 default n | ||||||
|  | 
 | ||||||
|             menuconfig USER_TEST_WEBSERVER |             menuconfig USER_TEST_WEBSERVER | ||||||
|                 bool "Config test webserver" |                 bool "Config test webserver" | ||||||
|                 default n |                 default n | ||||||
|  | @ -282,6 +286,10 @@ menu "test app" | ||||||
|                 bool "Config test ftp client" |                 bool "Config test ftp client" | ||||||
|                 default n |                 default n | ||||||
|              |              | ||||||
|  |             menuconfig USER_TEST_FTPCLIENT_RISCV | ||||||
|  |                 bool "Config test ftp client on riscv" | ||||||
|  |                 default n | ||||||
|  | 
 | ||||||
|             menuconfig USER_TEST_LORA_P2P |             menuconfig USER_TEST_LORA_P2P | ||||||
|                 bool "Config test lora p2p" |                 bool "Config test lora p2p" | ||||||
|                 default n |                 default n | ||||||
|  |  | ||||||
|  | @ -131,16 +131,26 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y) | ||||||
|         SRC_FILES += test_socket.c |         SRC_FILES += test_socket.c | ||||||
|     endif     |     endif     | ||||||
| 
 | 
 | ||||||
|  |     ifeq ($(CONFIG_USER_TEST_MODBUS_TCP),y) | ||||||
|  |         SRC_DIR += test_modbus_tcp | ||||||
|  |     endif  | ||||||
|  | 	 | ||||||
|     ifeq ($(CONFIG_USER_TEST_WEBSERVER),y) |     ifeq ($(CONFIG_USER_TEST_WEBSERVER),y) | ||||||
|         SRC_FILES +=  |         SRC_FILES += test_webserver/test_webserver.c | ||||||
|     endif |     endif | ||||||
| 
 | 
 | ||||||
|     ifeq ($(CONFIG_USER_TEST_MQTTCLIENT),y) |     ifeq ($(CONFIG_USER_TEST_MQTTCLIENT),y) | ||||||
|  |         SRC_DIR:= test_mqttclient | ||||||
|         SRC_FILES +=  |         SRC_FILES +=  | ||||||
|     endif |     endif | ||||||
| 
 | 
 | ||||||
|     ifeq ($(CONFIG_USER_TEST_FTPCLIENT),y) |     ifeq ($(CONFIG_USER_TEST_FTPCLIENT),y) | ||||||
|         SRC_FILES +=  |         SRC_FILES += test_ftpclient/test_ftpclient.c test_ftpclient/ftp_client/ftp_client.c\
 | ||||||
|  |                      test_ftpclient/ftp_client/my_socket.c | ||||||
|  |     endif | ||||||
|  | 
 | ||||||
|  | 	ifeq ($(CONFIG_USER_TEST_FTPCLIENT_RISCV),y) | ||||||
|  |         SRC_FILES += test_ftpclient_riscv/test_ftpclient_riscv.c | ||||||
|     endif |     endif | ||||||
| 
 | 
 | ||||||
|     ifeq ($(CONFIG_USER_TEST_LORA_P2P),y) |     ifeq ($(CONFIG_USER_TEST_LORA_P2P),y) | ||||||
|  | @ -159,5 +169,9 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y) | ||||||
|         SRC_FILES +=  |         SRC_FILES +=  | ||||||
|     endif |     endif | ||||||
| 
 | 
 | ||||||
|  |     ifeq ($(CONFIG_USER_TEST_FTPCLIENT_FINAL),y) | ||||||
|  |         SRC_FILES += test_ftpclient_final/test_ftpclient_final.c test_ftpclient_final/ftp_client/ftp_client.c test_ftpclient_final/ftp_client/my_socket.c | ||||||
|  |     endif    | ||||||
|  | 
 | ||||||
|     include $(KERNEL_ROOT)/compiler.mk |     include $(KERNEL_ROOT)/compiler.mk | ||||||
| endif | endif | ||||||
|  |  | ||||||
|  | @ -0,0 +1,60 @@ | ||||||
|  | # 初赛一级赛题3:基于矽璓已实现的Lwip,在ARM上实现FTP协议的Client功能 | ||||||
|  | 
 | ||||||
|  | ## 1. 简介 | ||||||
|  | 本项目是基于矽璓已实现的Lwip,在ARM上实现FTP协议的Client功能 | ||||||
|  | test_ftpclient.h声明了下载10个文件的测试函数 | ||||||
|  | test_ftpclient.c实现了下载10个文件的测试函数 | ||||||
|  | ftp_client文件夹定义了ftp_client的相关类库其中my_socket.h,my_socket.c定义了socket抽象层,并基于 | ||||||
|  | Lwip实现了该抽象层,ftp_client.h,ftp_client.c实现了ftp登录,获取文件大小,下载文件等功能 | ||||||
|  | 
 | ||||||
|  | ## 2. 数据结构设计说明 | ||||||
|  | - ftp_client.c 的设计 | ||||||
|  | 分别定义了发送命令和接收数据的socket和相应的缓冲区并且实现了登录、发送命令、接收响应数据、查找文件大小、进入被动模式、下载文件、关闭ftp客户端等操作 | ||||||
|  | ```c | ||||||
|  | static int  m_socket_cmd; // 发送命令的socket文件描述符 | ||||||
|  | static int  m_socket_data; // 接收ftp服务器文件的socket文件描述符 | ||||||
|  | static char m_send_buffer[1024]; // 发送缓冲区 | ||||||
|  | static char m_recv_buffer[1024];  // 接收缓冲区 | ||||||
|  | ``` | ||||||
|  | ## 3. 测试程序说明 | ||||||
|  | - test_ftpclient.c用于测试下载10个文件 | ||||||
|  | 连接电脑上的ftp服务器下载10个4KB文件,通过终端日志打印确定文件是否下载成功,以及追踪通信流程和下载进度 | ||||||
|  | ```c | ||||||
|  | void TestFtpClient(int argc, char* argv[]) | ||||||
|  | { | ||||||
|  |     FtpInitCmd(); | ||||||
|  |     int ret = FtpLogin("192.168.0.248", 21, "anonymous", "anonymous"); | ||||||
|  |     int size; | ||||||
|  |     char *buf; | ||||||
|  |     for(int i = 1;i <= 10;i++){ | ||||||
|  |         char fileName[20] = "/file";  | ||||||
|  |         char temp[5] = ""; | ||||||
|  |         sprintf(temp,"%d",i); | ||||||
|  |         strcat(fileName,temp); | ||||||
|  |         size = FtpFileSize(fileName); | ||||||
|  |         buf = malloc(size); | ||||||
|  |         FtpInitData();  // data socket 每次下载都要重新创建,下载完都要关闭 | ||||||
|  |         ret = FtpDownload(fileName, buf, size); | ||||||
|  |         free(buf); | ||||||
|  |     } | ||||||
|  |     FtpQuit(); | ||||||
|  |     return; | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ## 4. 运行结果(##需结合运行测试截图按步骤说明##) | ||||||
|  | 1. 配置开启BSP_USING_LWIP、USER_TEST_FTPCLIENT | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 2. 编译 | ||||||
|  |  | ||||||
|  | 3. 烧写 | ||||||
|  |  | ||||||
|  | 4. xshell连接串口终端 | ||||||
|  |  | ||||||
|  | 6. 配置ip | ||||||
|  |  | ||||||
|  | 7. 运行TestFtpClient,开始下载文件 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @ -0,0 +1,256 @@ | ||||||
|  | /*
 | ||||||
|  | * Copyright (c) 2020 AIIT XUOS Lab | ||||||
|  | * 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.c | ||||||
|  | * @brief:   ftp client tool | ||||||
|  | * @version: 1.0 | ||||||
|  | * @author:  bdislab_final | ||||||
|  | * @date:    2023/7/25 | ||||||
|  | * @reference https://kerndev.blog.csdn.net/article/details/89383888
 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | #include "my_socket.h" | ||||||
|  | #include "ftp_client.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; | ||||||
|  | 	printf("send command: %s\r\n", cmd); | ||||||
|  | 	ret = SocketSend(m_socket_cmd, cmd, (int)strlen(cmd)); | ||||||
|  | 	if(ret < 0) | ||||||
|  | 	{ | ||||||
|  | 		printf("failed to send command: %s\r\n",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) | ||||||
|  | 		{ | ||||||
|  | 			printf("recv respond error(ret=%d)!\r\n", ret); | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 		if(resp[off] == '\n') | ||||||
|  | 		{ | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	resp[off+1] = 0; | ||||||
|  | 	printf("respond:%s\r\n", resp); | ||||||
|  | 	return atoi(resp); | ||||||
|  | } | ||||||
|  |   | ||||||
|  | static int FtpEnterPasv(char *ipaddr, int *port) | ||||||
|  | { | ||||||
|  | 	int ret; | ||||||
|  | 	char *find; | ||||||
|  | 	int a,b,c,d; | ||||||
|  | 	int pa,pb; | ||||||
|  | 	ret = FtpSendCommand("PASV\r\n"); | ||||||
|  | 	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  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("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); | ||||||
|  | 		printf("download %d/%d.\r\n", i + ret, len); | ||||||
|  | 		if(ret < 0) | ||||||
|  | 		{ | ||||||
|  | 			printf("download was interrupted.\r\n"); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	//下载完成
 | ||||||
|  | 	printf("download %d/%d bytes complete.\r\n", i, len); | ||||||
|  | 	printf("====file content====\n"); | ||||||
|  | 	buf[100] = '\0'; | ||||||
|  | 	printf("%s\n",buf); | ||||||
|  | 	printf("====================\n"); | ||||||
|  |     // FILE *fp = NULL;
 | ||||||
|  | 
 | ||||||
|  |     // fp = fopen(name+1, "wb");
 | ||||||
|  |     // fwrite(buf,len,1,fp);
 | ||||||
|  |     // fclose(fp);
 | ||||||
|  | 
 | ||||||
|  | 	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; | ||||||
|  | } | ||||||
|  |   | ||||||
|  | int FtpLogin(char *addr, int port, char *username, char *password) | ||||||
|  | { | ||||||
|  | 	int ret; | ||||||
|  | 	printf("connect...\r\n"); | ||||||
|  | 	ret = SocketConnect(m_socket_cmd, addr, port); | ||||||
|  | 	if(ret != 1) | ||||||
|  | 	{ | ||||||
|  | 		printf("connect server failed!\r\n"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	printf("connect ok.\r\n"); | ||||||
|  |     //等待欢迎信息
 | ||||||
|  | 	ret = FtpRecvRespond(m_recv_buffer, 1024); | ||||||
|  | 	if(ret != 220) | ||||||
|  | 	{ | ||||||
|  | 		printf("bad server, ret=%d!\r\n", ret); | ||||||
|  | 		SocketClose(m_socket_cmd); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	printf("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; | ||||||
|  | 	} | ||||||
|  | 	printf("login success.\r\n"); | ||||||
|  | 	 | ||||||
|  |     //设置为二进制模式
 | ||||||
|  | 	ret = FtpSendCommand("TYPE I\r\n"); | ||||||
|  | 	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) | ||||||
|  | { | ||||||
|  | 	FtpSendCommand("QUIT\r\n"); | ||||||
|  | 	SocketClose(m_socket_cmd); | ||||||
|  | } | ||||||
|  |   | ||||||
|  | void FtpInitCmd(void) | ||||||
|  | { | ||||||
|  | 	m_socket_cmd = SocketCreate(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FtpInitData(void){ | ||||||
|  |     m_socket_data= SocketCreate(); | ||||||
|  | } | ||||||
|  | @ -0,0 +1,42 @@ | ||||||
|  | /*
 | ||||||
|  | * Copyright (c) 2020 AIIT XUOS Lab | ||||||
|  | * 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:   ftp client tool | ||||||
|  | * @version: 1.0 | ||||||
|  | * @author:  bdislab_final | ||||||
|  | * @date:    2023/7/25 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #ifndef FTP_CLIENT_H | ||||||
|  | #define FTP_CLIENT_H | ||||||
|  | 
 | ||||||
|  | /* init ftp cmd socket */  | ||||||
|  | void FtpInitCmd(void); | ||||||
|  | 
 | ||||||
|  | /* init ftp data socket */ | ||||||
|  | void FtpInitData(void); | ||||||
|  | 
 | ||||||
|  | /* quit ftp */ | ||||||
|  | void FtpQuit(void); | ||||||
|  | 
 | ||||||
|  | /* fpt login */ | ||||||
|  | int  FtpLogin(char *addr, int port, char *username, char *password); | ||||||
|  | 
 | ||||||
|  | /* get file size */ | ||||||
|  | int  FtpFileSize(char *name); | ||||||
|  | 
 | ||||||
|  | /* ftp download file*/ | ||||||
|  | int  FtpDownload(char *name, char *buf, int len); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | @ -0,0 +1,57 @@ | ||||||
|  | /*
 | ||||||
|  | * Copyright (c) 2020 AIIT XUOS Lab | ||||||
|  | * 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:    my_socket.c | ||||||
|  | * @brief:   a abstract socket api | ||||||
|  | * @version: 1.0 | ||||||
|  | * @author:  bdislab_final | ||||||
|  | * @date:    2023/7/25 | ||||||
|  | * @reference https://kerndev.blog.csdn.net/article/details/89383888
 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #include "my_socket.h" | ||||||
|  | #include <sockets.h> | ||||||
|  | #include <def.h> | ||||||
|  | #include <errno.h> | ||||||
|  | 
 | ||||||
|  | int  SocketCreate(void){ | ||||||
|  |     return socket(AF_INET,SOCK_STREAM,0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int  SocketConnect(int sock, const char *addr, int port){ | ||||||
|  | 	// unsigned int iRemoteAddr = 0;
 | ||||||
|  | 	struct sockaddr_in stRemoteAddr = {0}; //对端,即目标地址信息
 | ||||||
|  | 	 | ||||||
|  | 	stRemoteAddr.sin_family = AF_INET; | ||||||
|  | 	stRemoteAddr.sin_port = htons(port); | ||||||
|  | 	stRemoteAddr.sin_addr.s_addr = inet_addr(addr); | ||||||
|  | 	// inet_pton(AF_INET, addr, &iRemoteAddr);
 | ||||||
|  | 	// stRemoteAddr.sin_addr.s_addr=iRemoteAddr;
 | ||||||
|  | 	int res = connect(sock,(struct sockaddr *)&stRemoteAddr,sizeof(stRemoteAddr)); | ||||||
|  | 	if(res == -1){ | ||||||
|  | 		printf("error:%d\n",errno); | ||||||
|  | 	} | ||||||
|  |     return res == 0 ? 1 : 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int  SocketSend(int sock, void *data, int len){ | ||||||
|  |     return send(sock,data,len,0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int  SocketRecv(int sock, void *data, int len){ | ||||||
|  |     return recv(sock,data,len,0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void SocketClose(int sock){ | ||||||
|  | 	close(sock); | ||||||
|  | } | ||||||
|  | @ -0,0 +1,46 @@ | ||||||
|  | /*
 | ||||||
|  | * Copyright (c) 2020 AIIT XUOS Lab | ||||||
|  | * 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 my_socket.h | ||||||
|  |  * @brief a abstract socket api | ||||||
|  |  * @version 1.0 | ||||||
|  |  * @author bdislab_final | ||||||
|  |  * @date 2023/7/25 | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef MYSOCKET_H | ||||||
|  | #define MYSOCKET_H | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | /* create a socket */ | ||||||
|  | int  SocketCreate(void); | ||||||
|  | 
 | ||||||
|  | /* connect a socket */ | ||||||
|  | int  SocketConnect(int sock, const char *addr, int port); | ||||||
|  | 
 | ||||||
|  | /* send data through socket*/ | ||||||
|  | int  SocketSend(int sock, void *data, int len); | ||||||
|  | 
 | ||||||
|  | /* receive data from socket*/ | ||||||
|  | int  SocketRecv(int sock, void *data, int len); | ||||||
|  | 
 | ||||||
|  | /* close socket*/ | ||||||
|  | void SocketClose(int sock); | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
| After Width: | Height: | Size: 214 KiB | 
| After Width: | Height: | Size: 121 KiB | 
| After Width: | Height: | Size: 108 KiB | 
| After Width: | Height: | Size: 117 KiB | 
| After Width: | Height: | Size: 38 KiB | 
| After Width: | Height: | Size: 50 KiB | 
| After Width: | Height: | Size: 73 KiB | 
| After Width: | Height: | Size: 48 KiB | 
| After Width: | Height: | Size: 136 KiB | 
|  | @ -0,0 +1,50 @@ | ||||||
|  | /*
 | ||||||
|  | * Copyright (c) 2020 AIIT XUOS Lab | ||||||
|  | * 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 ftpClient test sample | ||||||
|  | * @version: 1.0 | ||||||
|  | * @author:  bdislab_final | ||||||
|  | * @date:    2023/7/25 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #include "test_ftpclient.h" | ||||||
|  | #include "ftp_client/ftp_client.h" | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <transform.h> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* test for ftp client */ | ||||||
|  | void TestFtpClient(int argc, char* argv[]) | ||||||
|  | { | ||||||
|  |     FtpInitCmd(); | ||||||
|  |     int ret = FtpLogin("192.168.1.248", 21, "anonymous", "anonymous"); | ||||||
|  |     int size; | ||||||
|  |     char *buf; | ||||||
|  |     for(int i = 1;i <= 10;i++){ | ||||||
|  |         char fileName[20] = "/file";  | ||||||
|  |         char temp[5] = ""; | ||||||
|  |         sprintf(temp,"%d",i-1); | ||||||
|  |         strcat(fileName,temp); | ||||||
|  |         size = FtpFileSize(fileName); | ||||||
|  |         buf = malloc(size); | ||||||
|  |         FtpInitData();  // data socket 每次下载都要重新创建,下载完都要关闭
 | ||||||
|  |         ret = FtpDownload(fileName, buf, size); | ||||||
|  |         free(buf); | ||||||
|  |     } | ||||||
|  |     FtpQuit(); | ||||||
|  |     return; | ||||||
|  | } | ||||||
|  | PRIV_SHELL_CMD_FUNCTION(TestFtpClient, a ftpClient test sample, PRIV_SHELL_CMD_MAIN_ATTR); | ||||||
|  | @ -0,0 +1,35 @@ | ||||||
|  | /*
 | ||||||
|  | * Copyright (c) 2020 AIIT XUOS Lab | ||||||
|  | * 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 a ftpClient test sample | ||||||
|  |  * @version 1.0 | ||||||
|  |  * @author bdislab_final | ||||||
|  |  * @date 2023/7/25 | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef TEST_FTPCLIENT_H | ||||||
|  | #define TEST_FTPCLIENT_H | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | /* test for ftp client */ | ||||||
|  | void TestFtpClient(int argc, char* argv[]); | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | @ -0,0 +1,135 @@ | ||||||
|  | # 决赛一级赛题3:基于初赛一级赛题3,在云服务器上实现FTP Server功能 | ||||||
|  | 
 | ||||||
|  | ## 1. 简介 | ||||||
|  | 本项目是基于赛事提供的云服务器,实现FTP协议的Server功能,其功能支持至少10个Client端并发向Server端传输4KB大小的文件, | ||||||
|  | 支持Server端并发地向至少10个Client端传输4KB大小的文件。 | ||||||
|  | test_ftpclient_final.h声明了多个客户端并发下载文件、并发上传文件的测试函数 | ||||||
|  | test_ftpclient_final.c实现了多个客户端并发下载文件、并发上传文件的测试函数 | ||||||
|  | ftp_client文件夹定义了ftp_client的相关类库其中my_socket.h,my_socket.c定义了socket抽象层,并基于 | ||||||
|  | Lwip实现了该抽象层,ftp_client.h,ftp_client.c实现了ftp登录,获取文件大小,下载文件等功能 | ||||||
|  | 注意:在赛事提供的云服务器/root/yanglongFTP上有对应服务器代码 ./server运行服务器,为了方便查看代码我们讲服务器代码备份存放在ftp_server目录下 | ||||||
|  | ## 2. 数据结构设计说明 | ||||||
|  | - ftp_client.c 的设计 | ||||||
|  | 分别定义了发送命令和接收数据的socket和相应的缓冲区并且实现了登录、发送命令、接收响应数据、查找文件大小、进入被动模式、下载文件、关闭ftp客户端等操作 | ||||||
|  | ```c | ||||||
|  | static int  m_socket_cmd[THREAD_NUM]; // 发送命令的socket文件描述符,THREAD_NUM表示线程数目,用来模拟多个客户端并发访问 | ||||||
|  | static int  m_socket_data[THREAD_NUM]; // 接收ftp服务器文件的socket文件描述符 | ||||||
|  | static char m_send_buffer[THREAD_NUM][1024]; // 发送缓冲区 | ||||||
|  | static char m_recv_buffer[THREAD_NUM][1024]; // 接收缓冲区 | ||||||
|  | ``` | ||||||
|  | - server.c 的设计(具体代码在赛事提供的云服务器的/root/yanglongFTP下) | ||||||
|  | ```c | ||||||
|  | #define THREAD_NUM 10000 // thread num | ||||||
|  | static int isBinary = 0; // transmit binary data | ||||||
|  | static int port = 9992; // service port | ||||||
|  | static int dataPort = 9993; // the port for file download | ||||||
|  | static char order[4]; // receive order | ||||||
|  | static char param[20]; // receive order param | ||||||
|  | static char *respMessage; // respose message | ||||||
|  | static int serverFd;  // the server fd for deal with order requests | ||||||
|  | static int dataServerFd; // the server fd for file download | ||||||
|  | sem_t mutex; // mutex lock | ||||||
|  | struct Data{ // 线程间通信传输的数据 | ||||||
|  |     char fileName[20]; // file name | ||||||
|  |     int type; // 0:download 1:upload | ||||||
|  |     sem_t isDone;  // complete file downlaod | ||||||
|  |     sem_t isReady;  // 文件准备好了 | ||||||
|  | } data; | ||||||
|  | ``` | ||||||
|  | ## 3. 测试程序说明 | ||||||
|  | - test_ftpclient_final.c用于测试多个客户端并发下载文件 | ||||||
|  | 通过多线程模拟多个客户端并发访问服务器,通过 TestFtpClient options threads进行测试 | ||||||
|  | 其中options=1表示下载options=2表示上传,threads表示线程数/模拟的并发客户端数目 | ||||||
|  | ```c | ||||||
|  | /* test for 10 ftp client */ | ||||||
|  | void TestFtpClient(int argc, char* argv[]) | ||||||
|  | { | ||||||
|  |     int options = atoi(argv[1]); | ||||||
|  |     int n = atoi(argv[2]); | ||||||
|  |     pthread_t threads[THREAD_NUM]; | ||||||
|  |     for(int i = 0;i < n;++i){ | ||||||
|  |         threadIDs[i] = i; | ||||||
|  |         if(options == 1){ // 全部都是下载 | ||||||
|  |             pthread_create(&threads[i],NULL,&DownLoad,&threadIDs[i]); | ||||||
|  |         }else if(options == 2){ // 全部都是上传 | ||||||
|  |             pthread_create(&threads[i],NULL,&UpLoad,&threadIDs[i]); | ||||||
|  |         }else if(options == 3){  // 随机下载/上传 | ||||||
|  |             int r = rand()%2; | ||||||
|  |             if(r == 0){ | ||||||
|  |                 printf("===============download===============\n"); | ||||||
|  |                 pthread_create(&threads[i],NULL,&DownLoad,&threadIDs[i]); | ||||||
|  |             }else{ | ||||||
|  |                 printf("===============upload===============\n"); | ||||||
|  |                 pthread_create(&threads[i],NULL,&UpLoad,&threadIDs[i]); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return; | ||||||
|  | } | ||||||
|  | PRIV_SHELL_CMD_FUNCTION(TestFtpClient, a ftpClient test sample, PRIV_SHELL_CMD_MAIN_ATTR); | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ## 4. 运行结果(##需结合运行测试截图按步骤说明##) | ||||||
|  | 1. 配置开启BSP_USING_LWIP、USER_TEST_FTPCLIENT | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 2. 编译 | ||||||
|  |  | ||||||
|  | 3. 烧写 | ||||||
|  |  | ||||||
|  | 4. xshell连接串口终端并配置ip | ||||||
|  |  | ||||||
|  | 5. 通过./server在云服务器运行FTP服务器 | ||||||
|  |  | ||||||
|  | 6. 运行TestFtpClient 1 10,模拟10个客户端并发下载文件 | ||||||
|  | - 客户端日志 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | - 服务器日志 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 7. 运行TestFtpClient 2 10,模拟10个客户端并发上传文件 | ||||||
|  | - 客户端日志 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | - 服务器日志 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | - 上传结果 | ||||||
|  |  | ||||||
|  | 8. 运行TestFtpClient 3 10,模拟10个客户端混合并发下载和上传文件 | ||||||
|  | - 客户端日志 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 
 | ||||||
|  | - 服务器日志 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 
 | ||||||
|  | - 下载和上传结果 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @ -0,0 +1,299 @@ | ||||||
|  | /*
 | ||||||
|  | * Copyright (c) 2020 AIIT XUOS Lab | ||||||
|  | * 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.c | ||||||
|  | * @brief:   ftp client tool | ||||||
|  | * @version: 1.0 | ||||||
|  | * @author:  bdislab_final | ||||||
|  | * @date:    2023/9/16 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | #include "my_socket.h" | ||||||
|  | #include "ftp_client.h" | ||||||
|  |   | ||||||
|  | 
 | ||||||
|  | static int  m_socket_cmd[THREAD_NUM]; | ||||||
|  | static int  m_socket_data[THREAD_NUM]; | ||||||
|  | static char m_send_buffer[THREAD_NUM][1024]; | ||||||
|  | static char m_recv_buffer[THREAD_NUM][1024]; | ||||||
|  |   | ||||||
|  | static int FtpSendCommand(int threadID,char *cmd) | ||||||
|  | { | ||||||
|  | 	int ret; | ||||||
|  | 	printf("send command: %s,threadID=%d\r\n", cmd,threadID); | ||||||
|  | 	ret = SocketSend(m_socket_cmd[threadID], cmd, (int)strlen(cmd)); | ||||||
|  | 	if(ret < 0) | ||||||
|  | 	{ | ||||||
|  | 		printf("failed to send command: %s\r\n",cmd); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  |   | ||||||
|  | static int FtpRecvRespond(int threadID,char *resp, int len) | ||||||
|  | { | ||||||
|  | 	int ret; | ||||||
|  | 	int off; | ||||||
|  | 	len -= 1; | ||||||
|  | 	for(off=0; off<len; off+=ret) | ||||||
|  | 	{ | ||||||
|  | 		ret = SocketRecv(m_socket_cmd[threadID], &resp[off], 1); | ||||||
|  | 		if(ret < 0) | ||||||
|  | 		{ | ||||||
|  | 			printf("recv respond error(ret=%d)!\r\n", ret); | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 		if(resp[off] == '\n') | ||||||
|  | 		{ | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	resp[off+1] = 0; | ||||||
|  | 	printf("respond:%s,threadID=%d\r\n", resp,threadID); | ||||||
|  | 	return atoi(resp); | ||||||
|  | } | ||||||
|  |   | ||||||
|  | static int FtpEnterPasv(int threadID,char *ipaddr, int *port) | ||||||
|  | { | ||||||
|  | 	int ret; | ||||||
|  | 	char *find; | ||||||
|  | 	int a,b,c,d; | ||||||
|  | 	int pa,pb; | ||||||
|  | 	ret = FtpSendCommand(threadID,"PASV\r\n"); | ||||||
|  | 	if(ret != 1) | ||||||
|  | 	{ | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	ret = FtpRecvRespond(threadID,m_recv_buffer[threadID], 1024); | ||||||
|  | 	if(ret != 227) | ||||||
|  | 	{ | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	find = strrchr(m_recv_buffer[threadID], '('); | ||||||
|  | 	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(int threadID,char *name, void *buf, int len) | ||||||
|  | { | ||||||
|  | 	int  ret; | ||||||
|  | 	char ipaddr[32]; | ||||||
|  | 	int  port; | ||||||
|  | 	 | ||||||
|  | 	//查询数据地址
 | ||||||
|  | 	ret=FtpEnterPasv(threadID,ipaddr, &port); | ||||||
|  | 	if(ret != 1) | ||||||
|  | 	{ | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	ret=SocketConnect(m_socket_data[threadID], ipaddr, port); | ||||||
|  | 	if(ret != 1) | ||||||
|  | 	{ | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	//准备上传
 | ||||||
|  | 	sprintf(m_send_buffer[threadID], "STOR %s\r\n", name); | ||||||
|  | 	ret = FtpSendCommand(threadID,m_send_buffer[threadID]); | ||||||
|  | 	if(ret != 1) | ||||||
|  | 	{ | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	ret = FtpRecvRespond(threadID,m_recv_buffer[threadID], 1024); | ||||||
|  | 	if(ret != 150) | ||||||
|  | 	{ | ||||||
|  | 		SocketClose(m_socket_data[threadID]); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	//开始上传
 | ||||||
|  | 	ret = SocketSend(m_socket_data[threadID], buf, len); | ||||||
|  | 	if(ret != len) | ||||||
|  | 	{	 | ||||||
|  | 		printf("send data error!\r\n"); | ||||||
|  | 		SocketClose(m_socket_data[threadID]); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	SocketClose(m_socket_data[threadID]); | ||||||
|  |   | ||||||
|  | 	//上传完成,等待回应
 | ||||||
|  | 	ret = FtpRecvRespond(threadID,m_recv_buffer[threadID], 1024); | ||||||
|  | 	return (ret==226); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int  FtpDownload(int threadID,char *name, void *buf, int len) | ||||||
|  | { | ||||||
|  | 	int   i; | ||||||
|  | 	int   ret; | ||||||
|  | 	char  ipaddr[32]; | ||||||
|  | 	int   port; | ||||||
|  |      | ||||||
|  | 	//查询数据地址
 | ||||||
|  | 	ret = FtpEnterPasv(threadID,ipaddr, &port); | ||||||
|  | 	if(ret != 1) | ||||||
|  | 	{ | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	printf("m_socket_data[threadID]=%d,threadID=%d\n",m_socket_data[threadID],threadID); | ||||||
|  | 	//连接数据端口
 | ||||||
|  | 	ret = SocketConnect(m_socket_data[threadID], ipaddr, port); | ||||||
|  | 	if(ret != 1) | ||||||
|  | 	{ | ||||||
|  | 		printf("failed to connect data port\r\n"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |   | ||||||
|  | 	//准备下载
 | ||||||
|  | 	sprintf(m_send_buffer[threadID], "RETR %s\r\n", name); | ||||||
|  | 	ret = FtpSendCommand(threadID,m_send_buffer[threadID]); | ||||||
|  | 	if(ret != 1) | ||||||
|  | 	{ | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	ret = FtpRecvRespond(threadID,m_recv_buffer[threadID], 1024); | ||||||
|  | 	if(ret != 150) | ||||||
|  | 	{ | ||||||
|  | 		SocketClose(m_socket_data[threadID]); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	//开始下载,读取完数据后,服务器会自动关闭连接
 | ||||||
|  | 	for(i=0; i<len; i+=ret) | ||||||
|  | 	{ | ||||||
|  | 		ret = SocketRecv(m_socket_data[threadID], ((char *)buf) + i, len); | ||||||
|  | 		printf("download %d/%d.,threadID=%d\r\n", i + ret, len,threadID); | ||||||
|  | 		if(ret < 0) | ||||||
|  | 		{ | ||||||
|  | 			printf("download was interrupted.\r\n"); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	//下载完成
 | ||||||
|  | 	printf("download %d/%d bytes complete.,threadID=%d\r\n", i, len,threadID); | ||||||
|  |     // FILE *fp = NULL;
 | ||||||
|  | 
 | ||||||
|  |     // fp = fopen(name+1, "wb");
 | ||||||
|  |     // fwrite(buf,len,1,fp);
 | ||||||
|  |     // fclose(fp);
 | ||||||
|  | 
 | ||||||
|  | 	SocketClose(m_socket_data[threadID]); | ||||||
|  | 	ret = FtpRecvRespond(threadID,m_recv_buffer[threadID], 1024); | ||||||
|  | 	return (ret==226); | ||||||
|  | } | ||||||
|  |   | ||||||
|  | int  FtpFileSize(int threadID,char *name) | ||||||
|  | { | ||||||
|  | 	int ret; | ||||||
|  | 	int size; | ||||||
|  | 	sprintf(m_send_buffer[threadID],"SIZE %s\r\n",name); | ||||||
|  | 	ret = FtpSendCommand(threadID,m_send_buffer[threadID]); | ||||||
|  | 	if(ret != 1) | ||||||
|  | 	{ | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	ret = FtpRecvRespond(threadID,m_recv_buffer[threadID], 1024); | ||||||
|  | 	if(ret != 213) | ||||||
|  | 	{ | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	size = atoi(m_recv_buffer[threadID] + 4); | ||||||
|  | 	return size; | ||||||
|  | } | ||||||
|  |   | ||||||
|  | int FtpLogin(int threadID,char *addr, int port, char *username, char *password) | ||||||
|  | { | ||||||
|  | 	int ret; | ||||||
|  | 	printf("connect...,threadID=%d\r\n",threadID); | ||||||
|  | 	ret = SocketConnect(m_socket_cmd[threadID], addr, port); | ||||||
|  | 	if(ret != 1) | ||||||
|  | 	{ | ||||||
|  | 		printf("connect server failed!\r\n"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	printf("connect ok.,threadID=%d\r\n",threadID); | ||||||
|  |     //等待欢迎信息
 | ||||||
|  | 	ret = FtpRecvRespond(threadID,m_recv_buffer[threadID], 1024); | ||||||
|  | 	if(ret != 220) | ||||||
|  | 	{ | ||||||
|  | 		printf("bad server, ret=%d!\r\n", ret); | ||||||
|  | 		SocketClose(m_socket_cmd[threadID]); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	printf("login...threadID=%d\r\n",threadID); | ||||||
|  |     //发送USER
 | ||||||
|  | 	sprintf(m_send_buffer[threadID], "USER %s\r\n", username); | ||||||
|  | 	ret = FtpSendCommand(threadID,m_send_buffer[threadID]); | ||||||
|  | 	if(ret != 1) | ||||||
|  | 	{ | ||||||
|  | 		SocketClose(m_socket_cmd[threadID]); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	ret = FtpRecvRespond(threadID,m_recv_buffer[threadID], 1024); | ||||||
|  | 	if(ret != 331) | ||||||
|  | 	{ | ||||||
|  | 		SocketClose(m_socket_cmd[threadID]); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  |     //发送PASS
 | ||||||
|  | 	sprintf(m_send_buffer[threadID], "PASS %s\r\n", password); | ||||||
|  | 	ret = FtpSendCommand(threadID,m_send_buffer[threadID]); | ||||||
|  | 	if(ret != 1) | ||||||
|  | 	{ | ||||||
|  | 		SocketClose(m_socket_cmd[threadID]); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	ret = FtpRecvRespond(threadID,m_recv_buffer[threadID], 1024); | ||||||
|  | 	if(ret != 230) | ||||||
|  | 	{ | ||||||
|  | 		SocketClose(m_socket_cmd[threadID]); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	printf("login success.threadID=%d\r\n",threadID); | ||||||
|  | 	 | ||||||
|  |     //设置为二进制模式
 | ||||||
|  | 	ret = FtpSendCommand(threadID,"TYPE I\r\n"); | ||||||
|  | 	if(ret != 1) | ||||||
|  | 	{ | ||||||
|  | 		SocketClose(m_socket_cmd[threadID]); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	ret = FtpRecvRespond(threadID,m_recv_buffer[threadID], 1024); | ||||||
|  | 	if(ret != 200) | ||||||
|  | 	{ | ||||||
|  | 		SocketClose(m_socket_cmd[threadID]); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  |   | ||||||
|  | void FtpQuit(int threadID) | ||||||
|  | { | ||||||
|  | 	FtpSendCommand(threadID,"QUIT\r\n"); | ||||||
|  | 	SocketClose(m_socket_cmd[threadID]); | ||||||
|  | } | ||||||
|  |   | ||||||
|  | void FtpInitCmd(int threadID) | ||||||
|  | { | ||||||
|  | 	m_socket_cmd[threadID] = SocketCreate(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void FtpInitData(int threadID){ | ||||||
|  |     m_socket_data[threadID]= SocketCreate(); | ||||||
|  | } | ||||||
|  | @ -0,0 +1,46 @@ | ||||||
|  | /*
 | ||||||
|  | * Copyright (c) 2020 AIIT XUOS Lab | ||||||
|  | * 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:   ftp client tool | ||||||
|  | * @version: 1.0 | ||||||
|  | * @author:  bdislab_final | ||||||
|  | * @date:    2023/9/16 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #ifndef FTP_CLIENT_H | ||||||
|  | #define FTP_CLIENT_H | ||||||
|  | 
 | ||||||
|  | #define THREAD_NUM 10 | ||||||
|  | 
 | ||||||
|  | /* init ftp cmd socket */  | ||||||
|  | void FtpInitCmd(int threadID); | ||||||
|  | 
 | ||||||
|  | /* init ftp data socket */ | ||||||
|  | void FtpInitData(int threadID); | ||||||
|  | 
 | ||||||
|  | /* quit ftp */ | ||||||
|  | void FtpQuit(int threadID); | ||||||
|  | 
 | ||||||
|  | /* fpt login */ | ||||||
|  | int  FtpLogin(int threadID,char *addr, int port, char *username, char *password); | ||||||
|  | 
 | ||||||
|  | /* get file size */ | ||||||
|  | int  FtpFileSize(int threadID,char *name); | ||||||
|  | 
 | ||||||
|  | /* ftp download file*/ | ||||||
|  | int  FtpDownload(int threadID,char *name, void *buf, int len); | ||||||
|  | 
 | ||||||
|  | /*ftp upload*/ | ||||||
|  | int  FtpUpload(int threadID,char *name, void *buf, int len); | ||||||
|  | #endif | ||||||
|  | @ -0,0 +1,55 @@ | ||||||
|  | /*
 | ||||||
|  | * Copyright (c) 2020 AIIT XUOS Lab | ||||||
|  | * 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:    my_socket.c | ||||||
|  | * @brief:   a abstract socket api | ||||||
|  | * @version: 1.0 | ||||||
|  | * @author:  bdislab_final | ||||||
|  | * @date:    2023/9/16 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #include "my_socket.h" | ||||||
|  | #include <sockets.h> | ||||||
|  | #include <def.h> | ||||||
|  | #include <errno.h> | ||||||
|  | #include <string.h> | ||||||
|  | 
 | ||||||
|  | int  SocketCreate(void){ | ||||||
|  |     return socket(AF_INET,SOCK_STREAM,0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int  SocketConnect(int sock, const char *addr, int port){ | ||||||
|  | 	// unsigned int iRemoteAddr = 0;
 | ||||||
|  | 	struct sockaddr_in stRemoteAddr = {0}; //对端,即目标地址信息
 | ||||||
|  | 	 | ||||||
|  | 	stRemoteAddr.sin_family = AF_INET; | ||||||
|  | 	stRemoteAddr.sin_port = htons(port); | ||||||
|  | 	stRemoteAddr.sin_addr.s_addr = inet_addr(addr); | ||||||
|  | 	int res = connect(sock,(struct sockaddr *)&stRemoteAddr,sizeof(stRemoteAddr)); | ||||||
|  | 	if(res == -1){ | ||||||
|  | 		printf("error:%d,str error:%s\n",errno,strerror(errno)); | ||||||
|  | 	} | ||||||
|  |     return res == 0 ? 1 : 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int  SocketSend(int sock, void *data, int len){ | ||||||
|  |     return send(sock,data,len,0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int  SocketRecv(int sock, void *data, int len){ | ||||||
|  |     return recv(sock,data,len,0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void SocketClose(int sock){ | ||||||
|  | 	close(sock); | ||||||
|  | } | ||||||
|  | @ -0,0 +1,46 @@ | ||||||
|  | /*
 | ||||||
|  | * Copyright (c) 2020 AIIT XUOS Lab | ||||||
|  | * 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 my_socket.h | ||||||
|  |  * @brief a abstract socket api | ||||||
|  |  * @version 1.0 | ||||||
|  |  * @author bdislab_final | ||||||
|  |  * @date 2023/9/16 | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef MYSOCKET_H | ||||||
|  | #define MYSOCKET_H | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | /* create a socket */ | ||||||
|  | int  SocketCreate(void); | ||||||
|  | 
 | ||||||
|  | /* connect a socket */ | ||||||
|  | int  SocketConnect(int sock, const char *addr, int port); | ||||||
|  | 
 | ||||||
|  | /* send data through socket*/ | ||||||
|  | int  SocketSend(int sock, void *data, int len); | ||||||
|  | 
 | ||||||
|  | /* receive data from socket*/ | ||||||
|  | int  SocketRecv(int sock, void *data, int len); | ||||||
|  | 
 | ||||||
|  | /* close socket*/ | ||||||
|  | void SocketClose(int sock); | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | @ -0,0 +1,5 @@ | ||||||
|  | #!/bin/bash | ||||||
|  | for i in {1..10} | ||||||
|  | do | ||||||
|  | 	dd if=/dev/zero of="file$i" bs=4K count=1 | ||||||
|  | done | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 | ||||||
|  | @ -0,0 +1,251 @@ | ||||||
|  | /*
 | ||||||
|  | * Copyright (c) 2020 AIIT XUOS Lab | ||||||
|  | * 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:    server.c | ||||||
|  | * @brief:   a ftpserver | ||||||
|  | * @version: 1.0 | ||||||
|  | * @author:  bdislab_final | ||||||
|  | * @date:    2023/10/11 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <sys/socket.h> | ||||||
|  | #include <netinet/in.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | #include <pthread.h> | ||||||
|  | #include <semaphore.h> | ||||||
|  | #include <errno.h> | ||||||
|  | 
 | ||||||
|  | #define THREAD_NUM 10000 // thread num
 | ||||||
|  | static int isBinary = 0; // transmit binary data
 | ||||||
|  | static int port = 9992; // service port
 | ||||||
|  | static int dataPort = 9993; // the port for file download
 | ||||||
|  | static char order[4]; // receive order
 | ||||||
|  | static char param[20]; // receive order param
 | ||||||
|  | static char *respMessage; // respose message
 | ||||||
|  | static int serverFd;  // the server fd for deal with order requests
 | ||||||
|  | static int dataServerFd; // the server fd for file download
 | ||||||
|  | sem_t mutex; // mutex lock
 | ||||||
|  | struct Data{ // 线程间通信传输的数据
 | ||||||
|  |     char fileName[20]; // file name
 | ||||||
|  |     int type; // 0:download 1:upload
 | ||||||
|  |     sem_t isDone;  // complete file downlaod
 | ||||||
|  |     sem_t isReady;  // 文件准备好了
 | ||||||
|  | } data; | ||||||
|  | 
 | ||||||
|  | void RecvData(int clientFd,char param[20]){ | ||||||
|  |     recv(clientFd,param,20,0); | ||||||
|  |     for(int i = 0;i < 20;++i){ | ||||||
|  |         if(param[i] == '\r'){ | ||||||
|  |             param[i] = '\0'; | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void SendMessage(int clientFd, char * respMessage){ | ||||||
|  |     int len = 0; | ||||||
|  |     while(respMessage[len] != '\n'){ | ||||||
|  |         len++; | ||||||
|  |     } | ||||||
|  |     send(clientFd,respMessage,len+1,0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int CreateServer(int port,int type) { | ||||||
|  |     int serverFd = 0; | ||||||
|  | 	struct sockaddr_in serverAddr = {0}; | ||||||
|  | 	socklen_t socklen = 0; | ||||||
|  | 	serverFd = socket(AF_INET, SOCK_STREAM, 0); | ||||||
|  | 	if(0 > serverFd) | ||||||
|  | 	{ | ||||||
|  | 		printf("创建socket失败\n"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  |     if(type == 0){ | ||||||
|  |         printf("in ftp server:serverFd=%d\n",serverFd); | ||||||
|  |     }else{ | ||||||
|  |         printf("in ftp data server:serverFd=%d\n",serverFd); | ||||||
|  |     }	 | ||||||
|  | 	serverAddr.sin_family = AF_INET; | ||||||
|  | 	serverAddr.sin_port = htons(port); | ||||||
|  | 	serverAddr.sin_addr.s_addr=htonl(INADDR_ANY); | ||||||
|  | 	if(0 > bind(serverFd, (void *)&serverAddr, sizeof(serverAddr))) | ||||||
|  | 	{ | ||||||
|  | 		printf("绑定失败!\n"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	if(0 > listen(serverFd, 1024)) | ||||||
|  | 	{ | ||||||
|  | 		printf("监听失败!\n"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |     return serverFd; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // receive file's data
 | ||||||
|  | void* UpLoadServer(void * args){  | ||||||
|  |     int clientFd = *(int *) args; | ||||||
|  |     char buf[4096]; | ||||||
|  |     int ret = recv(clientFd,buf,4096,0); | ||||||
|  |     printf("ret=%d,errno=%d\n",ret,errno); | ||||||
|  |     FILE * file = fopen(data.fileName,"wb"); | ||||||
|  |     fwrite(buf,4096,1,file); | ||||||
|  |     fclose(file); | ||||||
|  |     printf("upload complete for client: clientFd=%d,tid=%ld\n",clientFd,pthread_self()); | ||||||
|  |     // notify for file download complete
 | ||||||
|  |     sem_post(&data.isDone); | ||||||
|  |     close(clientFd); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | //  send file's data
 | ||||||
|  | void* DownLoadServer(void * args){  | ||||||
|  |     int clientFd = *(int *) args; | ||||||
|  |     char buf[4096]; | ||||||
|  |     FILE * file = fopen(data.fileName,"rb"); | ||||||
|  |     fread(buf,4096,1,file); | ||||||
|  |     send(clientFd,buf,sizeof(buf),0); | ||||||
|  |     fclose(file); | ||||||
|  |     printf("download complete for client: clientFd=%d,tid=%ld\n",clientFd,pthread_self()); | ||||||
|  |     // notify for file download complete
 | ||||||
|  |     sem_post(&data.isDone); | ||||||
|  |     close(clientFd); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // accept a client and new a thread for downlaod/upload
 | ||||||
|  | void* DataServer(void * args){ | ||||||
|  |     dataServerFd = CreateServer(dataPort,1); | ||||||
|  |     while(1){ | ||||||
|  |         // wait for a filename
 | ||||||
|  |         sem_wait(&data.isReady); | ||||||
|  |         struct sockaddr_in clientAdrr = {0}; | ||||||
|  |         int socketLen = sizeof(clientAdrr); | ||||||
|  |         int clientFd = accept(dataServerFd,(struct sockaddr *)&clientAdrr,&socketLen); | ||||||
|  |         pthread_t thread; | ||||||
|  |         if(data.type == 0){ // download
 | ||||||
|  |             printf("accept a client for file download: clientFd=%d,tid=%ld\n",clientFd,pthread_self()); | ||||||
|  |             pthread_create(&thread,NULL,&DownLoadServer,&clientFd); | ||||||
|  |         }else if(data.type == 1){ // upload
 | ||||||
|  |             printf("accept a client for file upload: clientFd=%d,tid=%ld\n",clientFd,pthread_self()); | ||||||
|  |             pthread_create(&thread,NULL,&UpLoadServer,&clientFd); | ||||||
|  |         } | ||||||
|  |         // release lock
 | ||||||
|  |         sem_post(&mutex); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // deal with order requests
 | ||||||
|  | void* OrderServer(void * args){ | ||||||
|  |     int clientFd = *(int *)args; | ||||||
|  |     printf("in OrderServer thread: tid=%ld\n",pthread_self()); | ||||||
|  |     // order format: USER anonymous\r\n
 | ||||||
|  |     // response code format: 213 4096\r\n
 | ||||||
|  |     while(1){ | ||||||
|  |         recv(clientFd,order,4,0); | ||||||
|  |         printf("order=%s,tid=%ld\n",order,pthread_self()); | ||||||
|  |         if(strcmp(order,"USER") == 0){ | ||||||
|  |             RecvData(clientFd,param); | ||||||
|  |             if(strcmp(param," anonymous") == 0){ | ||||||
|  |                 respMessage = "331 Please specify the password.\r\n"; | ||||||
|  |                 SendMessage(clientFd,respMessage); | ||||||
|  |             } | ||||||
|  |         }else if(strcmp(order,"PASS") == 0){ | ||||||
|  |             RecvData(clientFd,param); | ||||||
|  |             if(strcmp(param," anonymous") == 0){ | ||||||
|  |                 respMessage = "230 Login successful.\r\n"; | ||||||
|  |                 SendMessage(clientFd,respMessage); | ||||||
|  |                 printf("login successful in clientFd %d,tid=%ld\n",clientFd,pthread_self()); | ||||||
|  |             } | ||||||
|  |         }else if(strcmp(order,"TYPE") == 0){ | ||||||
|  |             RecvData(clientFd,param); | ||||||
|  |             if(strcmp(param," I") == 0){ | ||||||
|  |                 isBinary = 1; | ||||||
|  |                 respMessage = "200 Switching to Binary mode.\r\n"; | ||||||
|  |                 SendMessage(clientFd,respMessage); | ||||||
|  |             } | ||||||
|  |         }else if(strcmp(order,"SIZE") == 0){ | ||||||
|  |             RecvData(clientFd,param); | ||||||
|  |             respMessage = "213 4096\r\n"; | ||||||
|  |             SendMessage(clientFd,respMessage); | ||||||
|  |         }else if(strcmp(order,"PASV") == 0){ | ||||||
|  |             sem_wait(&mutex); // 锁竞争
 | ||||||
|  |             sem_init(&data.isDone,0,0); | ||||||
|  |             RecvData(clientFd,param); | ||||||
|  |             char buf[50]; | ||||||
|  |             sprintf(buf,"227 Entering passive mode (8,140,53,225,%d,%d).\r\n",dataPort/256,dataPort%256); | ||||||
|  |             respMessage = buf; | ||||||
|  |             SendMessage(clientFd,respMessage); | ||||||
|  |         }else if(strcmp(order,"RETR") == 0){ | ||||||
|  |             RecvData(clientFd,param); | ||||||
|  |             sprintf(data.fileName,"./data/%s",param+2); | ||||||
|  |             data.type = 0; | ||||||
|  |             // notify the thread of waiting fileName
 | ||||||
|  |             sem_post(&data.isReady); | ||||||
|  |             char buf[70]; | ||||||
|  |             sprintf(buf,"150 Opening Binary mode data connection for %s (4096 bytes).\r\n",param+1); | ||||||
|  |             respMessage = buf; | ||||||
|  |             SendMessage(clientFd,respMessage); | ||||||
|  |             // wait for download complete
 | ||||||
|  |             printf("wait for download complete,tid=%ld\n",pthread_self()); | ||||||
|  |             sem_wait(&data.isDone); | ||||||
|  |             respMessage = "226 Transfer complete.\r\n"; | ||||||
|  |             SendMessage(clientFd,respMessage); | ||||||
|  |         }else if(strcmp(order,"STOR") == 0){ | ||||||
|  |             RecvData(clientFd,param); | ||||||
|  |             sprintf(data.fileName,"./out/%s",param+1); | ||||||
|  |             data.type = 1; | ||||||
|  |             // notify the thread of waiting fileName
 | ||||||
|  |             sem_post(&data.isReady); | ||||||
|  |             char buf[70]; | ||||||
|  |             sprintf(buf,"150 Opening Binary mode data connection for %s (4096 bytes).\r\n",param+1); | ||||||
|  |             respMessage = buf; | ||||||
|  |             SendMessage(clientFd,respMessage); | ||||||
|  |             // wait for upload complete
 | ||||||
|  |             printf("wait for upload complete,tid=%ld\n",pthread_self()); | ||||||
|  |             sem_wait(&data.isDone); | ||||||
|  |             respMessage = "226 Transfer complete.\r\n"; | ||||||
|  |             SendMessage(clientFd,respMessage); | ||||||
|  |         } | ||||||
|  |         else if(strcmp(order,"QUIT") == 0){ | ||||||
|  |             printf("close clientFd=%d,tid=%ld\n",clientFd,pthread_self()); | ||||||
|  |             close(clientFd); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int main(){ | ||||||
|  |     serverFd = CreateServer(port,0); | ||||||
|  |     sem_init(&data.isReady,0,0); | ||||||
|  |     sem_init(&mutex,0,1); | ||||||
|  |     pthread_t thread; | ||||||
|  |     pthread_create(&thread,NULL,&DataServer,NULL); | ||||||
|  |     int clientFds[THREAD_NUM]; | ||||||
|  |     int i = 0; | ||||||
|  |     while(1){ | ||||||
|  |         struct sockaddr_in clientAdrr = {0};  | ||||||
|  |         int socketLen = sizeof(clientAdrr); | ||||||
|  |         clientFds[i] = accept(serverFd,(struct sockaddr *)&clientAdrr,&socketLen); | ||||||
|  |         printf("accept a client:fd=%d\n",clientFds[i]); | ||||||
|  |         respMessage = "220 (myFtpServer 1.0)\r\n"; | ||||||
|  |         SendMessage(clientFds[i],respMessage); | ||||||
|  |         printf("send welcome message successfully.\n"); | ||||||
|  |         pthread_t thread; | ||||||
|  |         pthread_create(&thread,NULL,&OrderServer,&clientFds[i]); | ||||||
|  |         i++; | ||||||
|  |     } | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
| After Width: | Height: | Size: 97 KiB | 
| After Width: | Height: | Size: 201 KiB | 
| After Width: | Height: | Size: 218 KiB | 
| After Width: | Height: | Size: 165 KiB | 
| After Width: | Height: | Size: 264 KiB | 
| After Width: | Height: | Size: 207 KiB | 
| After Width: | Height: | Size: 350 KiB | 
| After Width: | Height: | Size: 172 KiB | 
| After Width: | Height: | Size: 247 KiB | 
| After Width: | Height: | Size: 336 KiB | 
| After Width: | Height: | Size: 269 KiB | 
| After Width: | Height: | Size: 17 KiB | 
| After Width: | Height: | Size: 473 KiB | 
| After Width: | Height: | Size: 331 KiB | 
| After Width: | Height: | Size: 228 KiB | 
| After Width: | Height: | Size: 208 KiB | 
| After Width: | Height: | Size: 222 KiB | 
| After Width: | Height: | Size: 199 KiB | 
| After Width: | Height: | Size: 268 KiB | 
| After Width: | Height: | Size: 250 KiB | 
| After Width: | Height: | Size: 174 KiB | 
| After Width: | Height: | Size: 193 KiB | 
| After Width: | Height: | Size: 48 KiB | 
| After Width: | Height: | Size: 346 KiB | 
| After Width: | Height: | Size: 412 KiB | 
| After Width: | Height: | Size: 189 KiB | 
| After Width: | Height: | Size: 220 KiB | 
| After Width: | Height: | Size: 52 KiB | 
| After Width: | Height: | Size: 59 KiB | 
| After Width: | Height: | Size: 56 KiB | 
| After Width: | Height: | Size: 56 KiB | 
| After Width: | Height: | Size: 50 KiB | 
| After Width: | Height: | Size: 61 KiB | 
| After Width: | Height: | Size: 31 KiB | 
| After Width: | Height: | Size: 61 KiB | 
| After Width: | Height: | Size: 77 KiB | 
| After Width: | Height: | Size: 84 KiB | 
| After Width: | Height: | Size: 19 KiB | 
| After Width: | Height: | Size: 17 KiB | 
| After Width: | Height: | Size: 114 KiB | 
| After Width: | Height: | Size: 15 KiB | 
| After Width: | Height: | Size: 235 KiB | 
| After Width: | Height: | Size: 211 KiB | 
| After Width: | Height: | Size: 230 KiB | 
| After Width: | Height: | Size: 55 KiB | 
|  | @ -0,0 +1,93 @@ | ||||||
|  | /*
 | ||||||
|  | * Copyright (c) 2020 AIIT XUOS Lab | ||||||
|  | * 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 ftpClient test sample | ||||||
|  | * @version: 1.0 | ||||||
|  | * @author:  bdislab_final | ||||||
|  | * @date:    2023/9/16 | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #include "test_ftpclient_final.h" | ||||||
|  | #include "ftp_client/ftp_client.h" | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <transform.h> | ||||||
|  | #include <pthread.h> | ||||||
|  | 
 | ||||||
|  | int threadIDs[THREAD_NUM]; | ||||||
|  | 
 | ||||||
|  | /*one client upLoad a file of 4K*/ | ||||||
|  | void* UpLoad(void* arg){ | ||||||
|  |     int *pThreadID = (int*)arg; | ||||||
|  |     printf("in thread:tid=%ld\n", pthread_self()); | ||||||
|  |     FtpInitCmd(*pThreadID); | ||||||
|  |     int ret = FtpLogin(*pThreadID,"8.140.53.225", 9992, "anonymous", "anonymous"); | ||||||
|  |     int size = 4096; | ||||||
|  |     char buf[size]; | ||||||
|  |     char fileName[20]; | ||||||
|  |     sprintf(fileName,"file%d",*pThreadID); | ||||||
|  |     for(int i = 0;i < size;++i){ | ||||||
|  |         buf[i] = '0'; | ||||||
|  |     } | ||||||
|  |     FtpInitData(*pThreadID);  // data socket 每次下载都要重新创建,下载完都要关闭
 | ||||||
|  |     ret = FtpUpload(*pThreadID,fileName,buf,size); | ||||||
|  |     FtpQuit(*pThreadID); | ||||||
|  |     return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*one client downLoad a file of 4K*/ | ||||||
|  | void* DownLoad(void* arg){ | ||||||
|  |     int *pThreadID = (int*)arg; | ||||||
|  |     printf("in thread:tid=%ld\n", pthread_self()); | ||||||
|  |     FtpInitCmd(*pThreadID); | ||||||
|  |     int ret = FtpLogin(*pThreadID,"8.140.53.225", 9992, "anonymous", "anonymous"); | ||||||
|  |     int size; | ||||||
|  |     char *buf; | ||||||
|  |     char fileName[20] = "/file1";  | ||||||
|  |     size = FtpFileSize(*pThreadID,fileName); | ||||||
|  |     buf = malloc(size); | ||||||
|  |     FtpInitData(*pThreadID);  // data socket 每次下载都要重新创建,下载完都要关闭
 | ||||||
|  |     ret = FtpDownload(*pThreadID,fileName, buf, size); | ||||||
|  |     free(buf); | ||||||
|  |     FtpQuit(*pThreadID); | ||||||
|  |     return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* test for 10 ftp client */ | ||||||
|  | void TestFtpClient(int argc, char* argv[]) | ||||||
|  | { | ||||||
|  |     int options = atoi(argv[1]); | ||||||
|  |     int n = atoi(argv[2]); | ||||||
|  |     pthread_t threads[THREAD_NUM]; | ||||||
|  |     for(int i = 0;i < n;++i){ | ||||||
|  |         threadIDs[i] = i; | ||||||
|  |         if(options == 1){ // 全部都是下载
 | ||||||
|  |             pthread_create(&threads[i],NULL,&DownLoad,&threadIDs[i]); | ||||||
|  |         }else if(options == 2){ // 全部都是上传
 | ||||||
|  |             pthread_create(&threads[i],NULL,&UpLoad,&threadIDs[i]); | ||||||
|  |         }else if(options == 3){  // 随机下载/上传
 | ||||||
|  |             int r = rand()%2; | ||||||
|  |             if(r == 0){ | ||||||
|  |                 printf("===============download===============\n"); | ||||||
|  |                 pthread_create(&threads[i],NULL,&DownLoad,&threadIDs[i]); | ||||||
|  |             }else{ | ||||||
|  |                 printf("===============upload===============\n"); | ||||||
|  |                 pthread_create(&threads[i],NULL,&UpLoad,&threadIDs[i]); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return; | ||||||
|  | } | ||||||
|  | PRIV_SHELL_CMD_FUNCTION(TestFtpClient, a ftpClient test sample, PRIV_SHELL_CMD_MAIN_ATTR); | ||||||
|  | @ -0,0 +1,37 @@ | ||||||
|  | /*
 | ||||||
|  | * Copyright (c) 2020 AIIT XUOS Lab | ||||||
|  | * 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 a ftpClient test sample | ||||||
|  |  * @version 1.0 | ||||||
|  |  * @author bdislab_final | ||||||
|  |  * @date 2023/9/16 | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #ifndef TEST_FTPCLIENT_H | ||||||
|  | #define TEST_FTPCLIENT_H | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | /*one client upLoad a file of 4K*/ | ||||||
|  | void* UpLoad(void* arg); | ||||||
|  | /*one client downLoad 10 files of 4K*/ | ||||||
|  | void* DownLoad(void* arg); | ||||||
|  | /* test for ftp client */ | ||||||
|  | void TestFtpClient(int argc, char* argv[]); | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | @ -0,0 +1,43 @@ | ||||||
|  | # 基于矽璓已实现的W5500网卡驱动,在Riscv上实现FTP协议的Client功能 # | ||||||
|  | 
 | ||||||
|  | ## 1. 简介 | ||||||
|  | 利用w5500网络编程的api实现了ftp客户端的功能,具体功能包括向ftp服务器发送指定命令,根据用户名登陆ftp服务器,获取文件大小,下载指定文件并保存至sd卡内,并提供了测试函数模拟从ftp服务器上下载10个4KB文件的过程 | ||||||
|  | 
 | ||||||
|  | ## 2. 数据结构设计说明 | ||||||
|  | 全局变量: | ||||||
|  | char sendBuffer[]:输出缓冲区   | ||||||
|  | char recvBuffer[]:输入缓冲区 | ||||||
|  | 
 | ||||||
|  | 包括以下函数功能,分别为:   | ||||||
|  | `SendCommand`:发送指定的指令   | ||||||
|  | `EnterPasv`:进入被动模式   | ||||||
|  | `Login`:根据用户名登陆ftp服务器   | ||||||
|  | `GetFileSize`:获取指定文件的大小   | ||||||
|  | `Download`:下载指定文件 | ||||||
|  |    | ||||||
|  | 
 | ||||||
|  | ## 3. 测试程序说明 | ||||||
|  | 测试了创建套接字,与服务器建立连接并根据传入的用户名和密码发送登陆指令。登陆成功后下载服务器上指定的10个4KB大小的txt文件,然后调用开发板的相关api在系统根目录中创建对应的文件,写入从服务器接收到的数据。 | ||||||
|  | 
 | ||||||
|  | ## 4. 运行结果(##需结合运行测试截图按步骤说明##) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 打开menuconfig之后,将test_ftp开启(y),将Using TFcard device 和 Using W5500 as network device 开启(y)保存后退出 | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | 编译XiZi-edu-riscv64.elf成功 | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | 启动kflash烧录bin文件,按reset键重置成功进入系统并显示SD卡已挂载 | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | 执行TestTfp命令,可以看到成功登陆ftp服务器,并开始下载10个大小为4KB的文件。 | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | 服务器日志信息 | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | 读取sd卡中的文件可以看到10个大小为4KB的文件被成功下载 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| After Width: | Height: | Size: 172 KiB | 
| After Width: | Height: | Size: 161 KiB | 
| After Width: | Height: | Size: 258 KiB | 
| After Width: | Height: | Size: 116 KiB | 
| After Width: | Height: | Size: 117 KiB |