[大二下]Windows网络编程复习题


一、单选题(24分)

1.A)是指在发出一个功能调用后,在没有得到结果之前,该调用不返回。

A.       阻塞模式

B.       非阻塞模式

C.       异步模式

D.       事件选择模式

2.把套接字设置为(B),当所请求的函数操作无法完成时,发出调用的线程不会阻塞,而是返回一个错误码。调用线程将不断测试数据是否已准备好,如果没有准备好,继续测试,直到数据准备好为止。

A.       阻塞模式

B.       非阻塞模式

C.       异步模式

D.       事件选择模式

3.当应用程序调用(A)函数时,操作系统根据请求的Socket版本来搜索相应的Socket库,然后将找到的Socket库绑定到该应用程序中。之后应用程序可以随时调用所请求的Socket库函数。

A.       WSAStartup

B.       connect

C.       recv

D.       send

4.套接字在完成任务后,需要调用shutdown函数,作用是(B

A.       绑定套接字

B.       断开套接字与服务器之间的连接,但并不彻底关闭套接字和释放资源。

C.       断开套接字与服务器之间的连接,并释放所有资源。

D.       接受套接字连接请求

5.B)将套接字的事件通知包装成窗体消息发送到窗体的回调函数处理,从而实现对套接字FD_READFD_WRITE等网络事件的异步响应

A.       Select I/O模型

B.       WSAAyncSelect I/O模型

C.       WSAEventSelect I/O模型

D.       Overlapped I/O模型

E.       I/O完成端口I/O模型

6.A)将一个事件对象与网络事件集合关联起来,当网络事件发生时,应用程序以套接字事件对象的形式接受网络事件通知

A.       WSAEventSelect函数

B.       WSAAyncSelect函数

C.       Select函数函数

D.       CreateIoCompletionPort函数

7.D)负责创建一个I/O完成端口,并关联一个或多个文件句柄。文件句柄不仅可以是一个磁盘上的文件,还可以是一个网络断电、TCP套接字或命名管道,也可以是任何系统对象,只要它支持重叠I/O即可。

A.       WSAEventSelect函数

B.       WSAAyncSelect函数

C.       Select函数函数

D.       CreateIoCompletionPort函数

8.MFC类封装了Windows API。所以,在MFC程序中看不到程序入口函数和(A

A.       窗口回调函数

B.       Main函数

C.       WinMain函数

D.       程序出口函数

9.虚函数onReceive的作用是(A

A.       用于通知此套接字缓冲区中有需要接受的数据

B.       通知此套接字其连接尝试已完成,可能成功,也可能存在错误。

C.       通知此套接字它连接的远端套接字已关闭

D.       通知此侦听套接字可以接受挂起的或新到的连接请求。

10.POP3协议支持离线邮件处理,默认端口110,底层传输协议使用TCP

()命令的作用是

A.       LIST)命令返回邮件数量和每个邮件的大小

B.       RETR)命令返回有参数标识的邮件的所有文本

C.       STAT)命令请求服务器发回关于邮件的统计资料,如邮件总数和总字节数。

D.       QUIT)命令有处理器状态转到更新状态,再返回认证状态。

11.对于一个进程的内存空间而延,可以在逻辑上分为3个部分,局部变量存放在(C

A.       代码区

B.       静态数据区

C.       动态数据区

D.       寄存器

12.以下说法错误的是(   ABCD都对 

A.       CInternetSession类的GFtpConnection用于建立到FTP服务器的连接并登录

B.       CFtpConnection类的PutFile函数用于上传文件

C.       CFtpConnection类的setCurrentDirectory用于设置FTP客户端的当前目录

D.       CFtpFileFind类的FindFile用于查找目录中第一个文件或子目录,如果目录为空则返回False

13.以下说法错误的是(  ABCD都对

A.       CInternetSession类的GHttpConnection用于建立到HTTP服务器的连接并登录

B.       CFtpConnection类的setCurrentDirectory用于设置FTP客户端的当前目录

C.       CFtpConnection类的GetFile函数用于下载文件

D.       CFtpFileFind类的FindNextFile用于查找下一个文件或目录,如果没有下一个则返回False

14.以下描述错误的是( A

A.       RFC扩展了电子邮件标准,使其能够支持非ASCII字符和二进制格式附件等多种格式的邮件信息。

B.       进程是一个正在执行程序。

C.       Content-Transfer-Encoding指定对邮件主体的编码、解码方法,

D.       Base64主要思想是将输入的数据编码成只有64个可打印字符的串。

15.CHtmlView类的成员操作函数GoBackA)的作用是

A.       用于导航到历史列表的前一项

B.       用于导航到当前主页或起始页

C.       用于导航到由URL标识的资源,或由完整路径标识的文件

D.       用于停止打开文件

16.Pcap_findalldevs_ex()函数的作用是( A

A.       可用于获取本地机器设备列表

B.       可用于过滤指定设备的数据包

C.       用于释放设备列表

D.       用于设置过滤表达式。

17.SMTP命令HELO的作用是(D

A.       邮件来自何处,说明发信人的电子邮件地址

B.       请求发送邮件内容

C.       说明收件人的电子邮件地址

D.       SMTP客户机问候SMTP服务器

18.C)允许应用进程越过传输层对较低层次协议模块(如IP模块、ICMP模块)直接调用和访问。

a.       数据报套接字

b.       流式套接字

c.        原始套接字

d.       阻塞套接字

19.CAsyncsocket类操作类成员函数Connect的作用是( C

A.       接受连接请求

B.       将套接字和本地端口绑定

C.       与远端的套接字建立连接

D.       接受远端套接字发来的数据


 {分页}


二、程序阅读题(40分)

1.课本139CSocket编程服务器、客户端实例

// ClientSocket.cpp : 实现文件

// CClientSocket 成员函数

//1  当客户端套接字收到FD_READ消息时,执行此函数

void CClientSocket::OnReceive(int nErrorCode){

    CSocket::OnReceive(nErrorCode);

    //调用CClientDlg类的相应函数处理

    if (nErrorCode==0) m_pDlg->onReceive(); //1  调用OnReceive函数接收服务器数据

}

// ClientDlg.cpp : 实现文件

void CClientDlg::OnClickedButtonLogin(){

    m_pSocket=new CClientSocket(this);   //创建套接字

    if (!m_pSocket->Create()) //1  创建套接字对象的底层套接字 

    {    //错误处理

    }

    if (!m_pSocket->Connect(m_strServerName,m_nServerPort)) //1  连接聊天室服务器

    {    //错误处理

    }

    m_pFile=new CSocketFile(m_pSocket);//1 创建CSocketFile类对象  

    m_pArchiveIn=new CArchive(m_pFile,CArchive::load); //1  创建用于输入的CArchive类对象

    m_pArchiveOut=new CArchive(m_pFile,CArchive::store);

    //向服务器发送消息,表明新客户进入聊天室

    UpdateData(TRUE);//1  更新控件成员变量

    CString strTemp;

    strTemp=m_strUserName+_T(":昂首挺胸进入聊天室!!!");

    SendMyMessage(strTemp,FALSE);

}

//接收消息处理函数

void CClientDlg::ReceiveMessage(void){

    CMessage msg;

    TRY {

        msg.Serialize(*m_pArchiveIn);//1    调用消息对象的序列化函数,接收消息

        m_listCRoom.AddString(msg.m_strMessage);//1    接受到的消息显示在列表框

    }CATCH(CFileException, e) {

        //错误处理

    }

}

// ClientSocket.cpp : 实现文件

// CClientSocket 成员函数

//套接字收到数据时,自动调用此函数

void CClientSocket::OnReceive(int nErrorCode)  {

    CSocket::OnReceive(nErrorCode);

    m_pDlg->onReceive(this);//1  调用主对话框中的处理函数

}

void CClientSocket::Init(void){

    m_pFile=new CSocketFile(this,TRUE);  // 2 创建与CClientSocket绑定的CSocketFile对象

    m_pArchiveIn=new CArchive(m_pFile,CArchive::load);  //3 创建与m_pFile绑定的CArchive对象,用于接收数据

    m_pArchiveOut=new CArchive(m_pFile,CArchive::store); //4 创建与m_pFile绑定的CArchive对象,用于发送数据

    //CArchive对象不管是加载(接受)还是存储(发送),给定的CArchive对象只能在一个方向上传递数据,所以需要定义两个对象

    //一个用于发送数据,一个用于接受数据

}

//发送消息序列化

void CClientSocket::SendMessage(CMessage* pMsg){

    if (m_pArchiveOut!=NULL){

        pMsg->Serialize(*m_pArchiveOut); //5   


        //当把需要发送的数据都写入到CArchive对象后,还必须调用flush函数来刷新CArchive

        //对象的缓冲区,这是数据才真正从网络上发送出去,否则接收端就收不到数据

        m_pArchiveOut->Flush();

    }

}

// ServerDlg.cpp : 实现文件

//单击启动服务器按钮的事件处理函数

void CServerDlg::OnClickedButtonStart(){

    m_pServerSocket=new CServerSocket(this);  //1 创建服务器套接字对象,将当前对话框类的指针传给ServerSocket

    if (!m_pServerSocket->Create(m_nServerPort))  //1 创建监听套接字的底层套接字,用于在指定端口侦听

    {    //错误处理

    }

    if (!m_pServerSocket->Listen()) //1 启动服务器侦听套接字,可以随时接收来自客户机的请求

    {    //错误处理

    }

}

//服务器处理来自客户机的连接请求并在服务器端维护一个链接列表

void CServerDlg::onAccept(void){

    //创建服务器端连接客户机的套接字

    CClientSocket* pSocket=new CClientSocket(this);  //this 将当前对话框类的指针传给ClientSocket

    if (m_pServerSocket->Accept(*pSocket)){  //1 接受客户的连接请求 

        CString strTemp;

        strTemp.Format(_T("当前在线人数:%d"),m_ClientsList.GetCount()); //1  更新在线人数

        m_staOnline.SetWindowTextW(strTemp);

    }

}

//服务器处理来自客户机的消息

void CServerDlg::onReceive(CClientSocket* pSocket){

    static CMessage msg;

    do {

        pSocket->ReceiveMessage(&msg);//1  接收客户端发来的消息

        m_listSroom.AddString(msg.m_strMessage);//加入到服务器列表框

        sendToClients(&msg);//1   转发给所有客户机

    }while(!((pSocket->m_pArchiveIn)->IsBufferEmpty()));

}

//8  服务器向所有客户机转发来自某一客户机的消息

void CServerDlg::sendToClients(CMessage* pMsg){

    for (POSITION pos=m_ClientsList.GetHeadPosition();pos!=NULL;){

        CClientSocket* pSocket1=(CClientSocket*)m_ClientsList.GetNext(pos);

        pSocket1->SendMessage(pMsg);

    }

}


2.课本240 FTP客户机编程实例

// FtpClientDlg.cpp : 实现文件一部分

//connect函数实现连接到服务器

BOOL CFtpClientDlg::Connect(CString serverName, CString userName, CString password){

    //1    CInternetSession对象 创建并初始化Internet会话

    m_pFTPSession=new CInternetSession(AfxGetAppName(),1,

            PRE_CONFIG_INTERNET_ACCESS);

    try{

        //1 GetFtpConnection 试图建立FTP连接

        //1  m_pConnection对象 是CFtpConnection对象,管理FTP服务

        m_pConnection=m_pFTPSession->GetFtpConnection(serverName,userName,password);

    }catch (CInternetException* e){

    }

    return TRUE;

}

//显示服务器当前目录下的所有文件与子目录

void CFtpClientDlg::DisplayContent(LPCTSTR lpctstr,CString currentDir){

    UpdateData(TRUE);

    Connect(m_strServerName,m_strUserName,m_strPassword);

    m_pConnection->SetCurrentDirectory(currentDir);  //1  设置当前FTP目录

    m_listDirectory.DeleteAllItems();  //1  清空列表框所有项目

    m_pFileFind=new CFtpFileFind(m_pConnection); //1  CFtpFileFind类帮助FTP服务器查找文件

    BOOL bFound;

    bFound=m_pFileFind->FindFile(lpctstr);//1  查找所有文件


    CString strFileName;//文件名

    CString strFileTime; //文件修改时间

    CString strFileLength; //文件大小

    while(bFound){                            

        bFound= m_pFileFind->FindNextFile(); //1 查找下一个文件

        strFileName=m_pFileFind->GetFileName(); //1  文件名

        FILETIME ft;

        m_pFileFind->GetLastWriteTime(&ft);  

        CTime FileTime(ft);

        strFileTime = FileTime.Format("%y-%m-%d");

      }//end while

      UpdateData(FALSE);

}

//upload函数实现上传文件

void CFtpClientDlg::Upload(void){

      CString strSourceName;  //源文件名

      CString strDestName;    //目标文件名

      CFileDialog dlg(TRUE,_T(""),_T("*.*"));

      if (dlg.DoModal()==IDOK){

        //1  获得待上传的本地文件路径和文件名

        strSourceName = dlg.GetPathName();

        strDestName = dlg.GetFileName();

                    

        //1   调用CFtpConnect类中的PutFile函数上传文件

        if (m_pConnection->PutFile(strSourceName,strDestName))

            AfxMessageBox(_T("上传成功"),MB_OK|MB_ICONINFORMATION);

        else

            AfxMessageBox(_T("上传失败"),MB_OK|MB_ICONSTOP);

      }

    DisplayContent(_T("*"));

}

//Download函数实现下载文件

void CFtpClientDlg::Download(void){

    int index=m_listDirectory.GetNextItem(-1,LVNI_SELECTED);  //点击一个Item的时候,希望获得这个Item的Index

    if (index==-1){

        AfxMessageBox(_T("请首先选择要下载的文件!"),MB_OK | MB_ICONQUESTION);

    }else{

        CString strType=m_listDirectory.GetItemText(index,2);//得到选择项的类型

        if (strType!="<子目录>"){   //选择的是文件

            CString strDestName;

            CString strSourceName;

            strSourceName = m_listDirectory.GetItemText(index,0);//1  得到所要下载的文件名

            CFileDialog dlg(FALSE,_T(""),strSourceName);                          

            if (dlg.DoModal()==IDOK){

                 //1 获得下载文件在本地机上存储的路径和名称

                strDestName=dlg.GetPathName();               

                //1   调用CFtpConnect类中的GetFile函数下载文件

                if (m_pConnection->GetFile(strSourceName,strDestName))

                    AfxMessageBox(_T("下载成功!"),MB_OK|MB_ICONINFORMATION);

                else

                    AfxMessageBox(_T("下载失败!"),MB_OK|MB_ICONSTOP);

             }

         }

     }

}

//显示下级子目录

void CFtpClientDlg::DisplaySubDir(void){

    //得到所选择的文本

    int index=m_listDirectory.GetNextItem(-1,LVNI_SELECTED);

    strSub = m_listDirectory.GetItemText(index,0);

    if (index==-1){

        AfxMessageBox(_T("没有选择目录!"),MB_OK | MB_ICONQUESTION);

    }else{  

         //1   判断是不是目录

        if (_T("<子目录>")!=m_listDirectory.GetItemText(index,2)){

            AfxMessageBox(_T("不是子目录!"),MB_OK | MB_ICONSTOP);

        }else{

            //1   设置当前目录

            strCurrentDirectory.Format(_T("%s%s"),strCurrentDirectory,strSub);

            m_pConnection->SetCurrentDirectory(strCurrentDirectory);


            //对当前目录进行查询

            DisplayContent(_T("*"),strCurrentDirectory);

        }

    }             

}


{分页}


三、程序编写题(16分)

1.      课本273SMTP协议编程实例

// SmtpSocket.cpp : 实现文件一部分

//1  SMTP服务器接收了客户端连接请求时执行

void CSmtpSocket::OnConnect(int nErrorCode){

              CAsyncSocket::OnConnect(nErrorCode);

              if(nErrorCode==0)  m_pDlg->Disp(S_CONNECT);  //执行对话框类的Disp函数

}

//当接收到SMTP服务器的消息时

void CSmtpSocket::OnReceive(int nErrorCode)

{

              CAsyncSocket::OnReceive(nErrorCode);

              if(nErrorCode==0)

              {

                             char buff[MAX_BUFF];             //接收缓冲区

                             int rec=Receive(buff,MAX_BUFF);  //1  接收服务器发来的数据

                             buff[rec]=NULL;                  //结尾置为NULL

                             lastMsg=buff;

                             AnalyzeMsg();             //1   分析收到的数据,作不同的处理

              }  else  {

                             error="接收期间发生了错误!\r\n";

                             m_pDlg->Disp(S_CLOSE);   //显示信息

              }

}

//客户端与服务器实现SMTP会话

void CSmtpSocket::AnalyzeMsg()

{

              CString s;

              strstream str;    //strstream类同时可以支持C风格的串流的输入输出操作

              string check;

              str<<(LPCTSTR)lastMsg;  //

              str>>check;             //

              //根据smtp会话所处的状态做出不同的处理       

              switch(state)        {

              case EHLO:

                             m_pDlg->Disp(S_RECEIVE);

                             if(!(check=="250")) {}

                             s.Format(_T("AUTH LOGIN%c%c"),13,10); //1

                             Send((LPCTSTR)s,s.GetLength()); // 1  发送AUTH LOGIN命令

                             state=AUTH;

                             break;

 

              case AUTH:

                             m_pDlg->Disp(S_RECEIVE);

                             if(!(check=="334")) {}

                             coder.Encode(m_pDlg->m_strUserName);  // 2  用户名Base64编码

                             s.Format(_T("%s%c%c"), coder.EncodedMessage(),13,10);

                 // AfxMessageBox(s);

                             Send((LPCTSTR)s,s.GetLength()); //发送用户名

                              

                             state=USER;

                             break;

              }

              m_pDlg->m_listInfo.AddString(s);

              m_pDlg->UpdateData(FALSE);

}

// SmtpClientDlg.cpp : 实现文件一部分

//“发送邮件:按钮

void CSmtpClientDlg::OnClickedButtonSend()

{

                  //设定smtp类的变量,使之指向本对话框,以便传递信息

                  smtpSocket.setParentDlg(this);

                  UpdateData(TRUE);         //取来用户在对话框中输入的数据

                  smtpSocket.Create();      //1   创建套接字对象的底层套接字

                  smtpSocket.Connect((LPCTSTR)m_strSmtpServer,m_nServerPort);    //1  连接SMTP服务器,如果连接成功指向SmtpSocket.cpp  onConnet函数

                  UpdateData(FALSE);           //更新用户界面

}

//根据不同的情况,向用户显示不同的信息

void CSmtpClientDlg::Disp(LONG flag)

{

                  CString s;

                  switch(flag)

                  {

                  case S_RECEIVE: //1    收到服务器发来的数据,显示该数据

                                      m_listInfo.AddString(smtpSocket.lastMsg);    //1

                                      break;

                  }

                  UpdateData(FALSE);   //更新用户界面

}

 

2.课本284POP协议编程实例

// Pop3ClientDlg.cpp : 实现文件

//"连接并收取邮件"按钮

void CPop3ClientDlg::OnClickedButtonConnect()

{

      m_pop3ClientSocket.SetParentDlg(this);

      UpdateData(TRUE); 

      m_pop3ClientSocket.Create();   //创建套接字对象的底层套接字

      m_pop3ClientSocket.Connect((LPCSTR)m_strServerName,110); //1 连接pop3服务器

      m_bDelMail=FALSE;

      m_mailInfo = "";                //多文本列表框清空

      m_MailContent.Clear();

      UpdateData(FALSE);          //1  更新用户界面

}

//"查看邮件"按钮

void CPop3ClientDlg::OnClickedButtonBrowsemail()

{

      int index;

      index = m_comboTitle.GetCurSel();  //1   获得用户在组合框中的选择

      //获得并显示指定信件的基本属性及信件内容

      m_mailInfo="";

      m_mailInfo += m_pop3ClientSocket.GetMsgStuff(index);

      m_mailInfo += m_pop3ClientSocket.GetMsgBody(index);

      UpdateData(FALSE);

}

// m_pop3ClientSocket.cpp : 实现文件

// CPop3ClientSocket 成员函数

//1    连接上服务器

void CPop3ClientSocket::OnConnect(int nErrorCode){

      CAsyncSocket::OnConnect(nErrorCode);

      if(nErrorCode==0)  m_pDlg->DisplayInfo(S_CONNECT); //1 已连接到服务器,显示信息

}

void CPop3ClientSocket::AnalyzeMsg()

{

      str<<(LPCSTR)lastMsg; //将收到的信息拷贝到字符流变量中 

      str>>check;           //提取所收到信息的第一段代码

              

      //如果没有错误,则根据不同的会话阶段响应来处理

      switch(state)

      {

      case FIRST: //如果已经连接成功,类初始化的时候stateFIRST

                     msgs.clear();

                     //显示连接成功后服务器返回的消息

                     m_pDlg->DisplayInfo(S_RECEIVE);

                     //1发送 user 用户名 命令

                     s.Format("user %s%c%c",m_pDlg->m_strMailBox,13,10);

                     Send((LPCSTR)s,s.GetLength()); //1  发送用户帐号

                     state=USER;

                     break;

 

      case USER:

                     //显示服务器对于user命令的响应

                     m_pDlg->DisplayInfo(S_RECEIVE);

                     // 1 发送 pass 口令 命令,发送密码

                     s.Format(_T("pass %s%c%c"),m_pDlg->m_strPassword,13,10);

                     Send((LPCSTR)s,s.GetLength()); //1

                     state=PASS;

                     break;

      }

      m_pDlg->m_mailInfo+=s;// 增加上去

}


 {分页}


四、简答题(20分)

1.简述使用CAsyncsocket类编程服务器的编程步骤。P135

(1)    CAsyncSocket sockListen;//创建服务器侦听套接字对象

(2)    sockListen.Create(nPort);//创建SOCKET句柄,绑定到指定端口

(3)    sockListen.Listen();//启动监听,时刻准备接受客户连接请求

(4)    CAsyncSocket sockServer;//创建一个新的服务器套接字对象

        sockListen.Accept(sockServer);//接受新连接

(5)    sockServer.Receive(pBuf,nLen);//接收数据

        或sockServer.Send(pBuf,nLen);//发送数据

        或两者

(6)    sockServer.ShutDown();//禁用服务器套接字某些操作

(7)    sockServer.Close();//关闭服务器套接字

(8)    sockListen.Close();//关闭服务器侦听套接字

2.简述使用CAsyncsockett类编程客户机的编程步骤。P135

(1)    CAsyncSocket sockClient; //创建客户机套接字对象

(2)    sockClient.Create();//创建SOCKET句柄,自动选择本地可用端口

(3)    sockClient.Connect(strAddr,nPort); //请求连接到服务器 

(4)    sockClient.Send(pBuf,nLen);//发送数据

        或sockClient.Receive(pBuf,nLen); //接收数据

        或两者

(5)    sockClient.ShutDown();//禁用客户机套接字某些操作

(6)    sockClient.Close();//关闭客户机套接字

3.阻塞、非阻塞、异步工作模式的特点。

阻塞模式:在发出一个功能调用后,在没有得到结果之前,该调用不返回。(只有一件事情做完了,才能做下一件事情)

非阻塞模式:在发出一个功能调用后,在没有得到结果之前,该调用不会阻塞,而是返回一个错误码。

异步模式:套接字发出调用后不需要知道调用的结果就立即返回,剩下的工作交给系统消息驱动机制。系统侦测到结果后会向套接字发出通知消息,套接字再回调相应的函数进行处理.

 

4.简述用户界面线程特点,简述工作线程的特点。

1、用户界面线程(UI线程):封装消息循环,该线程可以创建并撤销窗口。由CWinApp类派生的新类都是用户界面线程,一个应用程序可以创建多个UI线程。用来处理用户输入和响应用户事件的线程。

2、工作线程:没有消息循环,不能处理系统事件和窗口消息,也不能关联窗口。可以使用工作线程完成经常性的、耗费机时的数据处理工作,如网络通信、后台计算、打印机的后台打印等

 

5.创建工作线程的步骤。

创建工作线程的步骤(一般不必从CWinThread派生一个类)

1、实现工作线程的控制函数

     控制函数实现线程的功能逻辑,当控制函数开始执行时,线程开始启动;控制函数结束退出时,线程也跟着结束。

Unit MyControllingFunctionLPVOID pParam

 

2、用AgfxBeginThread函数创建启动线程。

 


推荐您阅读更多有关于“”的文章

  • 8
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值