借鉴了网上一位大佬的作品,然后自己改改拿来完成了算是还行的作品。
代码一共大概是900多行,可以直接粘贴下来看看,其实还是很容易理解的。
运行的截图附上:
客户端:
服务器端:
#pragma once
//服务器侦听控制连接请求的端口
#define CMD_PORT 5858
//客户机侦听数据连接请求的端口
#define DATA_PORT 5850
//命令报文参数缓存的大小
#define CMD_PARAM_SIZE 256
//回复报文消息缓存的大小
#define RSPNS_TEXT_SIZE 256
#define BACKLOG 10
#define DATA_BUFSIZE 4096
//命令类型
typedef enum {
LS, PWD, CD, DOWN, UP, QUIT
} CmdID;
//命令报文,从客户端发往服务器
typedef struct _CmdPacket {
CmdID cmdid;
char param[CMD_PARAM_SIZE];
} CmdPacket;
//回复报文的类型
typedef enum {
OK, ERR
} RspnsID;
//回复报文,从服务器发往客户端
typedef struct _RspnsPacket {
RspnsID rspnsid;
char text[RSPNS_TEXT_SIZE];
} RspnsPacket;
#include
#include "sizes.h"
#include
#pragma comment(lib, "ws2_32.lib")
//创建线程时传递的数据结构,内含控制连接套接字和客户端地址信息:
struct threadData {
SOCKET tcps;
sockaddr_in clientaddr;
};
//全局函数声明:
//FTP初始化,创建一个侦听套接字:
int InitFTP(SOCKET *pListenSock);
int InitDataSocket(SOCKET *pDatatcps, SOCKADDR_IN *pClientAddr);
int ProcessCmd(SOCKET tcps, CmdPacket* pCmd, SOCKADDR_IN *pClientAddr);
int SendRspns(SOCKET tcps, RspnsPacket* prspns);
int RecvCmd(SOCKET tcps, char* pCmd);
int SendFileList(SOCKET datatcps);
int SendFileRecord(SOCKET datatcps, WIN32_FIND_DATA* pfd);
int SendFile(SOCKET datatcps, FILE* file);
int RecvFile(SOCKET datatcps, char* filename);
int FileExists(const char *filename);
//线程函数,参数包括相应控制连接的套接字:
DWORD WINAPI ThreadFunc(LPVOID lpParam) {
SOCKET tcps;
sockaddr_in clientaddr;
tcps = ((struct threadData *)lpParam)->tcps;
clientaddr = ((struct threadData *)lpParam)->clientaddr;
printf("socket的编号是:%u.\n", tcps);
//发送回复报文给客户端,内含命令使用说明:
printf("Serve client %s:%d\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
RspnsPacket rspns = { OK,
"欢迎进入FTP综合应用系统!\n"
"你可以使用的命令:\n"
"ls\t<展示当前目录下的文件(夹),无需参数>\n"
"pwd\t<展示当前目录的绝对路径,无需参数>\n"
"cd\t<切换到指定目录,参数为路径>\n"
"down\t<下载文件,参数为文件名>\n"
"up\t<上传文件,参数为文件名>\n"
"quit\t<退出系统,无需参数>\n"
};
SendRspns(tcps, &rspns);
//循环获取客户端命令报文并进行处理
for (;;) {
CmdPacket cmd;
if (!RecvCmd(tcps, (char *)&cmd))
break;
if (!ProcessCmd(tcps, &cmd, &clientaddr))
break;
}
//线程结束前关闭控制连接套接字:
closesocket(tcps);
delete lpParam;
return 0;
}
int main(int argc, char* argv[]) {
SOCKET tcps_listen; //FTP服务器控制连接侦听套接字
struct threadData *pThInfo;
if (!InitFTP(&tcps_listen)) //FTP初始化
return 0;
printf("FTP服务器开始监听,端口号为:%d。。。。。。\n", CMD_PORT);
//循环接受客户端连接请求,并生成线程去处理:
for (;;) {
pThInfo = NULL;
pThInfo = new threadData;
if (pThInfo == NULL) {
printf("为新线程申请空间失败。\n");
continue;
}
int len = sizeof(struct threadData);
//等待接受客户端控制连接请求
pThInfo->tcps = accept(tcps_listen, (SOCKADDR*)&pThInfo->clientaddr, &len);
//创建一个线程来处理相应客户端的请求:
DWORD dwThreadId, dwThrdParam = 1;
HANDLE hThread;
hThread = CreateThread(
NULL, //无需安全性的继承
0, //默认线程栈大小
ThreadFunc, //线程入口函数
pThInfo, //线程入口函数的参数
0, //立即启动线程
&dwThreadId); //返回线程的id值
//检查返回值是否创建线程成功
if (hThread == NULL) {
printf("创建线程失败。\n");
closesocket(pThInfo->tcps);
delete pThInfo;
}
}
return 0;
}
//FTP初始化,创建一个侦听套接字:
int InitFTP(SOCKET *pListenSock) {
//按照此步骤创建新的服务器端套接字,嗯,没错,前三个都是这个步骤
//startup->socket->bind->listen
WORD wVersionRequested;
WSADATA wsaData;
int err;
SOCKET tcps_listen;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
printf("Winsock初始化时发生错误!\n");
return 0;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
WSACleanup();
printf("无效Winsock版本!\n");
return 0;
}
tcps_listen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (tcps_listen == INVALID_SOCKET) {
WSACleanup();
printf("创建Socket失败!\n");
return 0;
}
SOCKADDR_IN tcpaddr;
tcpaddr.sin_family = AF_INET;
tcpaddr.sin_port = htons(CMD_PORT);
tcpaddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
err = bind(tcps_listen, (SOCKADDR*)&tcpaddr, sizeof(tcpaddr));
if (err != 0) {
err = WSAGetLastError();
WSACleanup();
printf("Scoket绑定时发生错误!\n");
return 0;
}
err = listen(tcps_listen, 3);
if (err != 0) {
WSACleanup();
printf("Scoket监听时发生错误!\n");
return 0;
}
*pListenSock = tcps_listen;
return 1;
}
//建立数据连接
//pDatatcps:用于存储数据连接套接字
//pClientAddr:指向客户端的控制连接套接字地址,需要使用其中的IP地址
//返回值:0表示失败,1正常
int InitDataSocket(SOCKET *pDatatcps, SOCKADDR_IN *pClientAddr) {
SOCKET datatcps;
//创建socket
datatcps = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (datatcps == INVALID_SOCKET) {
printf("Creating data socket failed!\n");
return 0;
}
SOCKADDR_IN tcpaddr;
memcpy(&tcpaddr, pClientAddr, sizeof(SOCKADDR_IN));
tcpaddr.sin_port = htons(DATA_PORT); //如若有什么意外只需要在头文件修改端口值
//请求连接客户端
if (connect(datatcps, (SOCKADDR*)&tcpaddr, sizeof(tcpaddr)) == SOCKET_ERROR) {
printf("Connecting to client failed!\n");
closesocket(datatcps);
return 0;
}
*pDatatcps = datatcps;
return 1;
}
//处理命令报文
//tcps:控制连接套接字
//pcmd:指向待处理的命令报文
//pClientAddr:指向客户端控制连接套接字地址
//返回值:0表示有错或者需要结束连接,1正常
int ProcessCmd(SOCKET tcps, CmdPacket* pCmd, SOCKADDR_IN *pClientAddr) {
SOCKET datatcps; //数据连接套接字
RspnsPacket rspns; //回复报文
FILE* file;
//根据命令类型分派执行:
switch (pCmd->cmdid) {
case LS://展示当前目录下的文件列表
//首先建立数据连接:
if (!InitDataSocket(&datatcps, pClientAddr))
return 0;
//发送文件列表信息:
if (!SendFileList(datatcps))
return 0;
break;
case PWD://展示当前目录的绝对路径
rspns.rspnsid = OK;
//获取当前目录,并放至回复报文中
if (!GetCurrentDirectory(RSPNS_TEXT_SIZE, rspns.text))
strcpy(rspns.text, "Can't get current dir!\n");
if (!SendRspns(tcps, &rspns))
return 0;
break;
case CD://设置当前目录,使用win32 API 接口函数
if (SetCurrentDirectory(pCmd->param)) {
rspns.rspnsid = OK;
if (!GetCurrentDirectory(RSPNS_TEXT_SIZE, rspns.text))
strcpy(rspns.text, "切换当前目录成功!但是不能获取到当前的文件列表!\n");
}
else {
strcpy(rspns.text, "不能更换到所选目录!\n");
}
if (!SendRspns(tcps, &rspns)) //发送回复报文
return 0;
break;
case DOWN://处理下载文件请求:
file = fopen(pCmd->param, "rb"); //打开要下载的文件
if (file) {
rspns.rspnsid = OK;
sprintf(rspns.text, "下载文件%s\n", pCmd->param);
if (!SendRspns(tcps, &rspns)) {
fclose(file);
return 0;
}
else {
//创建额外的数据连接来传送数据:
if (!InitDataSocket(&datatcps, pClientAddr)) {
fclose(file);
return 0;
}
if (!SendFile(datatcps, file))
return 0;
fclose(file);
}
}
else //打开文件失败
{
rspns.rspnsid = ERR;
strcpy(rspns.text, "不能打开文件!\n");
if (!SendRspns(tcps, &rspns))
return 0;
}
break;
case UP://处理上传文件请求
//首先发送回复报文
char filename[64];
strcpy(filename, pCmd->param);
//首先看一下服务器上是否已经有这个文件里,如果有就告诉客户端不用传输了
if (FileExists(filename)) {
rspns.rspnsid = ERR;
sprintf(rspns.text, "服务器已经存在名字为%s的文件!\n", filename);
if (!SendRspns(tcps, &rspns))
return 0;
}
else {
rspns.rspnsid = OK;
if (!SendRspns(tcps, &rspns))
return 0;
//另建立一个数据连接来接受数据:
if (!InitDataSocket(&datatcps, pClientAddr))
return 0;
if (!RecvFile(datatcps, filename))
return 0;
}
break;
case QUIT:
printf("客户端断开连接。\n");
rspns.rspnsid = OK;
strcpy(rspns.text, "常来啊!\n");
SendRspns(tcps, &rspns);
return 0;
}
return 1;
}
//发送回复报文
int SendRspns(SOCKET tcps, RspnsPacket* prspns) {
if (send(tcps, (char *)prspns, sizeof(RspnsPacket), 0) == SOCKET_ERROR) {
printf("与客户端失去连接。\n");
return 0;
}
return 1;
}
//接收命令报文
//tcps:控制连接套接字
//pCmd:用于存储返回的命令报文
//返回值:0表示有错或者连接已经断开,1表示正常
int RecvCmd(SOCKET tcps, char* pCmd) { //used to receive command from client
int nRet;
int left = sizeof(CmdPacket);
//从控制连接中读取数据,大小为 sizeof(CmdPacket):
while (left) {
nRet = recv(tcps, pCmd, left, 0);
if (nRet == SOCKET_ERROR) {
printf("从客户端接受命令时发生未知错误!\n");
return 0;
}
if (!nRet) {
printf("客户端关闭了连接!\n");
return 0;
}
left -= nRet;
pCmd += nRet;
}
return 1; //成功获取命令报文
}
//发送一项文件信息:
int SendFileRecord(SOCKET datatcps, WIN32_FIND_DATA* pfd) { //used to send response to client
char filerecord[MAX_PATH + 32];
FILETIME ft;
FileTimeToLocalFileTime(&pfd->ftLastWriteTime, &ft);
SYSTEMTIME lastwtime;
FileTimeToSystemTime(&ft, &lastwtime);
char* dir = (char*)(pfd->dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY ? "" : "");
sprintf(filerecord, "%04d-%02d-%02d%02d:%02d %5s %10d %-20s\n",
lastwtime.wYear,
lastwtime.wMonth,
lastwtime.wDay,
lastwtime.wHour,
lastwtime.wMinute,
dir,
pfd->nFileSizeLow,
pfd->cFileName);
if (send(datatcps, filerecord, strlen(filerecord), 0) == SOCKET_ERROR) {
printf("发送文件列表时发生未知错误!\n");
return 0;
}
return 1;
}
//发送文件列表信息
//datatcps:数据连接套接字
//返回值:0表示出错,1表示正常
int SendFileList(SOCKET datatcps) {
HANDLE hff;
WIN32_FIND_DATA fd;
//搜索文件
hff = FindFirstFile("*", &fd);
if (hff == INVALID_HANDLE_VALUE) //发生错误
{
const char* errstr = "不能列出文件!\n";
printf("文件列表输出失败!\n");
if (send(datatcps, errstr, strlen(errstr), 0) == SOCKET_ERROR) {
printf("发送给文件列表时发生未知错误!\n");
}
closesocket(datatcps); return 0;
}
BOOL fMoreFiles = TRUE;
while (fMoreFiles) {
//发送此项文件信息:
if (!SendFileRecord(datatcps, &fd)) {
closesocket(datatcps);
return 0;
}
//搜索下一个文件
fMoreFiles = FindNextFile(hff, &fd);
}
closesocket(datatcps);
return 1;
}
//通过数据连接发送文件
int SendFile(SOCKET datatcps, FILE* file) {
char buf[1024];
printf("发送文件数据中。。。。。。");
for (;;) { //从文件中循环读取数据并发送客户端
int r = fread(buf, 1, 1024, file);
if (send(datatcps, buf, r, 0) == SOCKET_ERROR) {
printf("与客户端失去连接!\n");
closesocket(datatcps);
return 0;
}
if (r < 1024) //文件传输结束
{
break;
}
}
closesocket(datatcps);
printf("完成传输!\n");
return 1;
}
//接收文件
//datatcps:数据连接套接字,通过它来接收数据
//filename:用于存放数据的文件名
int RecvFile(SOCKET datatcps, char* filename) {
char buf[1024];
FILE* file = fopen(filename, "wb");
if (!file) {
printf("写入文件时发生未知错误!\n");
fclose(file);
closesocket(datatcps);
return 0;
}
printf("接受文件数据中。。。。。。");
while (1) {
int r = recv(datatcps, buf, 1024, 0);
if (r == SOCKET_ERROR) {
printf("从客户端接受文件时发生未知错误!\n");
fclose(file);
closesocket(datatcps);
return 0;
}
if (!r) {
break;
}
fwrite(buf, 1, r, file);
}
fclose(file);
closesocket(datatcps);
printf("完成传输!\n");
return 1;
}
//检测文件是否存在:
int FileExists(const char *filename)
{
WIN32_FIND_DATA fd;
if (FindFirstFile(filename, &fd) == INVALID_HANDLE_VALUE)
return 0;
return 1;
}
#pragma once
//服务器侦听控制连接请求的端口
#define CMD_PORT 5858
//客户机侦听数据连接请求的端口
#define DATA_PORT 5850
//命令报文参数缓存的大小
#define CMD_PARAM_SIZE 256
//回复报文消息缓存的大小
#define RSPNS_TEXT_SIZE 256
#define BACKLOG 10
#define DATA_BUFSIZE 4096
//命令类型
typedef enum {
LS, PWD, CD, DOWN, UP, QUIT
} CmdID;
//命令报文,从客户端发往服务器
typedef struct _CmdPacket {
CmdID cmdid;
char param[CMD_PARAM_SIZE];
} CmdPacket;
//回复报文的类型
typedef enum {
OK, ERR
} RspnsID;
//回复报文,从服务器发往客户端
typedef struct _RspnsPacket {
RspnsID rspnsid;
char text[RSPNS_TEXT_SIZE];
} RspnsPacket;
#include
#include
#include "sizes.h"
#include
#include
#pragma comment(lib, "ws2_32.lib")
//读取回复报文
void do_read_rspns(SOCKET fd, RspnsPacket *ptr)
{
int count = 0;
int size = sizeof(RspnsPacket);
while (count < size)
{
int nRead = recv(fd, (char *)ptr + count, size - count, 0);
if (nRead <= 0)
{
printf("读取服务器的回复失败!\n");
closesocket(fd);
exit(1);
}
count += nRead;
}
}
//发送命令报文
void do_write_cmd(SOCKET fd, CmdPacket *ptr)
{
int size = sizeof(CmdPacket);
int flag = send(fd, (char *)ptr, size, 0);
if (flag == SOCKET_ERROR)
{
printf("给服务器发送命令失败!\n");
closesocket(fd);
WSACleanup();
exit(1);
}
}
//创建数据连接套接字并进入侦听状态
SOCKET create_data_socket()
{
SOCKET sockfd;
struct sockaddr_in my_addr;
//创建用于数据连接的套接字
if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
printf("创建用于数据连接的套接字失败!\n");
WSACleanup();
exit(1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(DATA_PORT);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
memset(&(my_addr.sin_zero), 0, sizeof(my_addr.sin_zero));
//绑定
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == SOCKET_ERROR)
{
int err = WSAGetLastError();
printf("绑定地址失败,错误代码:%d\n", err);
closesocket(sockfd);
WSACleanup();
exit(1);
}
//侦听数据连接请求
if (listen(sockfd, 1) == SOCKET_ERROR)
{
printf("监听数据连接失败!\n");
closesocket(sockfd);
WSACleanup();
exit(1);
}
return sockfd;
}
//处理list命令
void list(SOCKET sockfd)
{
int sin_size;
int nRead;
CmdPacket cmd_packet;
SOCKET newsockfd, data_sockfd;
struct sockaddr_in their_add;
char data_buf[DATA_BUFSIZE];
//创建数据连接
newsockfd = create_data_socket();
//构建命令报文并发送至服务器
cmd_packet.cmdid = LS;//没有参数
do_write_cmd(sockfd, &cmd_packet);
sin_size = sizeof(struct sockaddr_in);
//接受服务器的数据连接请求
if ((data_sockfd = accept(newsockfd, (struct sockaddr*)&their_add, &sin_size)) == INVALID_SOCKET)
{
printf("获取文件列表失败!\n");
closesocket(newsockfd);
closesocket(sockfd);
WSACleanup();
exit(1);
}
//每次读到多少数据就显示多少,直到数据连接断开
while (true)
{
nRead = recv(data_sockfd, data_buf, DATA_BUFSIZE - 1, 0);
if (nRead == SOCKET_ERROR)
{
printf("读取服务器回复失败!\n");
closesocket(data_sockfd);
closesocket(newsockfd);
closesocket(sockfd);
WSACleanup();
exit(1);
}
if (nRead == 0)//数据读取结束
break;
//显示数据
data_buf[nRead] = '\0';
printf("%s", data_buf);
}
closesocket(data_sockfd);
closesocket(newsockfd);
}
//处理pwd命令:
void pwd(int sockfd)
{
CmdPacket cmd_packet;
RspnsPacket rspns_packet;
cmd_packet.cmdid = PWD;
//发送命令报文并读取回复:
do_write_cmd(sockfd, &cmd_packet);
do_read_rspns(sockfd, &rspns_packet);
printf("%s\n", rspns_packet.text);
}
//处理cd命令:
void cd(int sockfd)
{
CmdPacket cmd_packet;
RspnsPacket rspns_packet;
cmd_packet.cmdid = CD;
scanf("%s", cmd_packet.param);
//发送命令报文并读取回复:
do_write_cmd(sockfd, &cmd_packet);
do_read_rspns(sockfd, &rspns_packet);
if (rspns_packet.rspnsid == ERR)
printf("%s", rspns_packet.text);
}
//处理down命令,即下载文件:
void get_file(SOCKET sockfd)
{
FILE *fd;
char data_buf[DATA_BUFSIZE];
CmdPacket cmd_packet;
RspnsPacket rspns_packet;
SOCKET newsockfd, data_sockfd;
struct sockaddr_in their_addr;
int sin_size;
int count;
//设置命令报文:
cmd_packet.cmdid = DOWN;
scanf("%s", cmd_packet.param);
//打开或者创建本地文件以供写数据:
fd = fopen(cmd_packet.param, "wb");//使用二进制方程
if (fd == NULL)
{
printf("打开文件%s来写入失败!\n", cmd_packet.param);
return;
}
//创建数据连接并侦听服务器的连接请求:
newsockfd = create_data_socket();
//发送报文请求:
do_write_cmd(sockfd, &cmd_packet);
//读取回复报文:
do_read_rspns(sockfd, &rspns_packet);
if (rspns_packet.rspnsid == ERR)
{
printf("%s", rspns_packet.text);
closesocket(newsockfd);
fclose(fd);
//删除文件:
DeleteFile(cmd_packet.param);
return;
}
sin_size = sizeof(struct sockaddr_in);
//等待接受服务器的连接请求
if ((data_sockfd = accept(newsockfd, (struct sockaddr *)&their_addr, &sin_size)) == INVALID_SOCKET)
{
printf("获取文件失败!\n");
closesocket(newsockfd);
fclose(fd);
//删除文件:
DeleteFile(cmd_packet.param);
return;
}
//循环读取网络数据并写入文件:
while ((count = recv(data_sockfd, data_buf, DATA_BUFSIZE, 0)) > 0)
fwrite(data_buf, sizeof(char), count, fd);
closesocket(data_sockfd);
closesocket(newsockfd);
fclose(fd);
}
//处理put命令,即上传文件
void put_file(SOCKET sockfd)
{
FILE *fd;
CmdPacket cmd_packet;
RspnsPacket rspns_packet;
char data_buf[DATA_BUFSIZE];
SOCKET newsockfd, data_sockfd;
struct sockaddr_in their_addr;
int sin_size;
int count;
cmd_packet.cmdid = UP;
scanf("%s", cmd_packet.param);
//打开本地文件用于读取数据
fd = fopen(cmd_packet.param, "rb");
if (fd == NULL)
{
printf("打开文件%s来读取数据失败!\n", cmd_packet.param);
return;
}
//创建数据连接套接字并进入侦听状态;
newsockfd = create_data_socket();
//发送命令报文
do_write_cmd(sockfd, &cmd_packet);
//读取回复报文
do_read_rspns(sockfd, &rspns_packet);
if (rspns_packet.rspnsid == ERR)
{
printf("%s", rspns_packet.text);
closesocket(newsockfd);
fclose(fd);
return;
}
sin_size = sizeof(struct sockaddr_in);
//准备接受数据连接
if ((data_sockfd = accept(newsockfd, (struct sockaddr *)&their_addr, &sin_size)) == INVALID_SOCKET)
{
printf("上传文件传输错误!\n");
closesocket(newsockfd);
fclose(fd);
return;
}
//循环从文件中读取数据并发给服务器
while (true)
{
count = fread(data_buf, sizeof(char), DATA_BUFSIZE, fd);
send(data_sockfd, data_buf, count, 0);
if (count < DATA_BUFSIZE)//数据已经读完或者发生cuowu
break;
}
closesocket(data_sockfd);
closesocket(newsockfd);
fclose(fd);
}
//处理退出命令
void quit(int sockfd)
{
CmdPacket cmd_packet;
RspnsPacket rspns_packet;
cmd_packet.cmdid = QUIT;
do_write_cmd(sockfd, &cmd_packet);
do_read_rspns(sockfd, &rspns_packet);
printf("%s", rspns_packet.text);
getchar();
}
void main()
{
SOCKET sockfd;
struct sockaddr_in their_addr;
char cmd[10];
RspnsPacket rspns_packet;
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
//Winsock初始化
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
{
printf("WinSock初始化失败!\n");
return;
}
//确认WindSock DLL的版本是2.2
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
printf("WindSock版本不是2.2!\n");
WSACleanup();
return;
}
//创建用于控制谅解的socket
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd == INVALID_SOCKET)
{
printf("创建套接字失败!\n");
WSACleanup();
exit(1);
}
their_addr.sin_family = AF_INET;
their_addr.sin_port = htons(CMD_PORT);
their_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
memset(&(their_addr.sin_zero), 0, sizeof(their_addr.sin_zero));
//连接服务器
if (connect(sockfd, (struct sockaddr*)&their_addr, sizeof(struct sockaddr)) == SOCKET_ERROR)
{
printf("连接服务器失败!\n");
closesocket(sockfd);
WSACleanup();
exit(1);
}
//连接成功后,首先接受服务器发回的消息
do_read_rspns(sockfd, &rspns_packet);
printf("%s", rspns_packet.text);
//主循环:读取用户输入并分配执行
while (true)
{
scanf("%s", cmd);
switch (cmd[0])
{
case 'l'://处理List命令
list(sockfd);
break;
case 'p'://处理pwd命令
pwd(sockfd);
break;
case 'c'://处理cd命令
cd(sockfd);
break;
case 'd'://处理down命令
get_file(sockfd);
break;
case 'u'://处理up命令
put_file(sockfd);
break;
case 'q'://处理quit命令
quit(sockfd);
break;
default:
printf("不存在的命令!\n");
break;
}
if (cmd[0] == 'q')
break;
}
WSACleanup();
}