diff --git a/APP_Framework/Applications/app_test/test_ftpclient_final/README.md b/APP_Framework/Applications/app_test/test_ftpclient_final/README.md new file mode 100644 index 000000000..3c676cf0e --- /dev/null +++ b/APP_Framework/Applications/app_test/test_ftpclient_final/README.md @@ -0,0 +1,80 @@ +# 基于赛事提供的云服务器的Server服务器 + +## 1. 简介 +利用c语言实现了ftp服务器,支持至少10个Client端并发向Server端传输4KB大小的文件,支持Server端并发地向至少10个Client端传输4KB大小的文件 + + +## 2. 数据结构设计说明 +user类用于持久化用户名和密码 +```c +struct User { + char username[50]; + char password[50]; +}; +``` +LoginStatus类用于持久化用户的登录信息 +```c +struct LoginStatus { + char *addr; + char username[50]; + char password[50]; + int login_status; +}; +``` +服务端包含以下函数: +```c +void StartNewConnection(int data_fd,struct sockaddr_in client_addr);//创建新连接 +void GetFullAddress(char* client_id, char* client_ip, int client_port);//根据客户端ip地址和端口号生成完整地址 +int CheckPassword(int it);//验证用户名与密码是否匹配 +void *CreateDataSockt(void *arg);//创建新数据连接 +char* GetRespond(char* buf, int it, int* ret, int cmd_fd);//根据输入的指令获取相应数据 +void *RecvSend(void *arg);//接收请求发送回应 +int Init();//初始化 + + + +``` + +## 3. 测试程序说明 +测试在本地运行10个客户端并行下载服务器的4kb文件,10个客户端向服务器并行上传10个4kb的文件。 + +## 4. 运行结果(##需结合运行测试截图按步骤说明##) +![image](img/01.png) +![image](img/02.png) +打开menuconfig之后,将Using LwIP by ethernet开启(y),Using SD CARD device开启(y),Config test ftp client 开启(y)保存后退出 + +![image](img/03.png) +编译XiZi-edu-arm32.elf成功 + +![image](img/04.png) +启动HDSC烧录XiZi-edu-arm32.bin文件至开发板 + +![image](img/05.png) +将开发板与路由器连接,配置开发板ip地址,子网掩码,网关使得开发板能连接互联网 + +![image](img/06.png) +使用putty连接服务器(8.140.53.225)用户名:xiuos 密码:xiuos@123 + +![image](img/07.png) +cd wojiuguaji 进入文件夹 + +![image](img/07.png) +cd wojiuguaji 进入文件夹 + +![image](img/08.png) +gcc ftpserver.c -lpthread 编译服务端文件 + +![image](img/09.png) +./a.out 运行服务端文件 + +![image](img/10.png) +打开MobaXterm连接开发板 + +![image](img/11.png) +在MobaXterm输入DownloadTest测试10个客户端并发下载,可以看到成功下载10个4KB的文件 + +![image](img/12.png) +在服务器终端输入Ctrl + C结束服务器进程,等待一段时间后服务解除占用的端口后再次使用./a.out运行服务器程序 + +![image](img/13.png) +在MobaXterm输入UploadTest测试10个客户端并发上传,可以看到成功上传10个4KB的文件 \ No newline at end of file diff --git a/APP_Framework/Applications/app_test/test_ftpclient_final/ftpserver.c b/APP_Framework/Applications/app_test/test_ftpclient_final/ftpserver.c index eebaf62d1..5418424f1 100644 --- a/APP_Framework/Applications/app_test/test_ftpclient_final/ftpserver.c +++ b/APP_Framework/Applications/app_test/test_ftpclient_final/ftpserver.c @@ -34,7 +34,7 @@ #define MAX_CONNECTION 100 #define UNLOGED_IN 0 #define LOGED_IN 1 - +int pasv_complete[200]; int off = 0; int fd_map[200]; struct User { @@ -49,6 +49,8 @@ struct LoginStatus { int login_status; }; +pthread_mutex_t mutex; + struct User users[MAX_USERS]; struct LoginStatus login_list[MAX_CONNECTION]; @@ -61,13 +63,16 @@ void GetFullAddress(char* client_id, char* client_ip, int client_port) { int CheckPassword(int it) { for (int i = 0;i < MAX_USERS;i++) { - if (strcmp(login_list[it].username, users[i].username) == 0 && strcmp(login_list[it].password, users[i].password) == 0)return 1; + if (strcmp(login_list[it].username, users[i].username) == 0 && strcmp(login_list[it].password, users[i].password) == 0) + { + return 1; + } } return 0; } void *CreateDataSockt(void *arg) { - + pthread_mutex_lock(&mutex); int *data = arg; int port = data[0]; int cmd_fd = data[1]; @@ -82,9 +87,9 @@ void *CreateDataSockt(void *arg) { server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); server_addr.sin_addr.s_addr = INADDR_ANY; - int ret = bind(fd, (struct sockaddr *)&server_addr, sizeof(server_addr)); + int ret = bind(fd, (struct sockaddr*)&server_addr, sizeof(server_addr)); + pthread_mutex_unlock(&mutex); if (ret < 0) { - printf("%d\n", ret); printf("Failed to bind socket\n"); return NULL; } @@ -95,22 +100,21 @@ void *CreateDataSockt(void *arg) { struct sockaddr_in client_addr; socklen_t len = sizeof(client_addr); - int data_fd = accept(fd, (struct sockaddr *)&client_addr, &len); - + int data_fd = accept(fd, (struct sockaddr*)&client_addr, &len); fd_map[cmd_fd] = data_fd; - + pasv_complete[data_fd] = 1; } close(fd); return NULL; } -char* GetRespond(char* buf, int it,int *ret,int cmd_fd) { - char * cmd = malloc(100); +char* GetRespond(char* buf, int it, int* ret, int cmd_fd) { + pthread_mutex_lock(&mutex); + char* cmd = malloc(100); char * data = malloc(100); char* respond = malloc(100); - //debug - printf("%s\n", buf); + sscanf(buf, "%s %s", cmd, data); if(strcmp(cmd,"USER")==0){ login_list[it].login_status=LOGED_IN; @@ -131,14 +135,14 @@ char* GetRespond(char* buf, int it,int *ret,int cmd_fd) { if (stat(data, &file_stat) == 0) { int size = file_stat.st_size; - sprintf(respond, "213 %d", size); + sprintf(respond, "213 %d\n", size); } - else sprintf(respond, "550 file not found"); + else sprintf(respond, "550 file not found\n"); } else if (strcmp(cmd, "PASV") == 0) { off = (off + 1) % 15; int port = 9980 + off; - sprintf(respond, "227 enter passive mode (8.140.53.225,%d,%d)", port / 256, port % 256); + sprintf(respond, "227 enter passive mode (8,140,53,225,%d,%d)\n", port / 256, port % 256); pthread_t thread; int arg[2]; arg[0] = port; @@ -147,7 +151,8 @@ char* GetRespond(char* buf, int it,int *ret,int cmd_fd) { *ret = 227; } else if (strcmp(cmd, "RETR") == 0) { - char* dir=malloc(100); + while (pasv_complete[fd_map[cmd_fd]] == 0); + char* dir = malloc(100); sprintf(dir, "/home/xiuos/wojiuguaji/%s", data); FILE* file = fopen(dir, "rb"); if (file == NULL) { @@ -158,14 +163,16 @@ char* GetRespond(char* buf, int it,int *ret,int cmd_fd) { char* start = "150 starting data transfer\n"; write(cmd_fd, start, strlen(start)); - char* buff = (char*)malloc(file_size); - + char* buff = (char*)malloc(file_size + 1); + memset(buff, sizeof(buff), 0); fread(buff, 1, file_size, file); - int size = write(fd_map[cmd_fd], buff, strlen(buff)); + + int size = send(fd_map[cmd_fd], buff, strlen(buff), 0); if (size < 0) { + perror("send error"); printf("failed to send message\n"); } - char* end = "226 Operation successfull"; + char* end = "226 Operation successfull\n"; write(cmd_fd, end, strlen(end)); fclose(file); @@ -173,21 +180,25 @@ char* GetRespond(char* buf, int it,int *ret,int cmd_fd) { free(dir); } else if (strcmp(cmd, "STOR") == 0) { - char* dir=malloc(100); + while (pasv_complete[fd_map[cmd_fd]] == 0); + char* dir = malloc(100); sprintf(dir, "/home/xiuos/wojiuguaji/%s", data); FILE* file = fopen(dir, "wb"); if (file == NULL) { + perror("file openfail"); sprintf(respond, "550 failed to open file\n"); } char* start = "150 starting data transfer\n"; - write(cmd_fd, start, strlen(start)); + int ret = write(cmd_fd, start, strlen(start)); char* buff = (char*)malloc(5000); - int size = read(fd_map[cmd_fd], buff, 5000); + + int size = recv(fd_map[cmd_fd], buff, 5000, 0); + while (size < 0) { - size = read(fd_map[cmd_fd], buff, 5000); + size = recv(fd_map[cmd_fd], buff, 5000, 0); } - char* end = "226 Operation successfull"; + char* end = "226 Operation successfull\n"; write(cmd_fd, end, strlen(end)); fwrite(buff, 1, strlen(buff), file); @@ -196,15 +207,16 @@ char* GetRespond(char* buf, int it,int *ret,int cmd_fd) { free(dir); } else if(strcmp(cmd,"QUIT")==0){ - sprintf(respond, "221 connection close"); + sprintf(respond, "221 connection close\n"); *ret = 221; } else if (strcmp(cmd, "TYPE") == 0) { - sprintf(respond, "200 Type set to I"); + sprintf(respond, "200 Type set to I\n"); } else { respond = "500 syntax error\n"; } + pthread_mutex_unlock(&mutex); return respond; } @@ -232,6 +244,7 @@ void *RecvSend(void *arg) } void StartNewConnection(int cmd_fd, struct sockaddr_in client_addr) { + pthread_mutex_lock(&mutex); char client_ip[INET_ADDRSTRLEN]; int client_port; inet_ntop(AF_INET, &(client_addr.sin_addr), client_ip, sizeof(client_ip)); @@ -248,30 +261,30 @@ void StartNewConnection(int cmd_fd, struct sockaddr_in client_addr) } if (it == -1) { for(int i=0;i