update server readme
|
@ -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. 运行结果(##需结合运行测试截图按步骤说明##)
|
||||

|
||||

|
||||
打开menuconfig之后,将Using LwIP by ethernet开启(y),Using SD CARD device开启(y),Config test ftp client 开启(y)保存后退出
|
||||
|
||||

|
||||
编译XiZi-edu-arm32.elf成功
|
||||
|
||||

|
||||
启动HDSC烧录XiZi-edu-arm32.bin文件至开发板
|
||||
|
||||

|
||||
将开发板与路由器连接,配置开发板ip地址,子网掩码,网关使得开发板能连接互联网
|
||||
|
||||

|
||||
使用putty连接服务器(8.140.53.225)用户名:xiuos 密码:xiuos@123
|
||||
|
||||

|
||||
cd wojiuguaji 进入文件夹
|
||||
|
||||

|
||||
cd wojiuguaji 进入文件夹
|
||||
|
||||

|
||||
gcc ftpserver.c -lpthread 编译服务端文件
|
||||
|
||||

|
||||
./a.out 运行服务端文件
|
||||
|
||||

|
||||
打开MobaXterm连接开发板
|
||||
|
||||

|
||||
在MobaXterm输入DownloadTest测试10个客户端并发下载,可以看到成功下载10个4KB的文件
|
||||
|
||||

|
||||
在服务器终端输入Ctrl + C结束服务器进程,等待一段时间后服务解除占用的端口后再次使用./a.out运行服务器程序
|
||||
|
||||

|
||||
在MobaXterm输入UploadTest测试10个客户端并发上传,可以看到成功上传10个4KB的文件
|
|
@ -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<MAX_CONNECTION;i++){
|
||||
if(login_list[i].login_status==0){
|
||||
if(login_list[i].login_status==UNLOGED_IN && strlen(login_list[i].addr)==0){
|
||||
it = i;
|
||||
strcpy(login_list[i].addr, client_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(it==-1){
|
||||
const char limit_exceeded[] = "530 connection limit exceeded.";
|
||||
const char limit_exceeded[] = "530 connection limit exceeded.\n";
|
||||
write(cmd_fd, limit_exceeded, strlen(limit_exceeded));
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(login_list[it].login_status == UNLOGED_IN){
|
||||
const char welcome[] = "220 welcome.";
|
||||
if (login_list[it].login_status == UNLOGED_IN) {
|
||||
const char welcome[] = "220 welcome.\n.";
|
||||
write(cmd_fd, welcome, strlen(welcome));
|
||||
}
|
||||
|
||||
pthread_t thread;
|
||||
|
||||
int arg[2];
|
||||
int *arg = malloc(2);
|
||||
arg[0] = cmd_fd;
|
||||
arg[1] = it;
|
||||
pthread_create(&thread, NULL, RecvSend, arg);
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
int Init() {
|
||||
|
@ -279,6 +292,7 @@ int Init() {
|
|||
|
||||
for (int i = 0;i < MAX_CONNECTION;i++) {
|
||||
login_list[i].addr = (char*)malloc(50);
|
||||
login_list[i].login_status = UNLOGED_IN;
|
||||
strcpy(login_list[i].addr, "");
|
||||
}
|
||||
int fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
@ -293,7 +307,6 @@ int Init() {
|
|||
server_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
int ret = bind(fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
|
||||
if (ret < 0) {
|
||||
printf("%d\n", ret);
|
||||
printf("Failed to bind socket\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
After Width: | Height: | Size: 122 KiB |
After Width: | Height: | Size: 123 KiB |
After Width: | Height: | Size: 197 KiB |
After Width: | Height: | Size: 77 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 67 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 174 KiB |
After Width: | Height: | Size: 225 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 217 KiB |