socket编程FTP客户端demo
这是计算机网络课程设计的作品,简单实现了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 一个农夫 -
浙公网安备 33010602011771号