C++ 简单FTP客户端软件开发

题目

简单FTP客户端软件开发(100分)网络环境中的一项基本应用就是将文件从一台计算机中复制到另一台可能相距很远的计算机中。而文件传送协议FTP是因特网上使用得最广泛的文件传送协议。FTP使用客户服务器方式。
设计要求:
1)以命令行形式运行
2)该FTP客户端程序具有以下基本功能:能完成FTP链接的打开和关闭操作;能执行文件的上传和下载;能完成目录的创建、删除等有关操作。
3)设计中加入新的功能:登录,进入上级或下级目录
要求可以传输简单的文本文件。

设计思路

1、分为两个端口,指令交流端口,数据交换端口
2、指令端口连接后一直保持通信,直到获得退出信号
3、数据交换端口在获得相关指令后重新建立连接

使用方法

1、分别创建两个C++项目
2、复制代码进入即可
3、若两个都在本地,使用本地回环测试IP,127.0.0.1
4、登录的部分在客户端中被注释掉了没有开启

Tips:

目前登录以及help部分仍有两个小bug,系由端口的命令断开以及连接部分引起,交由读者自己研究,若不想管可以不使用这两个功能

服务端——>Server

#include "Winsock2.h"
#include "windows.h"
#include <iostream>
#include <string>
using namespace std;

#define RECV_PORT 3312	//接收端口
#define SEND_PORT 4302	//发送端口
#define DATA_PORT 3313  //数据发送端口
#pragma comment(lib, "wsock32.lib")

SOCKET sockClient, sockServer;
SOCKET dataClient, dataServer;

sockaddr_in dataAddr;
sockaddr_in severAddr;//服务器地址
sockaddr_in ClientAddr;//客户端地址
sockaddr_in dataClientAddr;//数据地址

int addrLen;		//地址长度
char fileName[20];	//文件名
char order[20];		//命令
char rbuff[1024];	//接收缓冲区
char sbuff[1024];	//发送缓冲区

char namePassword[1024] = "user 123456";	//用户名和密码

//***************函数声明***************

DWORD startSock();
DWORD createSocket();
int sendFileRecord(SOCKET datatcps, WIN32_FIND_DATA *pfd);
int sendFileList(SOCKET datatcps);
int sendFile(SOCKET datatcps, FILE* file);
DWORD connectProcess();

//***************函数声明***************
DWORD startSock() {//初始化winsock
	WSADATA WSAData;
	if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0) {
		cout << "初始化失败" << endl;
		return -1;
	}
	return 1;
}
DWORD createSocket() {
	sockClient = socket(AF_INET, SOCK_STREAM, 0);
    dataClient = socket(AF_INET, SOCK_STREAM, 0);
	if (sockClient == SOCKET_ERROR||dataClient == SOCKET_ERROR) {
		cout << "创建失败" << endl;
		WSACleanup();
		return -1;
	}
    dataAddr.sin_family = AF_INET;
	severAddr.sin_family = AF_INET;
    dataAddr.sin_addr.s_addr = htonl(INADDR_ANY);//监听任意地址
    dataAddr.sin_port = htons(DATA_PORT);
	severAddr.sin_addr.s_addr = htonl(INADDR_ANY);//监听任意地址
    //cout<<htonl(INADDR_ANY)<<endl;
	severAddr.sin_port = htons(RECV_PORT);
	if (bind(sockClient, (struct sockaddr FAR*)&severAddr, sizeof(severAddr)) == SOCKET_ERROR||bind(dataClient, (struct sockaddr FAR*)&dataAddr, sizeof(dataAddr)) == SOCKET_ERROR) {
        //bind函数用于将socket和地址结构绑定==
		cout << "绑定失败" << endl;
		return -1;
	}
	return 1;
}

DWORD mkdir(char fileName[]){
    char path[1000];
    GetCurrentDirectory(sizeof(path), path);//找到当前进程的当前目录

    strcat(path,"\\");
    strcat(path,fileName);
    cout<<path<<endl;
    bool flag = CreateDirectory(path,NULL);
    if (flag)
        cout<<"创建文件:"<<fileName<<"成功"<<endl;
    else
        cout<<"创建文件:"<<fileName<<"失败"<<endl;

}

DWORD delFile(char fileName[]){
    char path[1000];
    GetCurrentDirectory(sizeof(path), path);//找到当前进程的当前目录

    strcat(path,"\\");
    strcat(path,fileName);
   // cout<<path<<endl;
    bool flag = RemoveDirectory(path);
    if (flag)
        cout<<"删除文件:"<<fileName<<"成功"<<endl;
    else
        cout<<"删除文件:"<<fileName<<"失败"<<endl;
}
DWORD connectProcess() {
	addrLen = sizeof(ClientAddr);//addrLen是对象地址的长度

	if (listen(sockClient, 10) < 0|| listen(dataClient, 10)<0) {//让套接字进入被动监听状态,参数2为请求队列的最大长度
		cout << "监听失败" << endl;
		return -1;
	}
	cout << "服务器正在监听中…" << endl;
	while (1) {
		//accept取出队列头部的连接请求
		//sockclient是处于监听的套接字
		//ClientAddr 是监听的对象地址

		sockServer = accept(sockClient, (struct sockaddr FAR*)&ClientAddr, &addrLen);
		while (1) {

			memset(rbuff, 0, sizeof(rbuff));
			memset(sbuff, 0, sizeof(sbuff));
			if (recv(sockServer, rbuff, sizeof(rbuff), 0) <= 0) {
                continue;
			}
			cout << endl << "获取并执行的命令:" << rbuff << endl;
			if (strncmp(rbuff, "get", 3) == 0) {//将文件发给客户端
				strcpy(fileName, rbuff + 4);
				FILE* file;//定义一个文件访问指针
				//处理下载文件请求
				file = fopen(fileName, "rb");//二进制打开文件,只允许读
				if (file) {
					sprintf(sbuff, "get %s", fileName);
					if (!send(sockServer, sbuff, sizeof(sbuff), 0)) {
                        cout<<"发送失败"<<endl;
						fclose(file);
						return 0;
					}
					else {//创建额外数据连接传送数据
						if (!sendFile(dataClient, file)) {
							return 0;
						}
						fclose(file);
					}
				}else {
					strcpy(sbuff, "无法打开文件\n");
                    cout<<"无法打开文件"<<endl;
					if (!send(sockServer, sbuff, sizeof(sbuff), 0)) {
						return 0;
					}
				}
			}//get
			else if (strncmp(rbuff, "put", 3) == 0) {//从客户端上传上来文件

                cout<<"debug1"<<endl;
				FILE* fd;
				int cnt;
				strcpy(fileName, rbuff + 4);
				fd = fopen(fileName, "wb");

				if (fd == NULL) {
					cout << "无法打开文件" << fileName << endl;
					return 0;
				}
				sprintf(sbuff, "put %s", fileName);
				if (!send(sockServer, sbuff, sizeof(sbuff), 0)) {
					fclose(fd);
					return 0;
				}
				memset(sbuff, '\0', sizeof(rbuff));
                int dataAddLen = sizeof (dataClientAddr);
                dataServer = accept(dataClient, (struct sockaddr FAR*)&dataClientAddr, &dataAddLen);
				while ((cnt = recv(dataServer, rbuff, sizeof(rbuff), 0)) > 0) {
					fwrite(rbuff, sizeof(char), cnt, fd);//把cnt个数据长度为char的数据从rbuff输入到fd指向的文件
				}
				cout << "成功获得文件" << fileName << endl;
                closesocket(dataServer);
				fclose(fd);
			}//put
			else if (strncmp(rbuff, "pwd", 3) == 0) {
				char path[1000];
				GetCurrentDirectory(sizeof(path), path);//找到当前进程的当前目录
				strcpy(sbuff, path);
				send(sockServer, sbuff, sizeof(sbuff), 0);
			}//pwd
			else if (strncmp(rbuff, "ls", 2) == 0) {
				strcpy(sbuff, rbuff);
				send(sockServer, sbuff, sizeof(sbuff), 0);
				sendFileList(dataClient);
			}//dir
            else if(strncmp(rbuff, "mkdir", 5)==0){
                strcpy(fileName, rbuff + 6);
                strcpy(sbuff,rbuff);
                send(sockServer, sbuff, sizeof (sbuff),0);//发送回信息
                mkdir(fileName);
            }//mkdir
            else if(strncmp(rbuff,"del", 3)==0){
                strcpy(fileName, rbuff + 4);//获得要删的文件名
                strcpy(sbuff,rbuff);
                send(sockServer, sbuff, sizeof (sbuff),0);//发送回信息
                delFile(fileName);
            }//del
			else if (strncmp(rbuff, "cd", 2) == 0) {
				strcpy(fileName, rbuff + 3);
				strcpy(sbuff, rbuff);
				send(sockServer, sbuff, sizeof(sbuff), 0);
                char path[1000];
                GetCurrentDirectory(sizeof(path), path);//找到当前进程的当前目录
                strcat(path,"\\");
                strcat(path,fileName);
				SetCurrentDirectory(path);//设置当前目录
			}//cd
			else if (strncmp(rbuff, "user", 4) == 0) {
				char tbuff[1024];
				strcpy(tbuff, rbuff + 5);
				strcat(tbuff, " ");
				memset(rbuff, '\0', sizeof(rbuff));
				strcpy(sbuff, "成功获取用户名\0");
				send(sockServer, sbuff, sizeof(sbuff), 0);

				recv(sockServer, rbuff, sizeof(rbuff), 0);
				cout << endl << "获取并执行的命令:" << rbuff << endl;
				strcat(tbuff, rbuff + 5);
				if (strcmp(tbuff, namePassword) == 0) {//验证是否正确并返回数据给客户端
					send(sockServer, "right\0", sizeof(sbuff), 0);
				}else {
					send(sockServer, "wrong\0", sizeof(sbuff), 0);
				}
			}//user pass

		}
        closesocket(sockServer);
	}
}
int sendFile(SOCKET datatcps, FILE* file) {
    int dataAddLen = sizeof (dataClientAddr);
    dataServer = accept(datatcps, (struct sockaddr FAR*)&dataClientAddr, &dataAddLen);
	cout << "正在发送文件…" << endl;
	memset(sbuff, '\0', sizeof(sbuff));
	while(1) {//从文件中循环读取数据并发送至客户端
		int len = fread(sbuff, 1, sizeof(sbuff), file);//把file指针指向的文件中的内容读取到sbuff中
       //cout<<"sbuff内容:"<<sbuff<<endl;
		if (send(dataServer, sbuff, len, 0) == SOCKET_ERROR) {
			cout << "连接失败" << endl;
			closesocket(dataServer);
			return 0;
		}
		if (len < sizeof(sbuff)) {//文件传送结束
			break;
		}
	}
	closesocket(dataServer);
	cout << "发送成功" << endl;
	return 1;
}
int sendFileList(SOCKET datatcps) {
    int dataAddLen = sizeof (dataClientAddr);
    dataServer = accept(datatcps, (struct sockaddr FAR*)&dataClientAddr, &dataAddLen);
	HANDLE hff;								//建立一个线程
	WIN32_FIND_DATA fd;						//搜索文件
	hff = FindFirstFile("*", &fd);			//查找文件来把待操作文件的相关属性读取到WIN32_FIND_DATA结构中去
	if (hff == INVALID_HANDLE_VALUE) {		//发生错误
		const char *errStr = "列出文件列表时发生错误\n";
		cout << *errStr << endl;
		if (send(dataServer, errStr, strlen(errStr), 0) == SOCKET_ERROR) {
			cout << "发送失败" << endl;
		}
		closesocket(dataServer);
		return 0;
	}
	BOOL flag = TRUE;
	while (flag) {//发送文件信息

		if (!sendFileRecord(dataServer, &fd)) {
			closesocket(dataServer);
			return 0;
		}
		flag = FindNextFile(hff, &fd);//查找下一个文件
	}
	closesocket(dataServer);
	return 1;
}
int sendFileRecord(SOCKET datatcps, WIN32_FIND_DATA *pfd) {//发送当前的文件记录
	char fileRecord[MAX_PATH + 32];

	FILETIME ft;						//文件的建立时间
	FileTimeToLocalFileTime(&pfd -> ftLastWriteTime, &ft);//Converts a file time to a local file time.

	SYSTEMTIME lastWriteTime;
	FileTimeToSystemTime(&ft, &lastWriteTime);

	const char *dir = pfd -> dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? "<DIR>" : " ";
	sprintf(fileRecord, "%04d-%02d-%02d %02d:%02d %5s %10d   %-20s\n",
		lastWriteTime.wYear,
		lastWriteTime.wMonth,
		lastWriteTime.wDay,
		lastWriteTime.wHour,
		lastWriteTime.wMinute,
		dir,
		pfd -> nFileSizeLow,
		pfd -> cFileName
	);
	if (send(datatcps, fileRecord, strlen(fileRecord), 0) == SOCKET_ERROR) {
		//通过datatcps接口发送fileRecord数据,成功返回发送的字节数
		cout << "发送失败" << endl;
		return 0;
	}
	return 1;
}
int main(){

	if (startSock() == -1 || createSocket() == -1 || connectProcess() == -1) {
		return -1;
	}
	return 1;
}

客户端——>Client

#include <Winsock.h>
#include <windows.h>
#include <time.h>
#include <stdio.h>
#include <iostream>
using namespace std;

#define RECV_PORT 3312	//接收端口
#define SEND_PORT 4302	//发送端口
#define DATA_PORT 3313  //数据接受端口

#pragma comment(lib, "wsock32.lib")	//加载ws2_32.dll,它是Windows Sockets应用程序接口, 用于支持Internet和网络应用程序。

SOCKET sockClient;		//客户端对象
sockaddr_in serverAddr;	//服务器地址
sockaddr_in dataAddr;
SOCKET dataClient;      //数据对象

char inputIP[20];		//存储输入的服务器IP
char fileName[20];		//文件名
char rbuff[1024];		//接收缓冲区
char sbuff[1024];		//发送缓冲区
bool checkFlag = false;			//标志是否通过登陆

//***********************函数声明***********************
DWORD startSock();							//启动winsock并初始化
DWORD createSocket(SOCKET &mySocket);						//创建socket
DWORD callServer(SOCKET &mySocket,sockaddr_in addr);							//发送连接请求

int command();                             //执行命令
void help();								//菜单
void list(SOCKET &sockfd);					//列出远方当前目录
DWORD sendTCP(char data[]);					//发送要执行的命令至服务端
int user();									//上传用户名
int pass();									//上传密码
int sendFile(SOCKET &datatcps, FILE* file);	//put 传送给远方一个文件
//***********************函数声明***********************


//***********************函数定义***********************
DWORD startSock() { //启动winsock并初始化
    WSADATA WSAData;
    char a[20];
    memset(a, 0, sizeof(a));
    if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0) { //加载winsock版本
        cout << "sock初始化失败" << endl;
        return -1;
    }
    if (strncmp(inputIP, a, sizeof(a)) == 0) {
        cout << "请输入要连接的服务器IP:";
        cin >> inputIP;
    }
    //设置地址结构
    serverAddr.sin_family = AF_INET;					//表明底层是使用的哪种通信协议来递交数据的,AF_INET表示使用 TCP/IPv4 地址族进行通信
    serverAddr.sin_addr.s_addr = inet_addr(inputIP);	//指定服务器IP,十进制转化成二进制IPV4地址
    serverAddr.sin_port = htons(RECV_PORT);				//设置端口号,htons用于将主机字节序改为网络字节序

    dataAddr.sin_family = AF_INET;
    dataAddr.sin_addr.s_addr = inet_addr(inputIP);
    dataAddr.sin_port = htons(DATA_PORT);//数据端口和控制端口不一样

    return 1;
}
DWORD createSocket(SOCKET &mySocket) { //创建socket
    //要使用套接字,首先必须调用socket()函数创建一个套接字描述符,就如同操作文件时,首先得调用fopen()函数打开一个文件。
    mySocket = socket(AF_INET, SOCK_STREAM, 0);//当scoket函数成功调用时返回一个新的SOCKET(Socket Descriptor) //SOCK_STREAM(流式套接字):Tcp连接,提供序列化的、可靠的、双向连接的字节流。支持带外数据传输
    if (mySocket == SOCKET_ERROR) {
        cout << "创建socket失败" << endl;
        WSACleanup();//终止Ws2_32.dll 的使用
        return -1;
    }
    return 1;
}
DWORD callServer(SOCKET &mySocket,sockaddr_in addr) { //发送连接请求
    createSocket(mySocket);
    if (connect(mySocket, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {//connect()创建与指定外部端口的连接
        cout << "连接失败" << endl;
        memset(inputIP, 0, sizeof(inputIP));
        return -1;
    }
    return 1;
}
void help() { //帮助菜单
    cout << "        ___________________________________________  " << endl
         << "       |                FTP帮助菜单                 |   " << endl
         << "       | 1、get 下载文件 [输入格式: get 文件名 ]       |   " << endl
         << "       | 2、put 上传文件 [输入格式:put 文件名]         |   " << endl
         << "       | 3、pwd 显示当前文件夹的绝对路径                |    " << endl
         << "       | 4、ls 显示远方当前目录的文件                 |   " << endl
         << "       | 5、mkdir 新建文件夹 [输入格式:mkdir 文件名]   |   " << endl
         << "       | 6、del 删除文件夹 [输入格式:del 文件名]       |   " << endl
         << "       | 7、cd  改变远方当前目录和路径                 |   " << endl
         << "       |         进入下级目录: cd 路径名              |   " << endl
         << "       |         进入上级目录: c ..                  |   " << endl
         << "       | 8、? 或者 help 进入帮助菜单                  |   " << endl
         << "       | 9、quit 退出FTP                            |   " << endl
         << "       |___________________________________________|    " << endl;
}
DWORD sendTCP(char data[]) { //发送要执行的命令至服务端
    int length = send(sockClient, data, strlen(data), 0);
    if (length <= 0) {
        cout << "发送命令至服务端失败" << endl;
        closesocket(sockClient);//当不使用socket()创建的套接字时,应该调用closesocket()函数将它关闭,就如同调用fclose()函数关闭一个文件,用来进行套接字资源的释放。
        WSACleanup();
        return -1;
    }
    return 1;
}
int sendFile(SOCKET &datatcps, FILE* file) { //put 传送给远方一个文件
    callServer(datatcps,dataAddr);
    cout << "正在传输文件…" << endl;
    memset(sbuff, '\0', sizeof(sbuff));
    while (1) { //从文件中循环读取数据并发送
        int len = fread(sbuff, 1, sizeof(sbuff), file); //fread从file文件读取sizeof(sbuff)长度的数据到sbuff,返回成功读取的数据个数

        if (send(datatcps, sbuff, sizeof(rbuff), 0) == SOCKET_ERROR) {
            cout << "与客户端的连接中断" << endl;
            closesocket(datatcps);
            return 0;
        }
        if (len < sizeof(sbuff)) {
            break;
        }
    }
    closesocket(datatcps);
    cout << "传输完成" << endl;
    return 1;
}
void list(SOCKET &sockfd) { //列出远方当前目录
    callServer(sockfd,dataAddr);
    int nRead;
    memset(sbuff, '\0', sizeof(sbuff));
    while (1) {
        nRead = recv(sockfd, rbuff, sizeof(rbuff), 0);
        //recv通过sockClient套接口接受数据存入rbuff缓冲区,返回接收到的字节数
        if (nRead == SOCKET_ERROR) {
            cout << "读取时发生错误" << endl;
            exit(1);
        }
        if (nRead == 0) { //数据读取结束
            break;
        }
        cout<<"nRead长度"<<nRead<<endl;
        //显示数据
        rbuff[nRead] = '\0';
        cout << rbuff << endl;
    }
    cout<<"读取结束"<<endl;
    closesocket(sockfd);
}
int  user() {
    char operation[10], name[20];		//操作与文件名
    char order[30] = "\0";				//输入的命令
    char buff[80];						//用来存储经过字符串格式化的order
    cout << "请输入用户名指令(user 用户名):";
    strcpy(operation,"user");
    cin >> name;
    strcat(order, operation), strcat(order, " "), strcat(order, name);
    sprintf(buff, order);
    sendTCP(buff);									//发送指令
    recv(sockClient, rbuff, sizeof(rbuff), 0);		//接收信息
    cout << rbuff << endl;
    return 1;
}
int pass() {
    char operation[10], name[20];		//操作与文件名
    char order[30] = "\0";				//输入的命令
    char buff[80];						//用来存储经过字符串格式化的order
    cout << "请输入密码指令(pass 密码):" ;
    strcpy(operation,"pass");
    cin >> name;
    strcat(order, operation), strcat(order, " "), strcat(order, name);
    sprintf(buff, order);
    sendTCP(buff);									//发送指令
    recv(sockClient, rbuff, sizeof(rbuff), 0);		//接收信息
    cout << rbuff << endl;
    if (strcmp(rbuff, "wrong") == 0) {
        return 0;
    }
    return 1;
}
//***********************函数定义***********************

int command(){
    char operation[10], name[20];        //操作与文件名
    char order[30] = "\0";                //输入的命令
    char buff[80];                        //用来存储经过字符串格式化的order
    FILE *fd1, *fd2;                    //File协议主要用于访问本地计算机中的文件,fd指针指向要访问的目标文件
    int cnt;
    //发送连接请求成功,初始化数据
    memset(operation, 0, sizeof(operation));
    memset(name, 0, sizeof(name));
    memset(order, 0, sizeof(order));
    memset(buff, 0, sizeof(buff));
    memset(rbuff, 0, sizeof(rbuff));
    memset(sbuff, 0, sizeof(sbuff));
        cout << endl << "请输入要执行的指令: ";
        cin >> operation;
//        cout<<"why:"<<operation<<endl;
        if (strncmp(operation, "get", 3) == 0 || strncmp(operation, "put", 3) == 0 ||
            strncmp(operation, "cd", 2) == 0 || strncmp(operation, "mkdir", 5) == 0 || strncmp(operation, "del", 3) ==0){ ///需要输入文件名的功能
            cin >> name;
        } else if (strncmp(operation, "quit", 4) == 0) { ///退出功能
            cout << "感谢您的使用" << endl;
            return 1;
        } else if (strncmp(operation, "?", 1) == 0 || strncmp(operation, "help", 4) == 0) { ///帮助菜单功能
            help();
        }else if(strncmp(operation,"ls",2)==0|| strncmp(operation,"pwd",3)==0){

        }
        else{
            cout<<"非法输入"<<endl;
            return 0;
        }


        //将指令整合进order,并存放进buff
        strcat(order, operation), strcat(order, " "), strcat(order, name);

        sprintf(buff, order);
        sendTCP(buff);                                    //发送指令
        recv(sockClient, rbuff, sizeof(rbuff), 0);        //接收信息
        cout << rbuff << endl;                            //pwd功能在这里已经实现
        if (strncmp(rbuff, "get", 3) == 0) {            ///下载功能
            callServer(dataClient,dataAddr);
            fd1 = fopen(name, "wb");                    //用二进制的方式打开文件,wb表示打开或新建一个二进制文件(只允许写数据)
            if (fd1 == NULL) {
                cout << "打开或者新建 " << name << "文件失败" << endl;
                return 1;
            }
            memset(rbuff, '\0', sizeof(rbuff));
            while ((cnt = recv(dataClient, rbuff, sizeof(rbuff), 0)) > 0) {
               // cout<<"缓冲区"<<rbuff<<endl<<"长度"<<cnt<<endl;
                fwrite(rbuff, sizeof(rbuff), 1, fd1);    //C 库函数 size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) 把 ptr 所指向的数组中的数据写入到给定流 stream 中。
            }
            closesocket(dataClient);
            fclose(fd1);                                //关闭文件
        }//get
        else if (strncmp(rbuff, "put", 3) == 0) { ///上传功能
          //  cout<<"执行"<<endl;
            strcpy(fileName, rbuff + 4);
            fd2 = fopen(fileName, "rb");                //打开一个二进制文件,文件必须存在,只允许读
            if (fd2) { //成功打开
               // cout<<"debug0"<<endl;
                if (!sendFile(dataClient, fd2)) {
                    cout << "发送失败" << endl;
                    return 1;
                }
                fclose(fd2);
            } else {
                strcpy(sbuff, "无法打开文件\n");
                if (!send(sockClient, sbuff, sizeof(sbuff), 0)) {
                    return 1;
                }
            }

        }//put
        else if (strncmp(rbuff, "ls", 2) == 0) { ///ls功能
            list(dataClient);
        }//dir

        return 0;

}

int main() {
    while (1) {
        startSock();                //启动winsock并初始化
        if (callServer(sockClient,serverAddr) == -1) {    //发送连接请求失败
            continue;
        }
        cout << "发送连接请求成功" << endl;

//        if (checkFlag == false) {//登陆
//            if (user() && pass()) {
//                checkFlag = true;
//            }
//            continue;
//        }
        checkFlag = true;

        if(checkFlag){
            help();
        }
        while(checkFlag){
            if(command()){
                break;
            }
        }
        cout<<"命令输入结束"<<endl;
        closesocket(sockClient);    //关闭连接
        WSACleanup();                //释放Winsock

        return 0;

    }
}
/*
192.168.0.100
user gyc
pass 123456
pwd
cd Debug
get 110.txt
*/


  • 5
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
如果读者需要使用光盘中的源代码,将相关目录及其包含的内容复制到您的硬盘上,并修改对应的硬盘目录属性——取消目录及其所包含子目录和文件的“只读”属性。否则,打开VC项目时由于无法进行文件的“”操作,会导致提示出错信息。 下面是对光盘中主要实例的简要说明: 实例2-1:演示C++程序的运行步骤。源代码在光盘中“\02\firstcpp”目录下。 实例2-2:Visual C++语言基本元素介绍。源代码在光盘中“\02\secondcpp”目录下。 实例2-3:cout流控制符setw的使用。源代码在光盘中“\02\thirdcpp”目录下。 实例2-4:增加域内填充字符。源代码在光盘中“\02\fourthcpp”目录下。 实例2-5:同一数据用不同进制输出结果。源代码在光盘中“\02\fifthcpp”目录下。 实例2-6:用浮点数的形式输出数据。源代码在光盘中“\02\sixthcpp”目录下。 实例2-7:数据的输入及输出。源代码在光盘中“\02\seventhcpp”目录下。 实例2-8:计算学生平均成绩。源代码在光盘中“\02\eighthcpp”目录下。 实例2-9:函数的调用。源代码在光盘中“\02\ninthcpp”目录下。 实例2-10:用指针传递参数。源代码在光盘中“\02\tenthcpp”目录下。 实例2-11:全局变量和局部变量。源代码在光盘中“\02\eleventhcpp”目录下。 实例2-12:使用指针注意内存的分配。源代码在光盘中“\02\twelfthcpp”目录下。 实例2-13:引用实例。源代码在光盘中“\02\thirteencpp”目录下。 实例2-14:虚函数的使用实例。源代码在光盘中“\02\fourteencpp”目录下。 实例3-1:利用向导生成的应用程序框架实例。源代码在光盘中“\03\test”目录下。 实例4-1:文档的存取。源代码在光盘中“\04\CDocument”目录下。 实例4-2:简单的文本编辑器。源代码在光盘中“\04\CEditView”目录下。 实例5-1:菜单实例。源代码在光盘中“\05\test1”目录下。 实例5-2:图片浏览器。源代码在光盘中“\05\picture”目录下。 实例5-3:工具栏资源编辑器。源代码在光盘中“\05\prop”目录下。 实例5-4:工具条的编程技术。源代码在光盘中“\05\record”目录下。 实例5-5:给状态栏添加时间窗格。源代码在光盘中“\05\pane”目录下。 实例6-1:创建模态对话框。源代码在光盘中“\06\dialog_1”目录下。 实例6-2:创建非模态对话框。源代码在光盘中“\06\dialog_2”目录下。 实例6-3:通用对话框展示。源代码在光盘中“\06\dialog_3”目录下。 实例6-4:创建一般属性页对话框。源代码在光盘中“\06\dialog_4”目录下。 实例6-5:创建向导对话框。源代码在光盘中“\06\dialog_5”目录下。 实例7-1:标准控件实例。源代码在光盘中“\07\CtrlTest”目录下。 实例8-1:区域探测实例。源代码在光盘中“\08\finding”目录下。 实例8-2:键盘字符的输入与显示。源代码在光盘中“\08\keyboard”目录下。 实例9-1:字体展示。源代码在光盘中“\09\text”目录下。 实例9-2:文字动画。源代码在光盘中“\09\characters”目录下。 实例9-3:画刷使用实例。源代码在光盘中“\09\Color”目录下。 实例10-1:打印实例。源代码在光盘中“\10\print”目录下。 实例11-1:存取SDI程序文档实例。源代码在光盘中“\11\SerialSDI”目录下。 实例11-2:文件操作实例。源代码在光盘中“\11\FileManipulate”目录下。 实例12-1:使用用户界面线程实例。源代码在光盘中“\12\InterfaceThread”目录下。 实例12-2:使用工作者线程实例。源代码在光盘中“\12\ControlThread”目录下。 实例12-3:多线程实例。源代码在光盘中“\12\WQDemo”目录下。 实例12-4:线程间的通信。源代码在光盘中“\12\ThreadCommu”目录下。 实例13-1:动态链接库(Dll)实例。源代码在光盘中“\13\dlltest ”目录下。 实例13-2:鼠标钩子应用实例。源代码在光盘中“\13\MouseHook”目录下。 实例13-3:键盘钩子应用实例。源代码在光盘中“\13\KeyboardHook”目录下。 实例14-1:WinSock网络程序:聊天室。源代码在光盘中“\14\WinSocketChat”目录下。 实例14-2:利用MSComm控件进行串口数据传输。源代码在光盘中“\14\MSComm”目录下。 实例14-3:简单的WinInet应用程序。源代码在光盘中“\14\SimpleNet”目录下。 实例15-1:创建Access数据库。源代码在光盘的“\15\Info”中。 实例15-2:MFC的ODBC数据库实例。源代码在光盘中“\15\Enroll”目录下。 实例15-3:利用ADO查询并操作数据库实例。源代码在光盘中“\15\AdoTest”目录下。 FTP应用实例:FTP客户端程序,源代码在光盘目录“\16”下。 人事管理系统:源代码在光盘目录“\17”下。
FTP(File Transfer Protocol)是一种常用的文件传输协议,它允许用户在网络上通过 FTP 客户端FTP 服务器之间传输文件。 下面是一个简单的 C 实现 FTP 客户端的代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #define BUF_SIZE 1024 int main(int argc, char *argv[]) { int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) { perror("socket"); exit(1); } struct sockaddr_in server_addr; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(21); server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) { perror("connect"); exit(1); } char buffer[BUF_SIZE]; int recv_len; recv_len = recv(sock, buffer, BUF_SIZE-1, 0); if (recv_len == -1) { perror("recv"); exit(1); } buffer[recv_len] = '\0'; printf("%s", buffer); char user[] = "USER anonymous\r\n"; if (send(sock, user, strlen(user), 0) == -1) { perror("send"); exit(1); } recv_len = recv(sock, buffer, BUF_SIZE-1, 0); if (recv_len == -1) { perror("recv"); exit(1); } buffer[recv_len] = '\0'; printf("%s", buffer); char pass[] = "PASS anonymous\r\n"; if (send(sock, pass, strlen(pass), 0) == -1) { perror("send"); exit(1); } recv_len = recv(sock, buffer, BUF_SIZE-1, 0); if (recv_len == -1) { perror("recv"); exit(1); } buffer[recv_len] = '\0'; printf("%s", buffer); char pwd[] = "PWD\r\n"; if (send(sock, pwd, strlen(pwd), 0) == -1) { perror("send"); exit(1); } recv_len = recv(sock, buffer, BUF_SIZE-1, 0); if (recv_len == -1) { perror("recv"); exit(1); } buffer[recv_len] = '\0'; printf("%s", buffer); close(sock); return 0; } ``` 这段代码实现了 FTP 客户端的基本功能,包括连接 FTP 服务器、登录、获取当前目录等。具体来说,它的实现步骤如下: 1. 创建一个 TCP 套接字; 2. 设置 FTP 服务器的地址和端口号; 3. 连接 FTP 服务器; 4. 接收 FTP 服务器的欢迎信息; 5. 发送用户名和密码,进行登录; 6. 接收登录成功信息; 7. 发送命令 PWD,获取当前目录; 8. 接收当前目录信息; 9. 关闭套接字。 在实际应用中,我们可以根据需要扩展这段代码,实现更多 FTP 客户端的功能,比如上传、下载、删除等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值