diff --git a/APP_Framework/Applications/app_test/test_ftpclient_final/README.md b/APP_Framework/Applications/app_test/test_ftpclient_final/README.md index f37ec7a77..2e691ad00 100644 --- a/APP_Framework/Applications/app_test/test_ftpclient_final/README.md +++ b/APP_Framework/Applications/app_test/test_ftpclient_final/README.md @@ -19,20 +19,22 @@ static char m_recv_buffer[THREAD_NUM][1024]; // 接收缓冲区 ``` - server.c 的设计(具体代码在赛事提供的云服务器的/root/yanglongFTP下) ```c -#define THREAD_NUM 10 // 可接受的客户端数目 -static int isBinary = 0; // 是否是二进制传输文件 -static int port = 9992; // 命令服务器端口 -static int dataPort = 9993; // 文件传输服务器端口 -static char order[4]; // 存储命令 -static char param[20]; // 存储命令参数 -static char *respMessage; // 响应消息指针 -static int serverFd; // 命令服务器的socket fd -static int dataServerFd; // 文件传输服务器的 socket fd -struct Data{ // 用于线程间通信 - sem_t isReady; // 命令服务器是否收到并写好文件名 - sem_t isDone; // 文件传输服务器是否传输完文件 - char fileName[20]; // 存储文件名 -}; +#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用于测试多个客户端并发下载文件 @@ -44,12 +46,22 @@ 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){ // for DownLoad - pthread_create(NULL,NULL,&DownLoad,&threadIDs[i]); - }else if(options == 2){ // for upLoad - pthread_create(NULL,NULL,&UpLoad,&threadIDs[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; @@ -103,4 +115,21 @@ PRIV_SHELL_CMD_FUNCTION(TestFtpClient, a ftpClient test sample, PRIV_SHELL_CMD_M ![](./img/image-31.png) ![](./img/image-32.png) - 上传结果 -![](./img/image-33.png) \ No newline at end of file +![](./img/image-33.png) +8. 运行TestFtpClient 3 10,模拟10个客户端混合并发下载和上传文件 +- 客户端日志 +![](./img/image-34.png) +![](./img/image-35.png) +![](./img/image-36.png) +![](./img/image-37.png) +![](./img/image-38.png) +![](./img/image-39.png) + +- 服务器日志 +![](./img/image-40.png) +![](./img/image-41.png) +![](./img/image-42.png) + +- 下载和上传结果 +![](./img/image-43.png) +![](./img/image-44.png) \ No newline at end of file diff --git a/APP_Framework/Applications/app_test/test_ftpclient_final/ftp_server/server.c b/APP_Framework/Applications/app_test/test_ftpclient_final/ftp_server/server.c index 154f0e5d8..14000941a 100644 --- a/APP_Framework/Applications/app_test/test_ftpclient_final/ftp_server/server.c +++ b/APP_Framework/Applications/app_test/test_ftpclient_final/ftp_server/server.c @@ -1,3 +1,23 @@ +/* +* 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 #include #include @@ -7,7 +27,7 @@ #include #include -#define THREAD_NUM 10 +#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 @@ -16,11 +36,13 @@ 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 -struct Data{ - sem_t isReady; - sem_t isDone; - char fileName[20]; -}; +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); @@ -41,7 +63,7 @@ void SendMessage(int clientFd, char * respMessage){ send(clientFd,respMessage,len+1,0); } -int CreateServer(int port) { +int CreateServer(int port,int type) { int serverFd = 0; struct sockaddr_in serverAddr = {0}; socklen_t socklen = 0; @@ -50,8 +72,13 @@ int CreateServer(int port) { { printf("创建socket失败\n"); return 0; - } - printf("in server:serverFd=%d\n",serverFd); + } + + 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); @@ -68,49 +95,60 @@ int CreateServer(int port) { return serverFd; } -// accept a client and receive file's data +// receive file's data void* UpLoadServer(void * args){ - struct Data* pData = (struct Data *) args; - struct sockaddr_in clientAdrr = {0}; - int socketLen = sizeof(clientAdrr); - int clientFd = accept(dataServerFd,(struct sockaddr *)&clientAdrr,&socketLen); - printf("accept a client for file upload: clientFd=%d,tid=%ld\n",clientFd,pthread_self()); - char data[4096]; - int ret = recv(clientFd,data,4096,0); + 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(pData->fileName,"wb"); // fileName需要线程间通信 - fwrite(data,4096,1,file); + 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()); - sem_post(&pData->isDone); + // notify for file download complete + sem_post(&data.isDone); close(clientFd); } -// accept a client and send file's data +// send file's data void* DownLoadServer(void * args){ - struct Data* pData = (struct Data *) args; - struct sockaddr_in clientAdrr = {0}; - int socketLen = sizeof(clientAdrr); - int clientFd = accept(dataServerFd,(struct sockaddr *)&clientAdrr,&socketLen); - printf("accept a client for file download: clientFd=%d,tid=%ld\n",clientFd,pthread_self()); - - // wait for fileName ready - printf("wait for fileName ready,tid=%ld\n",pthread_self()); - sem_wait(&pData->isReady); - char data[4096]; - FILE * file = fopen(pData->fileName,"rb"); // fileName需要线程间通信 - fread(data,4096,1,file); - send(clientFd,data,sizeof(data),0); + 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()); - sem_post(&pData->isDone); + // 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; - struct Data data; printf("in OrderServer thread: tid=%ld\n",pthread_self()); // order format: USER anonymous\r\n // response code format: 213 4096\r\n @@ -142,7 +180,7 @@ void* OrderServer(void * args){ respMessage = "213 4096\r\n"; SendMessage(clientFd,respMessage); }else if(strcmp(order,"PASV") == 0){ - sem_init(&data.isReady,0,0); + sem_wait(&mutex); // 锁竞争 sem_init(&data.isDone,0,0); RecvData(clientFd,param); char buf[50]; @@ -152,8 +190,7 @@ void* OrderServer(void * args){ }else if(strcmp(order,"RETR") == 0){ RecvData(clientFd,param); sprintf(data.fileName,"./data/%s",param+2); - pthread_t thread; - pthread_create(&thread,NULL,&DownLoadServer,&data); + data.type = 0; // notify the thread of waiting fileName sem_post(&data.isReady); char buf[70]; @@ -168,8 +205,9 @@ void* OrderServer(void * args){ }else if(strcmp(order,"STOR") == 0){ RecvData(clientFd,param); sprintf(data.fileName,"./out/%s",param+1); - pthread_t thread; - pthread_create(&thread,NULL,&UpLoadServer,&data); + 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; @@ -190,8 +228,11 @@ void* OrderServer(void * args){ } int main(){ - serverFd = CreateServer(port); - dataServerFd = CreateServer(dataPort); + 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){ @@ -201,7 +242,7 @@ int main(){ printf("accept a client:fd=%d\n",clientFds[i]); respMessage = "220 (myFtpServer 1.0)\r\n"; SendMessage(clientFds[i],respMessage); - printf("send successful.\n"); + printf("send welcome message successfully.\n"); pthread_t thread; pthread_create(&thread,NULL,&OrderServer,&clientFds[i]); i++; diff --git a/APP_Framework/Applications/app_test/test_ftpclient_final/ftp_server/test.c b/APP_Framework/Applications/app_test/test_ftpclient_final/ftp_server/test.c deleted file mode 100644 index 2ef2d11a0..000000000 --- a/APP_Framework/Applications/app_test/test_ftpclient_final/ftp_server/test.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -int main(){ - char* t = "123456789\r\n"; - printf("%ld:%s",sizeof(t),t); -} \ No newline at end of file diff --git a/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-34.png b/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-34.png new file mode 100644 index 000000000..f75b9add0 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-34.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-35.png b/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-35.png new file mode 100644 index 000000000..57b8fc78b Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-35.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-36.png b/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-36.png new file mode 100644 index 000000000..f92bc2ea9 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-36.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-37.png b/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-37.png new file mode 100644 index 000000000..0ca516df6 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-37.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-38.png b/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-38.png new file mode 100644 index 000000000..c58057dc6 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-38.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-39.png b/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-39.png new file mode 100644 index 000000000..b45cd4f88 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-39.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-40.png b/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-40.png new file mode 100644 index 000000000..0c787de91 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-40.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-41.png b/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-41.png new file mode 100644 index 000000000..c9cde1089 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-41.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-42.png b/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-42.png new file mode 100644 index 000000000..cb6147feb Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-42.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-43.png b/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-43.png new file mode 100644 index 000000000..885ba0192 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-43.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-44.png b/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-44.png new file mode 100644 index 000000000..d41535660 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_ftpclient_final/img/image-44.png differ diff --git a/APP_Framework/Applications/app_test/test_ftpclient_final/test_ftpclient_final.c b/APP_Framework/Applications/app_test/test_ftpclient_final/test_ftpclient_final.c index 117421842..5a2024f79 100644 --- a/APP_Framework/Applications/app_test/test_ftpclient_final/test_ftpclient_final.c +++ b/APP_Framework/Applications/app_test/test_ftpclient_final/test_ftpclient_final.c @@ -70,12 +70,22 @@ 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){ // for DownLoad - pthread_create(NULL,NULL,&DownLoad,&threadIDs[i]); - }else if(options == 2){ // for upLoad - pthread_create(NULL,NULL,&UpLoad,&threadIDs[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;