以下只是一个源代码:利用winsock实现ftp下载功能的基本步骤:
1。连接FTP SERVER很简单,创建一套接字,指定服务器的地址和端口号,连接到服务器,
2。分别再向它发送USER和PASS命令,服务器返回230,就代表登陆成功,并且服务器和客户建立了一控制连接。
3。使用PASV命令。
4。然后向服务器发送RETR命令下载文件,或先发送一REST命令指明从哪下载文件。
5。要建立一新的套接字
6。连接到数据连接指定的端口(即从第四步得到的返回消息),
7。采用RECV接收数据。
8。下载完毕后,关闭套接字。
#include <iostream>
#include <afx.h>
#include <string.h>
#include <WinSock2.h>
#pragma comment(lib,"Ws2_32.lib")
using namespace std;
void main()
{
//SOCKE初始化操作
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
return;
}
//建立一个套接字
SOCKET varsocket=socket(PF_INET,SOCK_STREAM,0);
SOCKADDR_IN sock1;
sock1.sin_family=AF_INET;
string str="172.18.16.176";
sock1.sin_addr.S_un.S_addr=inet_addr(str.c_str());
int port=21;
sock1.sin_port=htons(21);
//////////////////////////////////////
//连接操作
if (connect(varsocket,(LPSOCKADDR)&sock1,sizeof(sock1))==SOCKET_ERROR)
{
closesocket(varsocket);
cout<<"connect is wrong"<<endl;
return;
}
//////////////////登录操作///////////////////
char *username="USER wang \r\n";
char *buffer=new char[4000];
int recLen=0;
send(varsocket,username,strlen(username),0);
recLen=recv(varsocket,buffer,4000,0);
buffer[recLen]=0;
cout<<buffer<<endl;
char *pwd="PASS 851188 \r\n";
char *buffer2=new char[4000];
int recLen2=0;
send(varsocket,pwd,strlen(pwd),0);
recLen=recv(varsocket,buffer2,4000,0);
buffer2[recLen2]=0;
cout<<buffer<<endl;
//////////////////登录操作结束///////////////////
//以PASV模式连接服务器,服务器将返回一个数据接口
char *port0="PASV \r\n";
//char *buffer=new char[100];
send(varsocket,port0,strlen(port0),0);
recLen=recv(varsocket,buffer,4000,0);
buffer[recLen]=0;
cout<<buffer<<endl;
//下载文件操作
char *path="RETR root.txt \r\n";
//char *buffer=new char[100];
send(varsocket,path,strlen(path),0);
recLen=recv(varsocket,buffer,4000,0);
buffer[recLen]=0;
cout<<buffer<<endl;
//这是为什么输出的只是地址呀??????
//???????????????
// CString pasvStr=buffer;
// cout<<pasvStr<<endl;
//???????????????
//解析地址(172,18,16,176,p1,p2) 真实的端口地址应该是p1*256+p2
CString pasvStr=buffer;
int index = pasvStr.Find('(');
CString strTemp = pasvStr.Right(pasvStr.GetLength() - index -1);
CString temp;
for(int i =0 ; i < 4 ;i ++) {
index = strTemp.Find(',');
strTemp=strTemp.Right(strTemp.GetLength()- index - 1);
}
index = strTemp.Find(',');
temp = strTemp.Left(index);
strTemp = strTemp.Right(strTemp.GetLength() - index - 1);
index = strTemp.Find(')');
strTemp = strTemp.Left(index);
int shi = _ttoi(temp);
int ge = _ttoi(strTemp);
//再新建一个套接字
SOCKET varsocket2=socket(PF_INET,SOCK_STREAM,0);
SOCKADDR_IN sock2;
sock2.sin_family=AF_INET;
string str2="172.18.16.176";
sock2.sin_addr.S_un.S_addr=inet_addr(str2.c_str());
sock2.sin_port=htons(shi*256+ge);//注意端口号
//sock1.sin_port=htons(shi*256+ge);这样写导致的错误确实很难找 ----因为错误的把sock2写成sock1,找了半天的错,实在不应该
//以后调试时应该注意
if (connect(varsocket2,(LPSOCKADDR)&sock2,sizeof(sock2))==SOCKET_ERROR)
{
closesocket(varsocket2);
cout<<"connect is wrong"<<endl;
return;
}
//直接接收数据即可
recLen=recv(varsocket2,buffer,4000,0);
buffer[recLen]=0;
cout<<buffer<<endl;
//关闭套接字
closesocket(varsocket);
closesocket(varsocket2);
}
接下来将会是多线程的文件下载,敬请阅读,多提意见!