【转】GPRS开发系列文章之进阶篇

GPRS开发参考源码 基于GPRS的远程家电控制系统之GPRS开发参考源码,可根据此进行SMS短信、通话、GPS定位多功能开发。 立即下载

GPRS 开发系列文章之进阶篇

相关文章: GPRS开发系列文章之入门篇

         GPRS开发系列文章之实战篇

一、前言

在前篇《 GPRS 开发系列文章之入门篇 》里,我主要对 GPRS 开发中遇到的一些常用概念和一些业务逻辑做了简单的介绍,没想到得到了很多网友的支持和关注,因昨天有事因此延迟到今天才奉上这篇进阶系列文章,还请各位见谅。希望大家支持同时欢迎拍砖,共同提高。

在最后一篇《 GPRS 开发系列文章之实战篇 》我将详细叙述如何利用类库开发 Client 和 Server 端通信程序,因此本文的多数讲解将是为下文服务的。本文将向您介绍基于 PPC2003 的 Windows mobile 系列的客户端和基于 .Net 2005 的服务器端进行开发所需掌握和了解的开发库,并着重围绕客户端进行 GPRS 连接所用到的一些 API 函数进行讲解。本文的最后是一些用于引用和学习用的链接和利用 API 建立 GPRS 连接的 demo ,感兴趣的同志可以去点击或下载后进行深入研究。
   
关于客户端 API 的叙述我基本上都是翻译过来的,如欠妥还请各位多多斧正 !同时demo程序我也是只做了部分加工,主要都是参照了谢红伟 的发表的文章(后面有引用链接)

二、进阶系列篇详解

1.       客户端建立 GPRS 连接 API

客户端开发采用 EVC4.0 进行开发,主要讲解的类库为 Connection Manager 系列 API ,客户端在进行 GPRS 拨号连接时将使用下文所介绍的 API 。

Connection Manager( 本人译为 连接管理器,此对象为一系列 API 的集合 ) 系列 API 的主要目的是为了集中管理基于 Windows Mobile 系列的设备网络连接的建立与维护。移动应用程序使用 连接管理器 API 去建立或规划一个网络连接,而连接管理器则掌控连接过程中的所有状态信息 . 应用程序在要发起一个连接 ( 比如 Internet) ,只要简单的告知连接管理器就 OK 了。

当一个应用程序发起一个网络连接的请求时,连接管理器首先从连接服务提供商( CSPS )处获取所有可能的连接信息,然后连接管理器会从这一系列连接信息中根据开销,延迟、带宽等因素来选择一个最佳的连接,最后连接管理器将被请求的连接排入队列,然后在一个适合的时间使用 CSPS 来建立连接。     

【 API 函数】:

a)       ConnMgrApiReadyEvent ()函数
函数原型: HANDLE WINAPI ConnMgrApiReadyEvent();
利用此函数来我们可以返回一个连接事件的句柄 ,注意在的得到句柄后要记得及时释放

b)       ConnMgrConnectionStatus () 函数
函数原型:
HRESULT WINAPI ConnMgrConnectionStatus(HANDLE hConnection ,DWORD * pdwStatus );
利用此函数的返回值 pdwStatus ,我们可以得到很多的关于连接的信息,例如如果我们连接成功将返回 CONNMGR_STATUS_CONNECTED ,断开连接将返回 CONNMGR_STATUS_DISCONNECTED, 他的返回状态信息非常丰富,有 14 中之多,完全可以满足我们的应用需要;

c)        ConnMgrEnumDestinations() 函数
函数原型:
HRESULT WINAPI ConnMgrEnumDestinations(int nIndex ,CONNMGR_DESTINATION_INFO * pDestInfo )
;
一般我们的 PDA 在连接 GPRS 时都有好几个连接,利用此函数我们可以枚举出所有可用的连接,然后再对挑选的连接进行筛选得到一个最佳连接

接下来讲两个很重要的函数,我们将利用两个函数中的一个来发起连接,他们是:

d)       ConnMgrEstablishConnection() 和 ConnMgrEstablishConnectionSync() 函数,这两个函数一个用于发起一个异步连接请求,一个用于同步请求,使用异步连接请求我们可以在发起连接后立即返回,而使用同步请求客户端将一直被阻塞知道函数返回确认连接,关于异步和同步我就不再叙述;
它们的原型依次为:
HRESULT WINAPI ConnMgrEstablishConnection( CONNMGR_CONNECTIONINFO * pConnInfo , HANDLE * phConnection );
HRESULT WINAPI ConnMgrEstablishConnectionSync(   CONNMGR_CONNECTIONINFO * pConnInfo , HANDLE * phConnection ,    DWORD dwTimeout , DWORD * pdwStatus );
     
可以看到两个函数的第一个参数都为一个 CONNMGR_CONNECTIONINFO 对象,此对象为一个结构体,它保存了客户端发起连接请求的一系列信息,因此,在我们调用此函数时必须构造一个该对象,然后将其作为参数传入连接函数中。这里很有必要讲一下该结构体,该结构体的原型如下:
typedef struct _CONNMGR_CONNECTIONINFO
{
     DWORD cbSize ;   DWORD dwParams ;DWORD dwFlags ;

           DWORD dwPriority ;BOOL bExclusive ;BOOL bDisabled ;GUID guidDestNet ;

           HWND hWnd ;  UINT uMsg ;  LPARAM lParam ;ULONG ulMaxCost ;   ULONG ulMinRcvBw ;  
      ULONG ulMaxConnLatency ;

        } CONNMGR_CONNECTIONINFO;
其中参数 dwFlags 用于指定我们的接入点,比如我们常说的 CMNER 和 CMWAP ,而参数 GUID 则标志了 我们对应于每个接入点的全球唯一标志符,关于如何得到或者查看 GUID ,我们可以在 “/Program Files/Windows CE Tools/wce420/POCKET PC 2003/Include/Armv4” 目录下查看 connmgr.h 文件,里面包含了各个接入点的 GUID ,例如:

CMNET 为: (0x436ef144, 0xb4fb, 0x4863, 0xa0, 0x41, 0x8f, 0x90, 0x5a, 0x62, 0xc5, 0x72)

  CMWAP 为: 0x7022e968, 0x5a97, 0x4051, 0xbc, 0x1c, 0xc5, 0x78, 0xe2, 0xfb, 0xa5, 0xd9

如果想更进一步了解,我们还可以通过查看注册表方式来查看PDA上连接管理器的相关连接信息,在PPC 2003中注册表路径为:

[HKEY_LOCAL_MACHINE/Comm/ConnMgr],如下图所示:

 

在Destinations一项中就对应我们所有可用的网络连接,这个跟用ConnMgrEnumDestinations() 方法得到的是一样的效果,在默认Internet设置中我们将看到CMNET的GUID,如下所示:

 

在这里里面有DestId一项,就对应着我们久违的GUID

e)       ConnMgrReleaseConnection 函数
我们在上一步中建立连接后我们将得到一个连接句柄,在重新开始一个新的连接或者断开连接都要调用此函数来释放掉之前创建的连接,它的原型为:
HRESULT WINAPI ConnMgrReleaseConnection( HANDLE hConnection ,BOOL bCache );

【连接管理 API 大致使用步骤】:

首先我们利用 ConnMgrApiReadyEvent() 函数来确认是否有可用连接,如果有可用连接我们则利用 ConnMgrEnumDestinations() 函数枚举所有可用连接,然后遍历所有连接调用我们的同步或异步连接方法 ConnMgrEstablishConnectionSync() 与 ConnMgrEstablishConnection() 来发起连接,一旦连接成功后我们就可以进行我们伟大的下一步了,就是和我们的服务器进行通信。
【 GPRS demo 效果图】

 

 

【 GPRSDemo 介绍】

GPRSDemo 主要利用了上述的几个重要的 API 函数来获取当前可用连接,并自动选择一个最佳的连接途径,然后启用这个连接,在连接启动成功以后再用 socket 进行网络连接,与公网服务器进行通信。

首先检查是否有可用连接

 

BOOL CConnectManager::GetConnMgrAvailable()
{
    HANDLE hConnMgr 
=  ConnMgrApiReadyEvent ();
    BOOL bAvailbale 
=  FALSE;
    DWORD dwResult 
=  ::WaitForSingleObject ( hConnMgr,  2000  );
    
if  ( dwResult  ==  WAIT_OBJECT_0 )
    {
        bAvailbale 
=  TRUE;
    }
    
//  关闭
     if  ( hConnMgr ) CloseHandle ( hConnMgr );

    
return  bAvailbale;
}
                 然后枚举所有可用连接:
                
void  CConnectManager::EnumNetIdentifier ( OUT CStringArray  & StrAry )
{
    CONNMGR_DESTINATION_INFO networkDestInfo 
=  { 0 };

    
//  得到网络列表
     for  ( DWORD dwEnumIndex = 0 ; ; dwEnumIndex ++  )
    {
        memset ( 
& networkDestInfo,  0 ,  sizeof (CONNMGR_DESTINATION_INFO) );
        
if  ( ConnMgrEnumDestinations ( dwEnumIndex,  & networkDestInfo )  ==  E_FAIL )
        {
            
break ;
        }
        StrAry.Add ( networkDestInfo.szDescription );
    }
}

接下来找到 “Internet” 这个连接,可用远程 URL 映射的方式来完成,这样可以让系统自动选取一个最好的连接。

int  CConnectManager::MapURLAndGUID ( LPCTSTR lpszURL, OUT GUID  & guidNetworkObject, OUT CString  * pcsDesc /* =NULL */  )
{
    
if  (  ! lpszURL  ||  lstrlen(lpszURL)  <   1  )
        
return  FALSE;

    memset ( 
& guidNetworkObject,  0 ,  sizeof (GUID) );
    
int  nIndex  =   0 ;
    HRESULT hResult 
=  ConnMgrMapURL ( lpszURL,  & guidNetworkObject, (DWORD * ) & nIndex );
    
if  ( FAILED(hResult) )
    {
        nIndex 
=   - 1 ;
        DWORD dwLastError 
=  GetLastError ();
        AfxMessageBox ( _T(
" Could not map a request to a network identifier " ) );
    }
    
else
    {
        
if  ( pcsDesc )
        {
            CONNMGR_DESTINATION_INFO DestInfo 
=  { 0 };
            
if  ( SUCCEEDED(ConnMgrEnumDestinations(nIndex,  & DestInfo)) )
            {
                
* pcsDesc  =  DestInfo.szDescription;
            }
        }
    }

    
return  nIndex;
}


最后启用指定编号的连接并检查连接状态

 

BOOL CConnectManager::EstablishConnection ( DWORD dwIndex )
{
    
//  释放之前的连接
    ReleaseConnection ();

    
//  得到正确的连接信息
    CONNMGR_DESTINATION_INFO DestInfo  =  { 0 };
    HRESULT hResult 
=  ConnMgrEnumDestinations(dwIndex,  & DestInfo);
    BOOL bRet 
=  FALSE;
    
if (SUCCEEDED(hResult))
    {
        
//  初始化连接结构
        CONNMGR_CONNECTIONINFO ConnInfo;

        ZeroMemory(
& ConnInfo,  sizeof (ConnInfo));
        ConnInfo.cbSize 
=   sizeof (ConnInfo);
        ConnInfo.dwParams 
=  CONNMGR_PARAM_GUIDDESTNET;
        ConnInfo.dwFlags 
=  CONNMGR_FLAG_PROXY_HTTP  |  CONNMGR_FLAG_PROXY_WAP  |  CONNMGR_FLAG_PROXY_SOCKS4  |  CONNMGR_FLAG_PROXY_SOCKS5;
        ConnInfo.dwPriority 
=  CONNMGR_PRIORITY_USERINTERACTIVE;
        ConnInfo.guidDestNet 
=  DestInfo.guid;
        ConnInfo.bExclusive    
=  FALSE; 
        ConnInfo.bDisabled 
=  FALSE;

        DWORD dwStatus 
=   0 ;
        hResult 
=  ConnMgrEstablishConnectionSync( & ConnInfo,  & m_hConnection,  10 * 1000 ,  & dwStatus );
        
if (FAILED(hResult))
        {
            m_hConnection 
=  NULL;
        }
        
else  bRet  =  TRUE;
    }

    
return  bRet;
}

 

检测连接状态

 


BOOL CConnectManager::WaitForConnected ( int  nTimeoutSec, DWORD  * pdwStatus /* =NULL */  )
{
    DWORD dwStartTime 
=  GetTickCount ();
    BOOL bRet 
=  FALSE;
    
while  ( GetTickCount () - dwStartTime  <  (DWORD)nTimeoutSec  *   1000  )
    {
        
if  ( m_hConnection )
        {
            DWORD dwStatus 
=   0 ;
            HRESULT hr 
=  ConnMgrConnectionStatus ( m_hConnection,  & dwStatus );
            
if  ( pdwStatus )  * pdwStatus  =  dwStatus;
            
if  ( SUCCEEDED(hr) )
            {
                
if  ( dwStatus  ==  CONNMGR_STATUS_CONNECTED )
                {
                    bRet 
=  TRUE;
                    
break ;
                }
            }
        }
        Sleep ( 
100  );
    }

    
return  bRet;
}
                   最后要记得释放连接
void  CConnectManager::ReleaseConnection ()
{
    
if  ( m_hConnection )
    {
        ConnMgrReleaseConnection(m_hConnection, FALSE);
        m_hConnection 
=  NULL;
    }
}

 

2.       客户端与服务器端进行 socket 通信 API
socket 通信相关开发 API 在 Winsock2.h. 文件中定义,因为 SOCKET 通信不是本文的重点但是又是必须要涉及的

a)       WSAStartup 函数。在应用程序进行 Windows Sockets 通信时,必须首先调用此函数来指定应用程序要加载的 Windows Scoket 版本等信息,应用程序结束前我们应该调用 WSACleanup 去释放掉所用的系统资源

b)       Connect 函数。此函数用来建立连接

c)        Select 函数。建立连接后,用来侦听是否有数据传输

d)       Send 函数。用于给服务器发送消息

3.       服务器端与客户端进行 socket 通信
服务器端主要涉及到的库为:
System.Net
, System.Net.Sockets , System.IO;
System.Net 命名空间为当前网络上使用的多种协议提供了简单的编程接口, System.Net.Sockets 命名空间为需要严密控制网络访问的开发人员提供了 Windows Sockets (Winsock) 接口的托管实现。
System.IO
命名空间包含允许读写文件和数据流的类型以及提供基本文件和目录支持的类型。
需要了解的技术有:多线程,事件与委托, SOCKET 通信等

 

 

三、           引用(参考)文章地址

1.       http://msdn.microsoft.com/en-us/library/ms827527.aspx ( MSDN 移动开发中心);

2.       http://www.codeguru.com/cpp/w-p/ce/pocketpc/article.php/c7355/ ( PPC 应用程序 Internet 连接);

3.       http://www.vckbase.com/document/viewdoc/?id=1803 (如何建立 GPRS 连接)

4.       http://www.microsoft.com/china/msdn/library/NetFramework/netcompactframework/understandingnetcfFAQ.mspx?mfr=true (常见开发问题解答)

5.       PPC SDK 参考(安装 ppc 2003 SDK 后才有)

6.    GPRS Demo下载

simcom 4G完整应用代码以及使用说明(无源码文件) simcom 4G完整应用代码以及使用说明,包括电路设计,驱动设计、配置网络、4g通信等 立即下载

相关推荐

OpenEuler内核编译及替换

一、内核源码下载 在gitee上下载OpenEuler内核源码 下载地址 选择需要的内核版本源码压缩包进行下载 二、内核编译 1.解压缩 将下载好的源码进行解压 tar xvf openeuler-kernel-4.19.90-2107.1.0.tar.gz 2.清理源代码树 解压后得到一个名为kernel的内核源码文件夹,进入后执行命令 make mrproper 清理过去内核编译产生的config,第一次编译时可不执行此命令 3.生成内核配置文件.config 先将将系统原配置文件拷贝过来,原

m0_56602092的博客 2万+

GPRS开发系列文章之进阶篇

GPRS开发系列文章之进阶篇 相关文章:GPRS开发系列文章之入门篇          GPRS开发系列文章之实战篇 一、前言 在前篇《GPRS开发系列文章之入门篇》里,我主要对GPRS开发中遇到的一些常用概念和一些业务逻辑做了简单的介绍,没想到得到了很多网友的支持和关注,因昨天有事因此延迟到今天才奉上这篇进阶系列文章,还请各位见谅。希望大家支持同时欢迎拍砖,共同提高。 在最后一篇《G...

weixin_34255793的博客 168

Human3.6M 数据集介绍及下载

360 万张 3D 人体姿势和对应图像11 名专业演员(6 男 5 女)7 个场景(讨论、吸烟、拍照以及打电话等等)

XavierJ的博客 3万+

GPRS开发系列文章之实战篇

  GPRS开发系列文章之实战篇 相关文章:GPRS开发系列文章之入门篇             GPRS开发系列文章之进阶篇   一、前言 在前篇《GPRS开发系列文章之进阶篇》里,我主要详细讲解了客户端进行GPRS连接的常用API,并对GPRSdemo测试程序中的连接类ConnManager中的一些重要函数做了说明,最后稍微提及了下服务器端要用到的一些类库。今天,在这篇实战篇中,...

weixin_33860553的博客 191

基于STM32F407的定时器以及定时器中断的实现

基于STM32F407的定时器以及定时器中断的实现

weixin_57941207的博客 5228

故障诊断 | CNN-BiGRU-Attention故障诊断

故障诊断 | CNN-BiGRU-Attention故障诊断

机器学习之心的博客,关注并私信文章链接,获取对应文章源码和数据。 673

【STM32 .Net MF开发板学习-27】GPRS通信实现

GPRS是General Packet Radio Service(通用分组无线服务技术)的简称,它是GSM移动电话用户可用的一种移动数据业务。GPRS和以往连续在频道传输的方式不同,是以封包(Packet)式来传输。我们基于.NET Micro Framework 4.1平台,开发了YFSoft.Hardware.GPRS库,通过该库,用户简单调用相关接口,就可以实现GPRS通信。 我们所选用...

weixin_34184561的博客 271

系统架构设计师【第1章】: 绪论 (核心总结)

系统架构 (System Architecture)是系统的一种整体的高层次的结构表示,是系统的骨架和根基,也决定了系统的健壮性和生命周期的长短。系统架构设计师是承担系统架构设计的核心角色,他不仅是连接用户需求和系统进一步设计与实现的桥梁,也是系统开发早期阶段质量保证的关键角色。通俗地说,系统架构 (System Architecture)

数据知道的博客 1万+

GPRS开发系列文章之入门篇

  GPRS开发系列文章之入门篇 要做GPRS方面的应用软件开发,除了必备的一些程序设计知识之外,对计算机网络通信这些专业术语的了解可是一个都不能少,本人并不是专职于移动开发,所以在搞开发时也遇到了很多困难。出于这种考虑,我也想写个GPRS开发系列入门文章,服务于各位还正在搜索资料的同仁们(开发者抑或PDA爱好者等都行),同时欢迎各位移动开发的高手指点,共同提高。 接下来的文章依次为...

weixin_33737134的博客 206

DirectX function “GetDeviceRemovedReason“ failed with DXGI_ERROR_DEVICE_HUNG (“The GPU will not resp

游戏报错"DXGI_ERROR_DEVICE_HUNG"的解决方案 在使用RTX 40系显卡运行FIFA 23等游戏时,可能出现DirectX报错导致游戏崩溃。这主要由于最新显卡驱动与DirectX 12的兼容性问题。解决方法包括: 降级显卡驱动版本 修改游戏配置文件,将DIRECTX_SELECT设为1 在显卡控制面板中关闭垂直同步、抗锯齿、DLSS 3等功能 调整电源模式为性能优先 这些操作可以有效解决因驱动兼容性导致的游戏崩溃问题。

猿小白的博客 3886

YOLO11 改进系列 | 引入2023年 MLCA 的 C3k2_MLCA 模块,近零参数开销的本地-全局通道注意力,适合检测与分割特征增强

本文提出将MLCA(混合局部通道注意力)模块嵌入YOLOv11的C3k2框架中,形成C3k2_MLCA改进结构。该模块通过5×5局部池化和1×1全局池化双路融合,结合ECA式Conv1d生成通道注意力,在几乎不增加参数量的前提下(仅增加66个参数),实现了局部空间信息与全局通道统计的联合建模。相比传统SE和ECA注意力,MLCA保留了空间分布信息,更适合实例分割等需要精细定位的任务。实验表明改进后模型参数量仅增加0.002%,计算量基本不变,是一种高效的注意力增强方案。

qq_44224801的博客 92

GPRS开发系列文章之进阶篇【转】

在前篇《GPRS开发系列文章之入门篇》里,我主要对GPRS开发中遇到的一些常用概念和一些业务逻辑做了简单的介绍,没想到得到了很多网友的支持和关注,因昨天有事因此延迟到今天才奉上这篇进阶系列文章,还请各位见谅。希望大家支持同时欢迎拍砖,共同提高。在最后一篇《GPRS开发系列文章之实战篇》我将详细叙述如何利用类库开发Client和Server端通信程序,因此本文的多数讲解将是为下文服务的。本文

soulforcemw的专栏 549

uniapp - [全端兼容] 实现精美Editor富文本编辑器功能,uniApp全平台兼容的富文本插件组件用户可上传图片及对接服务器存储文件等,手机移动端H5网页富文本/小程序富文本/App富文本!

uni-app,h5移动端网页,微信小程序,支付宝小程序,Android安卓,苹果ios,app,nvue,uniapp富文本编辑器,uniapp中如何实现各平台都兼容的富文本编辑器,Editor富文本插件,uniApp微信小程序富文本,UNI-APP安卓苹果ios系统App端富文本组件,editor富文本编辑器如何实现上传图片,图片上传后不显示怎么办,如何配置图像上传功能,富文本图片上传怎么传到服务器中,获取图片路径,editor插入图片,富文本编辑器上传图片,报错怎么办,跨域CORS处理,配置不行无效

🏆 前端领域优质创作者 1万+

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

GPRS开发系列文章之入门篇【转】

要做GPRS方面的应用软件开发,除了必备的一些程序设计知识之外,对计算机网络通信这些专业术语的了解可是一个都不能少,本人并不是专职于移动开发,所以在搞开发时也遇到了很多困难。出于这种考虑,我也想写个GPRS开发系列入门文章,服务于各位还正在搜索资料的同仁们(开发者抑或PDA爱好者等都行),同时欢迎各位移动开发的高手指点,共同提高。接下来的文章依次为:GPRS开发系列文章之进阶篇(主要讲

soulforcemw的专栏 730

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

GPRS开发系列文章

GPRS开发系列文章之入门篇点击打开链接GPRS开发系列文章之进阶篇点击打开链接GPRS开发系列文章之实战篇点击打开链接

yxmsw2007的专栏 930

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

【转】GPRS开发系列文章之实战篇

GPRS开发系列文章之实战篇相关文章:GPRS开发系列文章之入门篇             GPRS开发系列文章之进阶篇 一、前言在前篇《GPRS开发系列文章之进阶篇》里,我主要详细讲解了客户端进行GPRS连接的常用API,并对GPRSdemo测试程序中的

code09的专栏 642
上一篇: 【转】GPRS开发系列文章之入门篇
下一篇: 【转】GPRS开发系列文章之实战篇
code09
博客等级 码龄18年 31粉丝 56原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值