4.2.2 登录FTP服务器
对于客户端而言,连接服务器成功后需要发送用户名等验证信息到服务器进行验证登录。
1.构造验证信息
在FTP中,验证信息是以命令字符串的形式发送到服务器的。首先,验证信息由用户名和密码组成。用户名用命令USER标识,密码用命令PASS标识。例如,用户名为"lymlrl",密码为"123456"的验证信息写成命令流为"USER"+lymlrl+"PASS"+123456。
如果用户使用匿名登录方式登录FTP服务器,则用户名使用默认的anonymous,密码可以是自己的邮箱。那么命令流为"USER"+anonymous+"PASS"+xxxx@163.com。
2.发送验证信息
验证信息构造完成后,用户可以使用MFC类库中的CSocketFile和CAchive两个类进行数据发送。一般情况下,CSocketFile类是和CSocket类一起使用的,它主要用来创建一个与套接字相关联的文件对象。例如,创建一个与4.2.1节中套接字对象m_clientsocket相关联的CSocketFile对象,代码如下:
- CSocketFile *m_sockfile; //定义文件对象指针
- m_sockfile=new CSocketFile(m_clientsocket);
- //关联对象,m_clientsocket是创建的套接字
然后,再使用CAchive类创建一个与该文件指针对象m_sockfile关联的串行化对象。代码如下:
- CArchive *m_archive; //定义串行化指针对象
- m_archive=new CArchive(&m_sockfile,CArchive::load| CArchive::store);
- //创建对象m_archive的实例并指定属性
一般情况下,用户在创建串行化对象m_archive时,都要为其指定属性CArchive::load| CArchive::store,表示创建的对象m_archive具有读取和存储的功能。
现在,用户可以调用CArchive类的WriteString()函数进行命令发送。其原型如下:
- Void WriteString(LPCTSTR lpsz);
参数lpsz指定将要操作的字符串。该函数调用失败会抛出一个异常。例如,用户要获取服务器上的文件目录需要向服务器发送LIST命令,使用该函数进行发送。代码如下:
- m_archive->WriteString("LIST"+"\r\n");
- //调用CArchive类的WriteString发送LIST命令
注意:有关FTP的其他命令请参考表4.3。
使用用户名和密码登录FTP服务器。其代码如下:
- CString str=""USER"+lymlrl+"PASS"+123456"; //定义命令字符串变量
- try
- {
- m_archive->WriteString(str+"\r\n");//调用CArchive类的WriteString发送命令
- m_archive->Flush(); //强制写入命令到服务器
- }
- Catch(CException e) //处理被抛出的异常
- {
- MessageBox("发送关闭命令失败!");
- }
- ...
在代码中,所使用的登录方式是用户名密码登录。如果用户选择匿名登录,则将字符串变量初始化为"USER"+anonymous+"PASS"+xxxx@163.com即可。然后使用函数WriteString()发送到服务器,如果失败该函数则抛出异常进行处理。
用户在实际编程(www.cppentry.com)中,需要首先发送信息到服务器进行初始化,才能发送其他命令到服务器执行。具体代码如下:
- CSocketFile *m_sockfile; //定义文件对象指针
- CArchive *m_archive; //定义串行化指针对象m_archive
- m_sockfile=new CSocketFile(m_clientsocket); //关联对象
- m_archive=new CArchive(&m_sockfile,CArchive::load| CArchive::store);
- //创建对象m
_archive的实例并指定属性 - Void Send() // Send()函
数发送信息到服务器 - { CString charstring;
- charstring=""USER"+lymlrl+"PASS"+123456"; //构造
字符串charstring - m_archive->WriteString(" "+"\r\n"); //向服务器
发送空字符串进行初始化 - try{
- m_archive->WriteString(charstring +"\r\n");
- //调用CArchive类
的WriteString发送命令 - m_archive->Flush(); //强制写入命令到服务器
- }
- Catch(CException e) //处理被抛出的异常
- {
- MessageBox("发送关闭命令失败!");
- }
- }
在上面的示例代码中,程序首先调用函数WriteString()发送一个空字符串到FTP服务器进行初始化工作。然后发送已经构造好的用户登录信息到服务器进行验证。
注意:在发送字符串的时候一定要在后面加上"\r\n"。
3.接收验证信息
客户端接收服务器返回的内容是通过CArchive类的函数ReadString()进行的。这个函数的作用是从与CArchive对象相关联的套接字文件中读取数据到指定变量中。其原型如下:
- BOOL ReadString( CString& rString );
其中,参数rString是存放接收数据的。该函数调用成功返回true,否则返回false。在本章中封装一个自定义函数Recv()来接收服务器返回的数据。其功能代码如下:
- CString Recv() // Recv()函
数接收服务器返回的数据 - {
- CString recvstr=" "; //初始化字符串recvstr为空
- if(m_archive->ReadString(recvstr)) //接收返回
信息并放到recvstr变量 - {
- if(recvstr==" ") MessageBox("接收数据为空"); //如果接收的数据为空则提示
- { MessageBox("接收数据成功");
- return recvstr; }} //返回接收到的数据
- else
- {
- MessageBox("接收数据失败"); //提示接收数据失败
- }
- }
函数Recv()的作用是接收服务器返回的数据,并将数据保存在字符串变量recvstr中,函数的返回类型是CString类型。在程序中,首先判断接收数据是否成功,再对接收到的数据进行判断是否为空。如果不为空,则直接返回接收到的数据。
用户接收到的数据内容,会因为FTP服务器的不同而不同。例如,有的服务器在客户端登录成功以后返回欢迎信息到客户端等。
4.分析数据
客户端在接收到服务器返回的信息以后,用户需要将返回的信息内容进行分析,以得到用户所需要的数据。该信息是一个字符串形式。它由3个数字、一个空格和一段文字信息组成。其形式如表4.4所示。
表4.4 数据基本格式
|
3个数字< xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> |
空格 |
文字信息字符串 |
第一个数字若为1或者2,则表示返回值正确。若为3,则表示一个中间层的肯定回答,此时,服务器会等待客户端进一步的信息。若为其他,则表示错误。第二个数字表示回答的类型,若为0,则表示语法错误。若为1则表示信息内容。第三个数字表示对错误进行具体的分类。
在文字信息中,如果内容为EROR表示出现用户名或密码错误。否则,表示验证成功。下面将使用自定义函数Recv()来接收数据,然后再对接收到的数据进行分析。代码如下:
- CString str1=" "; //初始化字符串变
量,用于存放服务器返回的信息 - char ch; //定义字符变量,用于字符比较
- int i=0; //循环变量初始化为0
- str1=Recv(); //调用Recv()函数得
到服务器返回的信息 - if(str1.GetLength()>0) //比较str1的长度
- {
- ch= str1.GetAt(i); //将接收到的第一个字符赋给ch
- }
- if(ch==1&& ch==2) //如果返回的第一
个字符等于1或者2,表示返回值正确 - {
- while(i<= str1.GetLength()&&ch!=NULL)
- { switch(ch)
- case EROR: //出现错误
- MessageBox("用户名或密码错误!");
- break;
- case SUSS: //验证成功
- MessageBox("登录成功!");
- return true;
- break;
- ch= str1.GetAt(++i); //循环查看返回的信息
- }
- }
在代码中,用户通过CString::GetAt(0)函数可以获得服务器返回信息的第一个字符。如果第一个字符等于1或2,则表示返回值正确。否则,表示发生错误。最后,使用变量i进行循环获得命令值,如果是EROR表示验证错误。否则,表示成功。
5.关闭与服务器的连接
当用户操作完需要的数据以后,需要关闭与服务器的连接。这时,向服务器发送ABORT或者是改变端口等操作都会使服务器关闭连接。在这里最为简便的方法是使用CArchive类的WriteString()发送ABORT命令到服务器。关闭连接操作的关键代码如下:
- try{ //尝试发送命
令ABORT到服务器,以关闭连接 - m_archive->WriteString("ABORT "+"\r\n");
- //调用CArchive
类的WriteString发送命令 - m_archive->Flush(); //强制写入命令到服务器
- }
- Catch(CException e)
- {
- MessageBox("发送关闭命令失败!");
- }
在这一小节中,用户主要了解了怎样去连接、登录FTP服务器、验证用户信息和关闭连接等过程实现。在上述操作都成功以后,用户就可以进行相关的文件处理操作了。关于FTP具体的文件处理将在下节中进行讲述。