本文根据在网上已有的ftpserver实现,但是根据那个源代码无法运行成功,因此,这里是基于那个代码的基础上,修改的(网址忘记了)。增加了一些命令,以及界面交互和bug. 目的在于熟悉ftp的协议以及通信。
环境:Ubuntu
1. ftpserver源码实现:
#include#include #include #include #include #include #include #include #include struct data { char ip[100]; short port; char user[100]; char pass[100]; char url[100]; int sock; pthread_t pid; FILE *fp; }; void server_init(struct data *data); void server_set(struct data *data, const char *addr, short port, const char *user, const char *pass, const char *rooturl); int server_start(struct data *data); void server_stop(struct data *data); #include #include #include #include #include #include #include struct ftp_server { int ofs; int port_ip; short port_port; int c_sock; int d_sock; int data_sock; int c_addr; short c_port; int d_addr; short d_port; int islogin; char rename[256]; char send_buf[256]; char user[100]; char pass[100]; void *data; }; static pid_t pid_arr[256]; static void sig_fun(int sig) { int status, i; pid_t pid = wait(&status); for (i = 0; i < sizeof(pid_arr) / sizeof(pid_arr[0]); i++) { if (pid_arr[i] == pid) { printf("pid=%d child exitn", pid); pid_arr[i] = 0; } } } static void close_tenor(void) { int i; for (i = 0; i < sizeof(pid_arr) / sizeof(pid_arr[0]); i++) { if (pid_arr[i]) { kill(pid_arr[i], SIGINT); pid_arr[i] = 0; } } } static char *my_split(char *src, const char *key, int *len, char **data) { char *pos, *p; if (src) *data = src; pos = strstr(*data, key); if (!pos) { *len = 0; return *data; } else { *len = pos - *data; p = *data; while (!memcmp(pos, key, strlen(key))) { pos += strlen(key); } *data = pos; return p; } } static int ftp_server_user(struct ftp_server *server, const char *cmd) { char *start; start = strstr(cmd, " "); if (!start) return -1; start++; if (!strcmp(server->user, start)) { sprintf(server->send_buf, "331 Password requiredrn"); server->islogin = 1; } else { sprintf(server->send_buf, "332 notfound userrn"); server->islogin = 0; } printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); return 0; } static int ftp_server_pass(struct ftp_server *server, const char *cmd) { char *start; start = strstr(cmd, " "); if (!start) return -1; start++; if (!strcmp(server->pass, start)) { sprintf(server->send_buf, "230 User logged in..rn"); if (server->islogin == 1) server->islogin = 2; else server->islogin = 0; } else { sprintf(server->send_buf, "331 Need password loginrn"); server->islogin = 0; } printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); return 0; } static int ftp_server_syst(struct ftp_server *server, const char *cmd) { char* buf = "215 UNIX ftpserver emulated rn"; printf("%s", buf); send(server->c_sock, buf, strlen(buf), 0); return 0; } static int ftp_server_pwd(struct ftp_server *server, const char *cmd) { char buf[128] = {}; getcwd(buf, sizeof(buf) - 1); sprintf(server->send_buf, "257 "%s" is current directory.rn", buf); printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); return 0; } static int ftp_server_type(struct ftp_server *server, const char *cmd) { char *start; start = strstr(cmd, " "); if (!start) return -1; start++; if (!strncmp(start, "I", 1)) { sprintf(server->send_buf, "200 Type set to I.rn"); } else { sprintf(server->send_buf, "500 : command not understood.rn"); } printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); return 0; } static int ftp_server_pasv(struct ftp_server *server, const char *cmd) { int ret; struct sockaddr_in addr; server->port_ip = 0; server->d_sock = socket(AF_INET, SOCK_STREAM , 0); if (server->d_sock == -1) { return -1; } struct timeval timeout = {6, 0}; setsockopt(server->d_sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(struct timeval)); //设置接收超时 setsockopt(server->d_sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval)); addr.sin_addr.s_addr = server->d_addr; addr.sin_port = 0; addr.sin_family = AF_INET; int opt=SO_REUSEADDR; setsockopt(server->d_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); ret = bind(server->d_sock, (struct sockaddr *)&addr, sizeof(addr)); if (ret != 0) { return -1; } struct sockaddr_in localaddr; socklen_t locallen = sizeof(localaddr); getsockname(server->d_sock, (struct sockaddr *)&localaddr, & locallen); ret = listen(server->d_sock, 10); if (ret == -1) { close(server->d_sock); return -1; } short port = localaddr.sin_port; sprintf(server->send_buf, "227 Entering Passive Mode (%s,%d,%d)rn", inet_ntoa(localaddr.sin_addr), 0xff & (port), 0xff & (port >> 8)); int i; for (i = 0; i < strlen(server->send_buf); i++) { if (server->send_buf[i] == '.') server->send_buf[i] = ','; } printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); return 0; } static int ftp_server_port(struct ftp_server *server, const char *cmd) { char *start; struct in_addr add; start = strstr(cmd, " "); if (!start) return -1; start++; char *pos, *end; pos = start; int i; for (i = 0, end = pos; i < 4; i++) { end = strstr(end, ","); if (end) *end = '.'; } *end = 0; server->port_ip = inet_addr(pos); add.s_addr = server->port_ip; pos = ++end; end = strstr(pos, ","); if (end) *end = 0; server->port_port = atoi(pos); server->port_port <<= 8; server->port_port |= atoi(end + 1); server->port_port = htons(server->port_port); printf("%s", "200 Port command successful.rn"); printf("ip=%s,port=%dn", inet_ntoa(add), ntohs(server->port_port)); send(server->c_sock, "200 Port command successful.rn", strlen("200 Port command successful.rn"), 0); return 0; } static int ftp_server_get_dsock(struct ftp_server *server) { struct sockaddr_in inaddr; socklen_t socklen = sizeof(inaddr); if (server->port_ip == 0) { server->data_sock = accept(server->d_sock, (struct sockaddr *)&inaddr, &socklen); if (server->data_sock == -1) return -1; } else { server->data_sock = socket(AF_INET, SOCK_STREAM, 0); if (server->data_sock == -1) return -1; inaddr.sin_addr.s_addr = server->port_ip; inaddr.sin_port = server->port_port; inaddr.sin_family = AF_INET; //in server, bind port=20 struct sockaddr_in serv_addr; serv_addr.sin_addr.s_addr = server->d_addr; serv_addr.sin_port = 20; serv_addr.sin_family = AF_INET; int opt=SO_REUSEADDR; setsockopt(server->data_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); int bind_ret = bind(server->data_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); if (bind_ret == -1) { perror("bind"); printf("failedn"); return -1; } struct timeval timeout = {30, 0}; setsockopt(server->data_sock , SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(struct timeval)); int ret = connect(server->data_sock, (struct sockaddr *)&inaddr, socklen); if (ret == -1) { close(server->data_sock); server->data_sock = -1; return -1; } } return 0; } static void stat_test(const char *name, char *out) { struct stat s = {}; char buf[100] = {}; int res = stat(name, &s); if (-1 == res) { return; } if (S_ISDIR(s.st_mode)) { out[0] = 'd'; } else { out[0] = '-'; } out[1] = 0; int i; int num = s.st_mode & 07777; strcat(out, "rwxrwxrwx"); for (i = 0; i < 9; i++) { if (!(num & (0x100 >> i))) { out[i + 1] = '-'; } } strcat(out, " "); sprintf(buf, "%3d", s.st_nlink); strcat(out, buf); strcat(out, " root root "); sprintf(buf, "%6d", (int)s.st_size); strcat(out, buf); strcat(out, " "); time_t t = time(NULL); int year = gmtime(&t)->tm_year; int year2 = gmtime(&s.st_mtime)->tm_year; if (year == year2) { strftime(buf, sizeof(buf), "%h %d %R", gmtime(&s.st_mtime)); } else { strftime(buf, sizeof(buf), "%h %d %G", gmtime(&s.st_mtime)); } strcat(out, buf); strcat(out, " "); strcat(out, name); strcat(out, "rn"); } static int ftp_server_list(struct ftp_server *server, const char *cmd) { if (server->d_sock == -1) return -1; printf("%s", "150 Opening BINARY mode data connection for /bin/ls.rn"); send(server->c_sock, "150 Opening BINARY mode data connection for /bin/ls.rn", strlen("150 Opening BINARY mode data connection for /bin/ls.rn"), 0); DIR *dir = NULL; struct dirent *ent = NULL; char buf[256] = {}; dir = opendir("."); if (!dir) { return -1; } if (-1 == ftp_server_get_dsock(server)) { return -1; } while ((ent = readdir(dir))) { if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) continue; stat_test(ent->d_name, buf); //printf("%s", buf); send(server->data_sock, buf, strlen(buf), 0); } closedir(dir); close(server->data_sock); if (server->d_sock != -1) close(server->d_sock); printf("%s", "226 Transfer complete.rn"); send(server->c_sock, "226 Transfer complete.rn", strlen("226 Transfer complete.rn"), 0); return 0; } static int ftp_server_stor(struct ftp_server *server, const char *cmd) { if (server->d_sock == -1) return -1; char *start; start = strstr(cmd, " "); if (!start) return -1; start++; sprintf(server->send_buf, "150 Opening BINARY mode data connection.rn"); printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); int fd; int len; char buf[256] = {}; if (-1 == ftp_server_get_dsock(server)) { sprintf(server->send_buf, "553 net errrn"); printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); if (server->d_sock != -1) close(server->d_sock); return -1; } fd = open(start, O_CREAT | O_TRUNC | O_WRONLY, 0664); if (fd == -1) { sprintf(server->send_buf, "553 : Permission deniedrn"); } else { while ((len = recv(server->data_sock, buf, sizeof(buf), 0)) > 0) { write(fd, buf, len); } close(fd); } close(server->data_sock); if (server->d_sock != -1) close(server->d_sock); sprintf(server->send_buf, "226 Transfer complete.rn"); printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); return 0; } static int ftp_server_rest(struct ftp_server *server, const char *cmd) { char *start; start = strstr(cmd, " "); if (!start) return -1; start++; server->ofs = atoi(start); printf("%s", "200 complete.rn"); send(server->c_sock, "200 complete.rn", strlen("200 complete.rn"), 0); return 0; } static int ftp_server_appe(struct ftp_server *server, const char *cmd) { if (server->d_sock == -1) return -1; char *start; start = strstr(cmd, " "); if (!start) return -1; start++; sprintf(server->send_buf, "150 Opening BINARY mode data connection.rn"); printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); int fd; int len; char buf[256] = {}; if (-1 == ftp_server_get_dsock(server)) { sprintf(server->send_buf, "553 net errrn"); printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); if (server->d_sock != -1) close(server->d_sock); return -1; } fd = open(start, O_APPEND | O_WRONLY); if (fd == -1) { sprintf(server->send_buf, "553 : Permission deniedrn"); } else { while ((len = recv(server->data_sock, buf, sizeof(buf), 0)) > 0) { write(fd, buf, len); } close(fd); } close(server->data_sock); if (server->d_sock != -1) close(server->d_sock); sprintf(server->send_buf, "226 Transfer complete.rn"); printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); return 0; } static int ftp_server_retr(struct ftp_server *server, const char *cmd) { if (server->d_sock == -1) return -1; char *start; start = strstr(cmd, " "); if (!start) return -1; start++; sprintf(server->send_buf, "150 Opening BINARY mode data connection for.rn"); printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); int fd; int len, ret; char buf[256] = {}; if (-1 == ftp_server_get_dsock(server)) { sprintf(server->send_buf, "553 net errrn"); printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); if (server->d_sock != -1) close(server->d_sock); return -1; } fd = open(start, O_RDONLY); if (fd == -1) { sprintf(server->send_buf, "553 : Permission deniedrn"); } else { lseek(fd, server->ofs, SEEK_SET); while ((len = read(fd, buf, sizeof(buf))) > 0) { ret = send(server->data_sock, buf, len, 0); if (ret < 0) break; } server->ofs = 0; close(fd); } close(server->data_sock); if (server->d_sock != -1) close(server->d_sock); sprintf(server->send_buf, "226 Transfer complete.rn"); printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); return 0; } static int ftp_server_size(struct ftp_server *server, const char *cmd) { char *start; int ret; struct stat info; start = strstr(cmd, " "); if (!start) return -1; start++; ret = stat(start, &info); if (ret) { sprintf(server->send_buf, "550 : not a plain file.rn"); } else { sprintf(server->send_buf, "213 %urn", (unsigned int)info.st_size); } printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); return 0; } static int ftp_server_cwd(struct ftp_server *server, const char *cmd) { char *start; int ret; start = strstr(cmd, " "); if (!start) return -1; start++; ret = chdir(start); if (ret == -1) { sprintf(server->send_buf, "550 : No such file or directory.rn"); } else { sprintf(server->send_buf, "250 CWD command successful.rn"); } printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); return 0; } static int ftp_server_cdup(struct ftp_server *server, const char *cmd) { int ret; ret = chdir(".."); if (ret == -1) { sprintf(server->send_buf, "550 CDUP No such file or directory.rn"); } else { sprintf(server->send_buf, "250 CDUP command successful.rn"); } printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); return 0; } static int ftp_server_mkd(struct ftp_server *server, const char *cmd) { char *start; int ret; start = strstr(cmd, " "); if (!start) return -1; start++; ret = access(start, F_OK); if (!ret) { sprintf(server->send_buf, "550 : File exists.rn"); } else { ret = mkdir(start, 0775); if (ret == -1) { sprintf(server->send_buf, "550 : Permission denied.rn"); } else { sprintf(server->send_buf, "257 MKD command successful.rn"); } } printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); return 0; } static int ftp_server_rmd(struct ftp_server *server, const char *cmd) { char *start; int ret; start = strstr(cmd, " "); if (!start) return -1; start++; ret = access(start, F_OK); if (ret) { sprintf(server->send_buf, "550 : No such file or directory.rn"); } else { ret = rmdir(start); if (ret == -1) { sprintf(server->send_buf, "550 : Permission denied.rn"); } else { sprintf(server->send_buf, "250 RMD command successful.rn"); } } printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); return 0; } static int ftp_server_dele(struct ftp_server *server, const char *cmd) { char *start; int ret; start = strstr(cmd, " "); if (!start) return -1; start++; ret = access(start, F_OK); if (ret) { sprintf(server->send_buf, "550 : No such file or directory.rn"); } else { ret = remove(start); if (ret == -1) { sprintf(server->send_buf, "550 : Permission denied.rn"); } else { sprintf(server->send_buf, "250 DELE command successful.rn"); } } printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); return 0; } static int ftp_server_utf8(struct ftp_server *server, const char *cmd) { sprintf(server->send_buf, "200 No such file or directory.rn"); printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); return 0; } static int ftp_server_feat(struct ftp_server *server, const char *cmd) { sprintf(server->send_buf, "211-Featuresrn SIZE rn UTF8rn211 Endrn"); printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); return 0; } static int ftp_server_site_chmod(struct ftp_server *server, const char *cmd) { char name[256] = {}; mode_t mode; char *start; start = strstr(cmd, " "); if (!start) return -1; start = strstr(++start, " "); if (!start) return -1; start++; printf("%sn", start); sscanf(start, "%o%s", (int *)&mode, name); printf("%d %sn", (int)mode, name); chmod(name, mode); sprintf(server->send_buf, "200 ok.rn"); printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); return 0; } static int ftp_server_rnfr(struct ftp_server *server, const char *cmd) { char *start; int ret; start = strstr(cmd, " "); if (!start) return -1; start++; ret = access(start, F_OK); if (ret) { sprintf(server->send_buf, "550 : No such file or directory.rn"); } else { strcpy(server->rename, start); sprintf(server->send_buf, "200 command successful.rn"); } printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); return 0; } static int ftp_server_rnto(struct ftp_server *server, const char *cmd) { char *start; int ret; start = strstr(cmd, " "); if (!start) return -1; start++; ret = rename(server->rename, start); if (ret) { sprintf(server->send_buf, "550 : rename err.rn"); } else { sprintf(server->send_buf, "200 command successful.rn"); } printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); return 0; } static int ftp_server_quit(struct ftp_server *server, const char *cmd) { char buf[100] = {}; struct sockaddr_in peeraddr; socklen_t peer_len = 0; peer_len = sizeof(peeraddr); getpeername(server->c_sock, (struct sockaddr*)&peeraddr, &peer_len); snprintf(buf, sizeof(buf), "client %s %d close.rn", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port)); printf("%s",buf); send(server->c_sock, buf, strlen(buf),0); close(server->c_sock); return 0; } static int ftp_server_nocmd(struct ftp_server *server, const char *cmd) { sprintf(server->send_buf, "500 : command not understood.rn"); printf("%s", server->send_buf); send(server->c_sock, server->send_buf, strlen(server->send_buf), 0); return 0; } struct cmd_t { const char *cmd; int (*func)(struct ftp_server *ftp, const char *cmd); }; static struct cmd_t cmd_table[] = { [0] = { .cmd = "not found cmd", .func = ftp_server_nocmd }, [1] = { .cmd = "PASS", .func = ftp_server_pass }, [2] = { .cmd = "SYST", .func = ftp_server_syst }, [3] = { .cmd = "USER", .func = ftp_server_user }, [4] = { .cmd = "PWD", .func = ftp_server_pwd }, [5] = { .cmd = "TYPE", .func = ftp_server_type }, [6] = { .cmd = "PASV", .func = ftp_server_pasv }, [7] = { .cmd = "LIST", .func = ftp_server_list }, [8] = { .cmd = "CWD", .func = ftp_server_cwd }, [9] = { .cmd = "CDUP", .func = ftp_server_cdup }, [10] = { .cmd = "MKD", .func = ftp_server_mkd }, [11] = { .cmd = "RMD", .func = ftp_server_rmd }, [12] = { .cmd = "DELE", .func = ftp_server_dele }, [13] = { .cmd = "STOR", .func = ftp_server_stor }, [14] = { .cmd = "RETR", .func = ftp_server_retr }, [15] = { .cmd = "SIZE", .func = ftp_server_size }, [16] = { .cmd = "UTF8", .func = ftp_server_utf8 }, [17] = { .cmd = "FEAT", .func = ftp_server_feat }, [18] = { .cmd = "SITE CHMOD", .func = ftp_server_site_chmod }, [19] = { .cmd = "RNTO", .func = ftp_server_rnto }, [20] = { .cmd = "RNFR", .func = ftp_server_rnfr }, [21] = { .cmd = "APPE", .func = ftp_server_appe }, [22] = { .cmd = "REST", .func = ftp_server_rest }, [23] = { .cmd = "PORT", .func = ftp_server_port }, [24] = { .cmd = "QUIT", .func = ftp_server_quit } }; struct cmd_t *find_cmd(char *cmd) { int i, len; char *end, *pos = NULL, *p; end = strstr(cmd, "rn"); if (!end) end = strstr(cmd, "n"); if (!end) return NULL; *end = 0; p = my_split(cmd, " ", &len, &pos); for (i = 0; i < sizeof(cmd_table) / sizeof(cmd_table[0]); i++) { if (!strncmp(cmd_table[i].cmd, p, strlen(cmd_table[i].cmd))) { return cmd_table + i; } } return cmd_table; }; static void *pthread_func(void *data) { int ret; char buf[256] = {}; struct cmd_t *cmd; struct ftp_server *server = data; send(server->c_sock, "220 ftprn", strlen("220 ftprn"), 0); while (1) { ret = recv(server->c_sock, buf, sizeof(buf) - 1, 0); printf("%s", buf); if (ret <= 0) break; cmd = find_cmd(buf); if (cmd != cmd_table + 1 && cmd != cmd_table + 3) { if (server->islogin != 2) continue; } if (cmd) { printf("CMD:%s, buf=%sn", cmd->cmd, buf); cmd->func(server, buf); } memset(buf, 0, sizeof(buf)); } printf("%s exitn", __func__); close(server->c_sock); free(server); return NULL; } int ftp_start(int sock, const char *local_addr, const char *user, const char *pass) { struct ftp_server *server = malloc(sizeof(struct ftp_server)); memset(server, 0, sizeof(struct ftp_server)); strcpy(server->user, user); strcpy(server->pass, pass); server->c_sock = sock; server->d_addr = inet_addr(local_addr); struct timeval timeout = {300, 0}; setsockopt(sock , SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(struct timeval)); setsockopt(sock , SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval)); //pthread_create(&pid, NULL, pthread_func, (void *)server); pthread_func((void *)server); return 0; } static void thread_exit_handler(int sig) { printf("this signal is %d n", sig); pthread_exit(0); } void *server_pthread(void *data) { struct data *p = data; int lis_sock = p->sock; int client; struct sockaddr_in cli_addr; socklen_t len; len = sizeof(cli_addr); printf("enter server_pthreadn"); //pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old); while (1) { client = accept(lis_sock, (struct sockaddr *)&cli_addr, &len); if (client == -1) break; int i; for (i = 0; i < sizeof(pid_arr) / sizeof(pid_arr[0]); i++) { if (!pid_arr[i]) { pid_arr[i] = fork(); break; } } if (i == sizeof(pid_arr) / sizeof(pid_arr[0])) { close(client); continue; } if (pid_arr[i] < 0) { close(client); pid_arr[i] = 0; continue; } else if (pid_arr[i] == 0) { printf("i=%d, connect client,cli_addr.port=%d,addr=%sn",i, ntohs(cli_addr.sin_port), inet_ntoa(cli_addr.sin_addr)); ftp_start(client, p->ip, p->user, p->pass); close(lis_sock); exit(0); } else if (pid_arr[i] > 0) { close(client); } } close(lis_sock); return NULL; } void server_init(struct data *data) { memset(data, 0, sizeof(struct data)); data->fp = fopen("./ftp.dat", "rb+"); if (!data->fp) { data->fp = fopen("./ftp.dat", "wb+"); if (data->fp) { fprintf(data->fp, "%hd %s %s %sn", 2121, "ftp", "1234", "/"); } //data->port = 2121; data->port = 2121; strcpy(data->user, "ftp"); strcpy(data->pass, "1234"); strcpy(data->url, "/"); return; } fscanf(data->fp, "%d %s %s %s", (int*)(&data->port), data->user, data->pass, data->url); } void server_set(struct data *data, const char *addr, short port, const char *user, const char *pass, const char *rooturl) { //strcpy(data->ip, addr); //strcpy(data->user, user); //strcpy(data->pass, pass); //strcpy(data->url, rooturl); memcpy(data->ip, addr, strlen(addr)); memcpy(data->user, user, strlen(user)); memcpy(data->pass, pass, strlen(pass)); memcpy(data->url, rooturl, strlen(rooturl)); data->port = port; printf("server ip=%s, port=%hd,user=%s,pass=%s,url=%sn", data->ip, data->port, data->user, data->pass,data->url); } int server_start(struct data *data) { int lis_sock, ret; struct sockaddr_in lis_addr; if (chroot(data->url) == -1) { ret = chdir(data->url); } else { ret = chdir("/"); } if (ret == -1) return ret; lis_sock = socket(AF_INET, SOCK_STREAM, 0); if (lis_sock == -1) { perror("socket"); return -1; } lis_addr.sin_addr.s_addr = inet_addr(data->ip); lis_addr.sin_port = htons(data->port); lis_addr.sin_family = AF_INET; printf("lis_addr.sin_port=%d,%hd, ip=%sn", lis_addr.sin_port, data->port, inet_ntoa(lis_addr.sin_addr)); int opt=SO_REUSEADDR; setsockopt(lis_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); ret = bind(lis_sock, (struct sockaddr*)&lis_addr, sizeof(lis_addr)); if (ret == -1) { perror("bind"); printf("failedn"); return -1; } printf("startedn"); listen(lis_sock, 10); //printf("=======1n"); data->sock = lis_sock; //printf("=======1n"); signal(SIGCHLD, sig_fun); //printf("=======2n"); signal(SIGQUIT, thread_exit_handler); //printf("=======1n"); pthread_create(&data->pid, NULL, server_pthread, (void *)data); if (data->fp) { fseek(data->fp, 0, 0); fprintf(data->fp, "%hd %s %s %sn", data->port, data->user, data->pass, data->url); } pthread_join(data->pid,NULL); printf("====rerurn 0n"); return 0; } void server_stop(struct data *data) { if (data->fp) { fclose(data->fp); data->fp = NULL; } close_tenor(); if (data->pid) { //pthread_cancel(data->pid); pthread_kill(data->pid, SIGQUIT); shutdown(data->sock, SHUT_RDWR); close(data->sock); data->sock = 0; data->pid = 0; } } void default_server_init(struct data *data) { char buf[100]= {"127.0.0.1"}; server_init(data); memcpy(data->ip, buf, sizeof(buf)); printf("default server ip=%s, port=%hd,user=%s,pass=%s,url=%sn", data->ip, data->port, data->user, data->pass,data->url); return; } int main(int argc, char **argv) { struct data ser_data; char buf[100]= {"127.0.0.1"}; printf("use: ./ftpserver [ip] [port] [user] [pass]rn"); printf("argc = %dn",argc); memset(&ser_data, 0, sizeof(ser_data)); if(2 == argc) server_set(&ser_data, argv[1], 21, "ftp", "1234", "."); else if(3 == argc) server_set(&ser_data, argv[1], atoi(argv[2]), "ftp", "1234", "."); else if(5 == argc) server_set(&ser_data, argv[1], atoi(argv[2]), argv[3], argv[4] , "."); else default_server_init(&ser_data); server_start(&ser_data); return 1; }
2. Makefile
all:
gcc -o ftpserver ftp_server.c -lpthread
3. 运行
打开一个控制台作为服务器:
./ftpserver
(默认127.0.0.1 21)
打开另一个控制台作为客户端(如果客户端软件没有安装,可apt-get install 安装,网上可以查到,同时,如果系统有ftpserver,请关闭):
主动模式:
ftp 127.0.0.1 21
被动模式
ftp -p 127.0.0.1 21



