这是计算机网络课程设计的作品,简单实现了FTP客户端。
用winsock2头文件。算是socket编程的学习实践。
所有代码在vc6.0下调试通过。
/* *本程序参考rfc959标准。能与遵守此标准的服务器进行信息交互。仅限于windows系统。 */ #include < stdio.h > #include < string.h > #include < stdlib.h >/*system()*/ #include < winsock2.h > #pragma comment(lib, "ws2_32.lib") #define ONUM 512 #define MNUM 512 #define FNUM 512 #define ptstruct host { char ip[20]; unsigned short port; }; SOCKET ts; fd_set readfds; struct timeval timeval; struct host host; char renum[4]; char ordertemp[ONUM]; char order[ONUM]; char ordercp[ONUM]; char mess[MNUM]; char file[FNUM]; char setpath[FNUM]; char setpathf[FNUM]; int i, door, r, sys, seti;/*i for;door switch;r receive num;sys system state;set set state*/ char * p;/*strtok*/ int printmess(); void input(char ordertemp[]); int ftp(); int user(); int pass(); int command(); int list(); SOCKET createDataSocket(); int set(); int retr(); int stor(); int stor() { char filename[256]; SOCKET ds; int wi; int r2, r3, r4, bsnum, brnum; FILE * fp = NULL; set(); memset(filename, '\0', 256); memset(order, '\0', ONUM); for (i = 5; i <= 200 && ordercp[i] != '\0'; i++) { order[i - 5] = ordercp[i]; } strcpy(filename, setpathf); strcat(filename, "\\\\"); strcat(filename, order); memset(order, '\0', ONUM); strcpy(order, "type i\r\n"); /*type i 二进制 type a ASCII*/ send(ts, order, strlen(order), 0); switch (printmess()) { case 421: closesocket(ts); sys = 0; return 421; case 530: closesocket(ts); sys = 0; return - 1; case 500: case 501: case 504: case 226: return - 1; case 200: break; default: return - 1; } ds = createDataSocket(); if (ds ==- 1) { return - 1; } strcat(ordercp, "\r\n"); send(ts, ordercp, strlen(ordercp), 0); switch (printmess()) { case 421: closesocket(ds); closesocket(ts); sys = 0; return 421; case 532: case 530: closesocket(ds); closesocket(ts); sys = 0; return - 1; case 450: case 452: case 553: case 500: case 501: closesocket(ds); return - 1; case 125: case 150: break; default: closesocket(ds); return - 1; } fp = fopen(filename, "rb"); if (!fp) { printf("read file fail!\n"); closesocket(ds); return - 1; } r2 = 0; r3 = 0; r4 = 0; bsnum = 0; brnum = 0; wi = 1; while (wi) { memset(file, '\0', FNUM); r = fread(file, sizeof(char), FNUM, fp); if (r == 0) { closesocket(ds); wi = 0; break; } brnum = brnum + r; r3 = r; printf("read %8d bytes! have read %16d bytes!\r", r, brnum); do { r2 = send(ds, file, r3, 0); if (r2 == SOCKET_ERROR) { printf("send file error!"); closesocket(ds); return - 1; } bsnum = bsnum + r2; r3 = r3 - r2; printf("send %8d bytes! have sended %16d bytes!\r", r2, bsnum); } while (brnum > bsnum); }/*while*/ printf("\n"); switch (printmess()) { case 425: case 426: case 451: case 551: case 552: closesocket(ds); fclose(fp); return - 1; case 250: case 226: fclose(fp); return 0; default: return 0; } }/*stor*/ int retr() { char filename[256]; unsigned long fsize, wfsize; int r2, wi; SOCKET ds; FILE * fp = NULL; memset(filename, '\0', 256); memset(order, '\0', ONUM); for (i = 5; i <= 200 && ordercp[i] != '\0'; i++) { order[i - 5] = ordercp[i]; } strcpy(filename, setpathf); strcat(filename, "\\\\"); strcat(filename, order); ds = createDataSocket(); if (ds ==- 1) { return - 1; } memset(order, '\0', ONUM); strcpy(order, "type i\r\n");/*type i 二进制 type a ASCII*/ send(ts, order, strlen(order), 0); switch (printmess()) { case 421: closesocket(ds); closesocket(ts); sys = 0; return 421; case 530: closesocket(ds); closesocket(ts); sys = 0; return - 1; case 500: case 501: case 504: case 226: closesocket(ds); return - 1; case 200: break; default: closesocket(ds); return - 1; } strcat(ordercp, "\r\n"); send(ts, ordercp, strlen(ordercp), 0); switch (printmess()) { case 421: closesocket(ds); closesocket(ts); sys = 0; return 421; case 530: closesocket(ds); closesocket(ts); sys = 0; return - 1; case 450: case 500: case 501: case 550: closesocket(ds); return - 1; case 125: case 150: break; default: closesocket(ds); return - 1; } set(); system(setpath); fp = fopen(filename, "wb"); if (!fp) { printf("create file fail!\n"); closesocket(ds); printmess(); return - 1; } wi = 1; fsize = 0; wfsize = 0; while (wi) { memset(file, '\0', FNUM); r = recv(ds, file, FNUM, 0); if (r == SOCKET_ERROR) { printf("file recv error!\n"); closesocket(ds); fclose(fp); return - 1; } fsize = fsize + r; if (r == 0) { wi = 0; break; } printf("receive %8d bytes! have received %16d bytes!\r", r, fsize); r2 = fwrite(file, sizeof(char), r, fp); // fflush(fp);/*这里是关键*/ wfsize = wfsize + r2; printf("write %8d bytes!have written %20d bytes!\r", r2, wfsize); }/*while*/ printf("\n"); fflush(fp);/*这里是关键*/ switch (printmess()) { case 425: case 426: case 451: closesocket(ds); fclose(fp); return - 1; case 250: case 226: closesocket(ds); wi = 1; while (wi) { if (fclose(fp) == 0) { wi = 0; } return 0; default: closesocket(ds); fclose(fp); return 0;; } } }/*retr()*/ int set() { int n, m; n = 3; m = 0; if (strcmp(order, "set") != 0 && seti == 1) { return 1; } else if (strcmp(order, "set") != 0 && seti == 0) { memset(setpath, '\0', FNUM); memset(setpathf, '\0', FNUM); strcpy(setpath, "md d:\\rhFTPdir"); strcpy(setpathf, "d:\\\\rhFTPdir"); return 2; } memset(setpath, '\0', FNUM); memset(setpathf, '\0', FNUM); memset(order, '\0', ONUM); if (ordercp[5] != ':') { printf("error input!\n"); return - 1; } for (i = 4; i <= 200 && ordercp[i] != '\0'; i++) { order[i - 4] = ordercp[i]; } strcpy(setpath, "md "); for (i = 0; i <= FNUM - 5 && order[i] != '\0'; i++) { if (order[i] == '\\') { strcat(setpath, "\\\\"); n++; strcat(setpathf, "\\\\"); m++; continue; } setpathf[i + m] = order[i]; setpath[i + n] = order[i]; } printf("setpath %s\n", setpath); seti = 1; return 0; }/*set*/ int list() { SOCKET ds; int wi; ds = createDataSocket(); if (ds ==- 1) { return - 1; } strcat(ordercp, "\r\n"); send(ts, ordercp, strlen(ordercp), 0); switch (printmess()) { case 421: closesocket(ds); closesocket(ts); sys = 0; return 421; case 530: closesocket(ds); closesocket(ts); sys = 0; return - 1; case 450: case 500: case 501: case 502: closesocket(ds); return - 1; case 125: case 150: break; default: closesocket(ds); return - 1; } wi = 1; while (wi) { memset(file, '\0', FNUM); r = recv(ds, file, FNUM - 1, 0); if (r == SOCKET_ERROR) { printf("list file recv error!\n"); closesocket(ds); return - 1; } printf("%s", file); if (r == 0) { wi = 0; } } switch (printmess()) { case 425: case 426: case 451: case 226: case 250: closesocket(ds); return 0; default: closesocket(ds); return - 1; } }/*list*/ SOCKET createDataSocket() { char p1[5], p2[5]; unsigned short port; int p1s, p2s; SOCKET ds; struct sockaddr_in server; memset(order, '\0', ONUM); /*pasv*/ strcpy(order, "pasv\r\n"); send(ts, order, strlen(order), 0); r = printmess(); if (r ==- 1 || r != 227) { return - 1; } memset(p1, '\0', 5); memset(p2, '\0', 5); p1s = 0; p2s = 0; for (i = 0, r = 0; i < 200 && mess[i] != '\0'; i++) { if (mess[i] == ',') { r++; continue; } if (r == 4) { p1[p1s] = mess[i]; p1s++; continue; } if (r == 5) { p2[p2s] = mess[i]; p2s++; continue; } } port = atoi(p1) * 256 + atoi(p2); printf("port:%d\n", port); server.sin_family = AF_INET; server.sin_port = htons(port); server.sin_addr.S_un.S_addr = inet_addr(host.ip); ds = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); /*TCP*/ if (ds ==- 1) { printf("Failed socket() in createDataSocket()\n"); return - 1; } r = connect(ds, (struct sockaddr * ) & server, sizeof(server)); if (r == SOCKET_ERROR) { printf("connect error in createDataSocket()!\n"); closesocket(ds); return - 1; } return ds; }/*createDataSocket()*/ int command() { strcat(ordercp, "\r\n"); send(ts, ordercp, strlen(ordercp), 0); switch (printmess()) { case 421: closesocket(ts); sys = 0; return 421; case 221: closesocket(ts); sys = 0; return 221; case 530: closesocket(ts); sys = 0; return 0; case 200: case 250: case 450: case 550: case 500: case 501: case 502: return 0; default: return - 1; } }/*command*/ int pass() { strcat(ordercp, "\r\n"); send(ts, ordercp, strlen(ordercp), 0); switch (printmess()) { case 421: closesocket(ts); sys = 0; return 421; case 530: closesocket(ts); sys = 0; return 0; case 500: case 501: case 503: case 202: return 0; case 332: sys = 1; return 0; case 230: sys = 3; return 0; default: return - 1; } }/*pass*/ int user() { if (ordercp[5] == '-') { strcat(order, " anonymous\r\n"); send(ts, order, strlen(order), 0); } else { strcat(ordercp, "\r\n"); send(ts, ordercp, strlen(ordercp), 0); } switch (printmess()) { case 421: closesocket(ts); sys = 0; return 421; case 530: closesocket(ts); sys = 0; return 0; case 230: sys = 3; return 0; case 500: case 501: case 332: return 0; case 331: sys = 2; return 0; default: return - 1; } }/*user*/ int ftp() { WSADATA wsaData; struct sockaddr_in serveraddr; if (sys != 0) { printf("please bye first!\n"); return 0; } WSAStartup(MAKEWORD(2, 2), & wsaData); /*建立与Socket库绑定*/ ts = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); /*TCP*/ if (ts ==- 1) { printf("Failed socket()\n"); WSACleanup(); return - 1; } memset(host.ip, '\0', 20); p = strtok(NULL, " "); strcpy(host.ip, p); p = strtok(NULL, " "); if (p == NULL) { host.port = 21; } else { host.port = atoi(p); } serveraddr.sin_family = AF_INET; /*主机地址标识*/ serveraddr.sin_port = htons(host.port); /*port htons 16*/ serveraddr.sin_addr.S_un.S_addr = inet_addr(host.ip); /*ip*/ r = connect(ts, (struct sockaddr * ) & serveraddr, sizeof(serveraddr)); /*发送连接请求*/ if (r == SOCKET_ERROR) { printf("connect error!\n"); return - 1; } switch (printmess()) { case 220: sys = 1; return 0; case 120: while (printmess() == 220) { sys = 1; return 0; } case 421: closesocket(ts); sys = 0; return 421; case - 1: return - 1; default: return - 1; } }/*ftp*/ int printmess() { int p, n, wi; p = 0; n = 0; wi = 1; memset(renum, '\0', 4); FD_ZERO(&readfds); /*select*/ FD_SET(ts, & readfds); r = select(0, & readfds, NULL, NULL, & timeval); while (r > 0 && FD_ISSET(ts, & readfds) && wi == 1) { memset(mess, '\0', MNUM); r = recv(ts, mess, MNUM - 1, 0); if (r == SOCKET_ERROR) { printf("printmess recv error!\n"); return - 1; } if (p == 0) { strncpy(renum, mess, 4); n = atoi(renum); p = 1; } printf("%s", mess); FD_ZERO(&readfds); /*select*/ FD_SET(ts, & readfds); r = select(0, & readfds, NULL, NULL, & timeval); if (r == 0) { wi = 0; } } return n; }/*printmess()*/ void input(char ordertemp[]) { for (i = 0; i < ONUM; i++) { ordertemp[i] = getchar(); if (ordertemp[i] == 10) { ordertemp[i] = '\0'; break; } /*10 enter*/ } if (ordertemp[0] != '\0') { strcpy(ordercp, ordertemp); p = NULL; p = strtok(ordertemp, " "); strcpy(order, p); strlwr(order); } }/*input*/ int main() { int wi; seti = 0; timeval.tv_sec = 0; /*5000ms 避免死锁*/ timeval.tv_usec = 500000; printf("** Welcome to use RedHaw FTPclient! **\n"); sys = 0; /*0-初始 1-接收user 2-接收pass 3-接收其他command*/ wi = 1; while (wi) { memset(ordertemp, '\0', ONUM); memset(order, '\0', ONUM); memset(ordercp, '\0', ONUM); switch (sys) { case 0: printf("+ ftp <host-ip> [port] + exit +\n"); break; case 1: printf("+ user <username> Tip:\" \'-\' for anonymous \" +\n"); break; case 2: printf("+ pass <password> Tip:\" \'-\' for anonymous \" +\n"); break; default: printf("+ help|list|cdup|cwd <dir>|mkd <>|rmd <>|set <dir> +\n"); printf("+ user|quit|exit|retr <down>|stor <up>|dele <file> +\n"); } printf("rhFTP>"); input(ordertemp); if (ordertemp[0] == '\0') { continue; } if (strcmp(order, "ftp") == 0 && sys == 0) { door = 1; } /*1 ftp */ else if (strcmp(order, "user") == 0 && (sys == 1 || sys == 3)) door = 2; /*2 user*/ else if (strcmp(order, "pass") == 0 && sys == 2) door = 3; /*3 pass*/ else if (strcmp(order, "quit") == 0 && sys == 3) door = 4; /*4 quit*/ else if (strcmp(order, "exit") == 0 && (sys == 0 || sys == 3)) door = 5; /*5 exit*/ else if (strcmp(order, "list") == 0 && sys == 3) door = 6; /*6 list*/ else if (strcmp(order, "cwd") == 0 && sys == 3) door = 7; /*7 cwd */ else if (strcmp(order, "dele") == 0 && sys == 3) door = 8; /*8 dele*/ else if (strcmp(order, "retr") == 0 && sys == 3) door = 9; /*9 retr*/ else if (strcmp(order, "set") == 0 && sys == 3) door = 10; /*10 set */ else if (strcmp(order, "stor") == 0 && sys == 3) door = 11; /*11 stor*/ else if (strcmp(order, "cdup") == 0 && sys == 3) door = 12; /*12 cdup*/ else if (strcmp(order, "help") == 0 && sys == 3) door = 13; /*13 help*/ else if (strcmp(order, "mkd") == 0 && sys == 3) door = 14; /*14 mkd */ else if (strcmp(order, "rmd") == 0 && sys == 3) door = 15; /*15 rmd */ else door = 0; switch (door) { case 0: printf("Disallowed command!\n"); break; case 1: r = ftp(); break; case 2: r = user(); break; case 3: r = pass(); break; case 4: r = command(); break; case 5: if (sys == 3) { memset(ordercp, '\0', ONUM); strcpy(ordercp, "quit\r\n"); command(); closesocket(ts); } wi = 0; break; case 13: case 6: r = list(); break; case 12: case 14: case 15: case 7: case 8: r = command(); break; case 9: r = retr(); break; case 10: r = set(); break; case 11: r = stor(); break; default: wi = 0; break; } /*switch(door)*/ } /*while(wi)*/ WSACleanup(); return 0; } /*main*/
- by 一个农夫 -