实现ftp多线程下载<一>

以下只是一个源代码:利用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);

}


接下来将会是多线程的文件下载,敬请阅读,多提意见!



你可能感兴趣的:(多线程,Stream,socket,服务器,buffer,Path)