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 一个农夫 -

原文地址:https://www.cnblogs.com/afarmer/p/1610944.html