SOCKET编程之FTP CLIENT

//  Client.cpp : 定义控制台应用程序的入口点。
// 需在项目设置 链接中添加ws2_32.lib

#include 
" stdafx.h "
#include 
< winsock2.h >
#include 
< iostream >
#include 
< fstream >
#include 
< io.h >      
#include 
< string >    
#include 
< vector >    
#include 
< iomanip >    
#include 
< ctime >  

using   namespace  std;
#define  DEFAULT_PORT 2100  // 默认服务器端口
#define  DEFAULT_BUFFER 4096  // 默认缓冲区大小
char  szServer[ 128 ]; // IP地址

void  inputInt( int   & );  // int输入排错
bool  getList(SOCKET  & , vector < string >   & );  // 接收文件列表
bool  down(SOCKET  & , vector < string >   & );  // 接收文件
void  setServerIp();   // 设置服务器IP
void  menu();  // cmd菜单
void  exit();  // 退出动作

int  main()
{
 setServerIp();

 WSADATA wsd;  
//The WSADATA structure contains information about the Windows Sockets implementation
 SOCKET sClient;
 
int iPort=DEFAULT_PORT;
 vector
<string>   fileName;
 
 
struct sockaddr_in server;
 
struct hostent *host=NULL;


 
if(WSAStartup(MAKEWORD(2,2),&wsd)!=0)
 
{
  cout
<<"Failed to load Winsock library! ";
  exit();
  
return 1;
 }


 sClient
=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
 
if(sClient==INVALID_SOCKET)
 
{
  cout
<<"socket() failed : "<<WSAGetLastError()<<' ';
  exit();
  
return 1;
 }

 
 server.sin_family
=AF_INET;
 server.sin_port
=htons(iPort);
 server.sin_addr.s_addr
=inet_addr(szServer);


 
if(server.sin_addr.s_addr==INADDR_NONE)
 
{
  host
=gethostbyname(szServer);
  
if(host==NULL)
  
{
   cout
<<"Unable to resolve server: "<<szServer<<" ";
   exit();
   
return 1;
  }

  CopyMemory(
&server.sin_addr,host->h_addr_list[0],host->h_length);
 }


 
if(connect(sClient,(struct sockaddr *)&server,sizeof(server))==SOCKET_ERROR)
 
{
  cout
<<"connect() failed: "<<WSAGetLastError()<<' ';
  exit();
  
return 1;
 }

 
 
 
if(!getList(sClient,fileName)) //获取文件列表
  return 1;
 
 
 menu();
//控制台菜单

 cout
<<"请输入你的选择"<<' ';
 
int choice ;
 inputInt(choice);

 
while(choice)
 
{
  
if(choice==1)
  
{
   
if(!down(sClient,fileName))//下载
   
    exit();
    
return 1;
   }

  }

  
else if(choice==2)
  

   
if(!getList(sClient,fileName)) //获取文件列表
   
    exit();
    
return 1;
   }

  }


  menu();
  cout
<<"请输入你的选择"<<' ';
  inputInt(choice);
 }

 closesocket(sClient);
 WSACleanup();
 exit();
 
return 0;
}


void  exit()  // 退出动作
{
 cout
<<"按任意键退出"<<" ";
 
if(getchar()) //防止cmd立即退出
  return;
}

void  inputInt( int   & i)
{
 cin
>>i;
 
while(!cin) //输入错误处理
 {
  cin.clear();
  fflush(stdin);
  cout
<<"Error:输入非整数"<<' ';
  cout
<<"请重新输入一个整数:";
  cin
>>i;
 }

}


bool  getList(SOCKET  & sClient, vector < string >   & fileName)  // 接收文件列表
{
 fileName.clear();

 
char Buffer[DEFAULT_BUFFER]; //缓冲区
 int ret;

 fd_set sf,rf;  
//The fd_set structure is used by various Windows Sockets functions and service providers, such as the select function, 
      
//to place sockets into a "set" for various purposes, such as testing a given socket for readability using the readfds parameter of 
      
//the select function
      
//sf check for writability,rf check for readability

 
 sf.fd_count
=0;
 sf.fd_array[sf.fd_count
++]=sClient;

 timeval to;  
//The timeval structure is used to specify time values
 to.tv_sec=60//60s超时
 to.tv_usec=0//毫秒

 
if(select(0,NULL,&sf,NULL,&to)) //checked for writability
 {
  ret
=send(sClient,"LIST",DEFAULT_BUFFER,0);//发送LIST命令,获取文件列表
  if(ret==0)
   
return false;
  
else if(ret==SOCKET_ERROR)
  
{
   cout
<<"recv() faild: "<<WSAGetLastError()<<' ';
   
return false;
  }

 }

 
else
 
{
  cout
<<"Time out"<<' ';
  
return false;
 }

 
 rf.fd_count
=0;
 rf.fd_array[rf.fd_count
++]=sClient;
 
int i=0;

 cout
<<setiosflags(ios::left)  <<  setw(43)   <<"文件夹名"<<   setw(12)   <<""<<setw(20)   << "修改时间"<<' ';

 
while(1//接收文件夹信息
 {
  
if(select(0,&rf,NULL,NULL,&to))
  
{

   ret
=recv(sClient,Buffer,DEFAULT_BUFFER,0); //checked for readability
   if(strcmp(Buffer," ")==0//判断是否传送完成
    break;
   
if(ret==0)
    
return false;
   
    
   
else if(ret==SOCKET_ERROR)
   
{
    cout
<<"recv() faild: "<<WSAGetLastError()<<' ';
    
return false;
   }

 
  
   
if(i==0)
   
{     
    cout 
<<    setw(43)   <<Buffer;
    cout
<<   setw(12)     <<   "<DIR>" ; 
    i
++;
  
   }

   
else
   
{
     cout 
<<   setw(20)   <<Buffer;
    i
=0;
   }

   
  }

  
else
  
{
   cout
<<"Time out"<<' ';
   
return false;
  }

 }


 cout
<<" 注:本程序没有做进入文件夹的功能,只根据序号下载文件,测试SOCKET ";
 i
=0;

 
int num=0;
 
int length;
 cout
<<setiosflags(ios::left) <<setw(5)<<"序号"  <<  setw(38)   <<"文件名"<<   setw(12)   <<"大小(Byte)"<<setw(20)   << "修改时间"<<' ';

 
while(1)  //接收文件信息
 {
 
  
if(select(0,&rf,NULL,NULL,&to)) //checked for readability
  {

   ret
=recv(sClient,Buffer,DEFAULT_BUFFER,0); 
   
if(strcmp(Buffer," ")==0//判断是否传送完成
    return true;
   
if(ret==0)
    
return false;
   
    
   
else if(ret==SOCKET_ERROR)
   
{
    cout
<<"recv() faild: "<<WSAGetLastError()<<' ';
    
return false;
   }

 
   length
=strlen(Buffer);
   
if(length<DEFAULT_BUFFER)
    Buffer[length]
='
 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值