MC新手入门(五十)------服务器连接 一

服务器是现在网络游戏一个必不可少的部分。例如手机游戏<动友大富翁>、<斗地主>等,这都需要依赖于服务器。下面是一个游戏登录、注册界面,图10-1是游戏登录界面,图10-2是游戏注册界面。

、 10-2.jpg


图10-1

10-1.jpg


图10-2




10.1 概念

Web服务器是网络最重要的服务器,是直接服务于用户的服务器,通俗的讲,Web服务器传送(serves)页面使浏览器可以浏览,然而应用程序服务器提供的是客户端应用程序可以调用(call)的方法(methods)。确切一点,你可以说:Web服务器专门处理HTTP请求(request),但是应用程序服务器是通过很多协议来为应用程序提供(serves)商业逻辑(business logic)。

JSON(JavaScriptObject Notation) 是一种轻量级的数据交换格式。它基于JavaScript(Standard ECMA-262 3rd Edition - December 1999)的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成。

SQL(Structured Query Language)结构化查询语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统

10.2 游戏登录、注册例程实现

下面通过游戏登录、注册的例程,解释如何使用MC工具进行数据库连接。



10.2.1 服务器搭建

1.        准备工作

以下配置的环境都是在window 7下。

首先要到准备一下软件,需要安装软件是MicrosoftVisual Studio 2008、Microsoft SQL Server 2008。

Microsoft SQLServer 20088企业版下载: http://www.microsoft.com/zh-cn/SQLServer/default.aspx

MicrosoftVisual Studio 2008企业版下载: http://www.microsoft.com/visualstudio/zh-cn

务必要把软件安装成功,否则后面的工作无法进行。如有问题可以参考如下网址资料:

http://hi.baidu.com/goodyishao/item/3453c0c69d61e26ff6c95d08

http://blog.sina.com.cn/s/blog_7028ff940100l3i7.html

IIS安装

1)  进入Win7的<控制面板>,选择左侧的<打开或关闭Windows功能>。

2)  现在出现了安装Windows功能的选项菜单,注意选择的项目,我们需要手动选择需  要的功能,下面这张图片把需要安装的服务都已经选择了,大家可以按照图10-3片勾选功能。


10-2-1-1.png

图10-3

3)  安装完成后,再次进入<控制面板>,选择<管理工具>,双击<Internet(IIS)管理器>选项,进入IIS设置。

4)  现在进入到IIS7控制面板。

5)  选择 Default Web Site,并双击 ASP 的选项。

6)  IIS7中<ASP 父路径>是没有启用的,要<开启父路径>,选择True,选定父路径选项。

7)  配置IIS7的站点。 单击右边的<高级设置>选项,可以设置网站的目录。

8)  点击右侧的<绑定>,设置网站的<端口>。

9)  点击<默认文档>, 设置网站的默认文档。


2.        创建服务器

服务器是用C#的Web来创建的服务器,项目名字WebService,如下图10-4所示:

10-2-1-2.png

图10-4


在服务器中创建DataBaseHelper类来操作数据库数据,比如上面注册用户,那意味着要在数据库中插入数据,而在GsoapBLLServiceJson类中提供一个接口DC_Registernfo用来注册用户。在登陆时要查询数据库中是否有这个用户,还要判断密码是否正确,GsoapBLLServiceJson类也提供一个DC_Login接口来处理。具体实现步骤如下代码如下所示:


1、创建DataBaseHelper用来连接数据库,断开数据库和更新数据、删除数据、添加数据等。如下所示:

usingSystem;

usingSystem.Data;

usingSystem.Data.SqlClient;

usingSystem.Configuration;

namespace GsoapDAL

{

    public class DataBaseHelper

    {

        #region 属性

        /// <summary>

        /// 连接字符串

        /// </summary>

        privatestring connectString;

        /// <summary>

        /// 连接数据库对象

        /// </summary>

        privateSqlConnection connection;

        /// <summary>

        /// 控制数据访问对象

        /// </summary>

        privateSqlCommand command;

        /// <summary>

        /// 控制适配器

        /// </summary>

        privateSqlDataAdapter dataAdapter;

        #endregion

        #region 构造方法

        publicDataBaseHelper()

        {

            //获取连接字符串。

           this.connectString= ConfigurationManager.ConnectionStrings["ConnectionStrings"].ConnectionString;

         

        }

        #endregion

        #region 方法

        #region 打开连接

        privatevoid Open()

        {

            this.connection= new SqlConnection(this.connectString);

            if(ConnectionState.Open != this.connection.State)

            {

                this.connection.Open();

            }

        }

        #endregion

        #region 关闭连接

        privatevoid Close()

        {

            if(ConnectionState.Closed != this.connection.State)

            {

                this.connection.Close();

                this.connection.Dispose();

            }

        }

        #endregion

        #region 查询多行数据

        /// <summary>

        /// 执行筛选操作

        /// </summary>

        /// <paramname="sql">筛选的SQL语句</param>

        /// <paramname="param">语句中所相关的参数</param>

        /// <returns>DataTable类型数据集</returns>

        public DataTable Select(stringsql, SqlParameter[] param)

        {

            //实例化一个控制访问对象,和连接对象,并初始化连接字符串

            this.command= new SqlCommand();

            this.connection= new SqlConnection(this.connectString);

            this.command.Connection= this.connection;

            //如果参数不为空,则给控制访问对象添加参数

            if(param != null)

            {

                this.command.CommandText= sql;

            }

            //初始化sql语句,实例化适配器和数据集

            foreach(SqlParameter p inparam)

            {

                this.command.Parameters.Add(p);

            }

            this.dataAdapter= new SqlDataAdapter(this.command);

            DataTabledt = new DataTable();

            //执行语句,如果错误,抛出异常。

            try

            {

                this.dataAdapter.Fill(dt);

            }

            catch(Exception ex)

            {

                thrownew Exception(ex.Message);

            }

            finally

            {

                this.command.Dispose();

                this.dataAdapter.Dispose();

            }

            returndt;

        }

        #endregion

        #region 查询一行数据

        /// <summary>

        /// 执行一条SQL语句,返回一个对象,该对象为语句的第一行第一列。

        /// </summary>

        /// <paramname="sql">>筛选的sql语句</param>

        /// <paramname="param">sql语句的相关参数</param>

        /// <returns>返回一个对象</returns>

        public object SelectOne(stringsql, SqlParameter[] param)

        {

            //实例化一个控制语句和初始化SQL语句

            this.command= new SqlCommand();

            this.command.CommandText= sql;

            //为控制语句添加参数

            foreach(SqlParameter p inparam)

            {

                this.command.Parameters.Add(p);

            }

            //打开连接,使控制访问对象获取当前连接

            this.Open();

            this.command.Connection= this.connection;

            //初始化一个对象,此将做返回。

            objecto = null;

            //执行sql语句,如果发现异常抛出。

            try

            {

                o = this.command.ExecuteScalar();

            }

            catch(Exception ex)

            {

                thrownew Exception(ex.Message);

            }

            finally

            {

               this.Close();

                this.command.Dispose();

            }

            returno;

        }

        #endregion

        #region 更新数据、删除数据、添加数据

        /// <summary>

        /// 执行非查询语句

        /// </summary>

        /// <param name="sql">sql</param>

        /// <paramname="param">sql的相关参数</param>

        /// <returns>返回影响行数</returns>

        public int UDIManager(stringsql, SqlParameter[] param)

        {

            //实例化一个控制语句和初始化SQL语句

            this.command= new SqlCommand();

            this.command.CommandText= sql;

            //为控制语句添加参数

            foreach(SqlParameter p inparam)

            {

                this.command.Parameters.Add(p);

            }

            //打开连接,使控制访问对象获取当前连接

            inte = -1;

            this.Open();

            this.command.Connection= this.connection;

            //执行sql语句,如果发现异常抛出。

            try

            {

                e = this.command.ExecuteNonQuery();

            }

            catch(Exception ex)

            {

                throw new Exception(ex.Message);

            }

            finally//关闭联机,销毁控制访问对象。

            {

                this.Close();

                this.command.Dispose();

            }

            returne;

        }

        /// <summary>

        /// 执行非查询语句(重载UDIManager

        /// </summary>

        /// <paramname="sql">SQL语句</param>

        /// <paramname="param">参数</param>

        /// <paramname="id">标识,判断是否返回ID</param>

        /// <returns>返回ID</returns>

        public int UDIManager(stringsql, SqlParameter[] param, bool id)

        {

            //实例化一个控制语句和初始化SQL语句

            this.command= new SqlCommand();

            this.command.CommandText= sql + " SELECT @@IDENTITY";

            //为控制语句添加参数

            foreach(SqlParameter p inparam)

            {

                this.command.Parameters.Add(p);

            }

            //打开连接,使控制访问对象获取当前连接,初始化影响行数(e=-1.

            inte = -1;

            this.Open();

            this.command.Connection= this.connection;

            //执行sql语句,如果发现异常抛出。

            try

            {

                e = Convert.ToInt32(this.command.ExecuteScalar());

            }

            catch(Exception ex)

            {

                thrownew Exception(ex.Message);

            }

            finally//关闭联机,销毁控制访问对象。

            {

                this.Close();

                this.command.Dispose();

            }

            returne;//返回结果

        }

        #endregion

        #endregion

        #region 存储过程

        // 用指定的参数值列表为存储过程参数赋值。

        privatevoid AssignParameterValues(SqlCommand sqlCommand, paramsobject[] paraValues)

        {

            if(paraValues != null)

            {

                if((sqlCommand.Parameters.Count - 1) != paraValues.Length)

                {

                    thrownew ArgumentNullException("The number of parameters does not match number ofvalues for stored procedure.");

                }

                for(int i = 0; i < paraValues.Length; i++)

                {

                    sqlCommand.Parameters[i +1].Value = (paraValues == null) ? DBNull.Value : paraValues;

                }

            }

        }

        // 创建用于执行存储过程的 SqlCommand

        privateSqlCommand CreateSqlCommand(SqlConnection connection, stringstoreProcedureName)

        {

            SqlCommandcommand = new SqlCommand(storeProcedureName,connection);

            command.CommandType = CommandType.StoredProcedure;

            returncommand;

        }

        /// <summary>

        /// 从在 System.Data.SqlClient.SqlCommand 中指定的存储过程中检索参数信息并填充指定的

        /// System.Data.SqlClient.SqlCommand 对象的System.Data.SqlClient.SqlCommand.Parameters   合。

        /// </summary>

        /// <paramname="sqlCommand">将从其中导出参数信息的存储过程的 System.Data.SqlClient.SqlCommand 对象。</param>

        internalvoid DeriveParameters(SqlCommandsqlCommand)

        {

            try

            {

                sqlCommand.Connection.Open();

                SqlCommandBuilder.DeriveParameters(sqlCommand);

                sqlCommand.Connection.Close();

            }

            catch(Exception ex)

            {

                if(sqlCommand.Connection != null)

                {

                   sqlCommand.Connection.Close();

                }

                thrownew Exception(ex.Message);

            }

        }

        /// <summary>

        /// 执行操作类(Insert/Delete/Update)存储过程。

        /// </summary>

        /// <paramname="storeProcedureName">存储过程的名称</param>

        /// <paramname="param">传递给存储过程的参数值列表。</param>

        /// <returns>受影响的行数。</returns>

        public int ExecuteNonQuery(stringstoreProcedureName, params object[] paraValues)

        {

            using(SqlConnection connection = new SqlConnection(this.connectString))

            {

                SqlCommandcommand = this.CreateSqlCommand(connection,storeProcedureName);

                try

                {

                    this.DeriveParameters(command);

                    this.AssignParameterValues(command,paraValues);

                    connection.Open();

                    intaffectedRowsCount = command.ExecuteNonQuery();

                    returnaffectedRowsCount;

                }

                catch(Exception ex)

                {

                    thrownew Exception(ex.Message);

                }

            }

        }

        /// <summary>

        /// 执行存储过程,返回 System.Data.DataTable

        /// </summary>

        /// <paramname="storeProcedureName">存储过程的名称</param>

        /// <paramname="param">传递给存储过程的参数值列表。</param>

        /// <returns>包含查询结果的 System.Data.DataTable</returns>

        public DataTable ExecuteDataTable(string storeProcedureName, params object[] paraValues)

        {

            using(SqlConnection connection = new SqlConnection(this.connectString))//创建连接对象

            {

                SqlCommandcommand = this.CreateSqlCommand(connection,storeProcedureName);  // 创建用于执行存储过程的 SqlCommand

                try

                {

                    this.DeriveParameters(command);//打开数据库

                    this.AssignParameterValues(command,paraValues);//为存储过程赋参数值

                    SqlDataAdapteradapter = new SqlDataAdapter(command);创建DataAdapter数据适配器实例

                    DataTabledataTable = new DataTable();

                    adapter.Fill(dataTable);

                    returndataTable;

                }

                catch(Exception ex)

                {

                    thrownew Exception(ex.Message);

                }

            }

        }

        /// <summary>

        /// 执行存储过程,返回 System.Data.DataSet

        /// </summary>

        /// <paramname="storeProcedureName">存储过程的名称</param>

        /// <paramname="param">传递给存储过程的参数值列表。</param>

        /// <returns>包含查询结果的 System.Data.DataSet</returns>

        public DataSet ExecuteDataSet(stringstoreProcedureName, params object[] paraValues)

        {

            using(SqlConnection connection = new SqlConnection(this.connectString))

            {

                SqlCommandcommand = this.CreateSqlCommand(connection,storeProcedureName);

                try

                {

                    this.DeriveParameters(command);

                    this.AssignParameterValues(command,paraValues);

                    SqlDataAdapteradapter = new SqlDataAdapter(command);

                    DataSetdataSet = new DataSet();

                    adapter.Fill(dataSet);

                    returndataSet;

                }

                catch(Exception ex)

                {

                    thrownew Exception(ex.Message);

                }

            }

        }

        /// <summary>

        /// 执行存储过程,填充指定的 System.Data.DataTable

        /// </summary>

        /// <paramname="storeProcedureName">存储过程的名称</param>

        /// <paramname="dataTable">用于填充查询结果的 System.Data.DataTable</param>

        /// <paramname="param">传递给存储过程的参数值列表。</param>

        public void ExecuteFillDataTable(stringstoreProcedureName, DataTable dataTable, params object[]paraValues)

        {

            using(SqlConnection connection = new SqlConnection(this.connectString))

            {

                SqlCommandcommand = this.CreateSqlCommand(connection,storeProcedureName);

                try

                {

                    this.DeriveParameters(command);

                    this.AssignParameterValues(command,paraValues);

                    connection.Open();

                    SqlDataAdapteradapter = new SqlDataAdapter(command);

                    adapter.Fill(dataTable);

                }

                catch(Exception ex)

                {

                    thrownew Exception(ex.Message);

                }

            }

        }

        /// <summary>

        /// 执行存储过程返回 System.Data.SqlClient.SqlDataReader

        ///  System.Data.SqlClient.SqlDataReader 对象关闭时,数据库连接自动关闭。

        /// </summary>

        /// <paramname="storeProcedureName">存储过程的名称</param>

        /// <paramname="param">传递给存储过程的参数值列表。</param>

        /// <returns>包含查询结果的 System.Data.SqlClient.SqlDataReader 对象。</returns>

        public SqlDataReader ExecuteDataReader(string storeProcedureName, paramsobject[] paraValues)

        {

            using(SqlConnection connection = new SqlConnection(this.connectString))

            {

                SqlCommandcommand = this.CreateSqlCommand(connection,storeProcedureName);

                try

                {

                    this.DeriveParameters(command);

                    this.AssignParameterValues(command,paraValues);

                    connection.Open();

                    returncommand.ExecuteReader(CommandBehavior.CloseConnection);

                }

                catch(Exception ex)

                {

                    thrownew Exception(ex.Message);

                }

            }

        }

        /// <summary>

        /// 执行查询,并返回查询所返回的结果集中第一行的第一列。忽略其他列或行。

        /// </summary>

        /// <paramname="storeProcedureName">存储过程的名称</param>

        /// <paramname="param">传递给存储过程的参数值列表。</param>

        /// <returns>结果集中第一行的第一列或空引用(如果结果集为空)。</returns>

        public object ExecuteScalar(stringstoreProcedureName, params object[] paraValues)

        {

            using(SqlConnection connection = new SqlConnection(this.connectString))

            {

                SqlCommandcommand = this.CreateSqlCommand(connection,storeProcedureName);

                try

                {

                    this.DeriveParameters(command);

                    this.AssignParameterValues(command,paraValues);

                    connection.Open();

                    returncommand.ExecuteScalar();

                }

                catch(Exception ex)

                {

                    thrownew Exception(ex.Message);

                }

            }

        }

        #endregion

    }

}

2、创建类StateMethods来转换格式,代码如下:

usingSystem;

usingSystem.Collections.Generic;

usingSystem.Text;

usingSystem.Text.RegularExpressions;

namespaceGsoapDTL

{

    public class StateMethods

    {

        #region C语言中移植的sscanf函数

        public static unsafe bool sscanf(stringstr, string format, paramsvoid*[] args)

        {

            try

            {

                AnalyzeResultanalyze = sscanfAnalyze(format);

                Regexregex = new Regex(analyze.OutString);

                Matchm = regex.Match(str);

                if(m.Success == false) returnfalse;

                for(int i = 0; i < analyze.formats.Length; i++)

                {

                    stringblock = m.Groups[(i + 1).ToString()].Value;

                    switch(analyze.formats)

                    {

                        case 'c':

                            *((char*)args) = block[0];

                            break;

                        case 'd':

                            *((int*)args)= int.Parse(block);

                            break;

                        case 'x':

                            *((int*)args) = int.Parse(block,System.Globalization.NumberStyles.HexNumber);

                            break;

                        case's':

                            *((char**)args) = (char*)System.Runtime.InteropServices.Marshal.StringToCoTaskMemUni(block);

                            break;

                        case 'f':

                            *((float*)args) = float.Parse(block);

                            break;

                    }

                }

                returntrue;

            }

            catch

            {

                returnfalse;

            }

        }

        static AnalyzeResult sscanfAnalyze(string format)

        {

            List<char> key = new List<char>();

            key.Add('\\');

            key.Add('^');

            key.Add('[');

            key.Add(']');

            key.Add('(');

            key.Add(')');

            key.Add('{');

            key.Add('}');

            key.Add('.');

            key.Add('*');

            key.Add('?');

            key.Add('|');

            key.Add('+');

            key.Add('$');

            AnalyzeResultresult = new AnalyzeResult();

            StringBuildersb = new StringBuilder();

            List<char> fmt = new List<char>();

            inti, n;

            charnow;

            for(i = 0, n = format.Length; i < n; i++)

            {

                now = format;

                if(key.Contains(now)) //剔除关键字

                {

                    sb.Append('\\');

                    sb.Append(now);

                }

                elseif (now == '%')//转义

                {

                    now = format[++i];

                    switch(now)

                    {

                        case '%':

                            sb.Append(now);

                            break;

                        case 'c':

                            sb.Append(@"(.)");

                            fmt.Add(now);

                            break;

                        case 'd':

                            sb.Append(@"([+-]?\d+)");

                            fmt.Add(now);

                            break;

                        case 'x':

                            sb.Append(@"(0x[0-9a-fA-F]+)");

                            fmt.Add(now);

                            break;

                        case 's':

                            sb.Append(@"(\S+)");

                            fmt.Add(now);

                            break;

                        case 'f':

                            sb.Append(@"([+-]?\d+(?<null>\.\d+)?)");

                            fmt.Add(now);

                            break;

                        default:

                            throw new Exception("未识别的转义字符: %" +now);

                    }

                }

                else

                {

                    sb.Append(now);

                }

            }

            result.OutString = sb.ToString();

            result.formats = fmt.ToArray();

            returnresult;

        }

        struct AnalyzeResult

        {

            publicstring OutString;

            publicchar[] formats;

        }

        #endregion

    }

}


3、创建GsoapBLLServiceJson类来定义接口函数:

namespaceGsoapBLL

{

    public class GsoapBLLServiceJson

    {

        public string CallGsoapServiceJson(stringparameters, string format, string serverName,)

        {

            switch(serverName)

            {

                case "DC_RegisterInfo":// 用户注册

                    returnDC_RegisterInfo(parameters, format);

                case"DC_Login":    // 用户登陆

                    returnDC_Login(parameters, format);

               }

           }

       #region 用户信息注册

        public unsafe stringDC_RegisterInfo(string parameters, string format)

        {

             stringjsonString = string.Empty;

            char*cName;

            char*cPassword;

            char*cPhoneNo;

            StateMethods.sscanf(parameters,format, &cName, &cPassword, &cPhoneNo);

            stringname = new string(cName);

            stringpassword = new string(cPassword);

            stringphoneNo = new string(cPhoneNo);

               SqlParameter[] p= new SqlParameter[]

                {

                    newSqlParameter("@name,@passwor,@phoneNo", name ,password,phoneNo);

                };

              

                stringsql = @"INSERT INTO USER_INFO (USER_NAME, USER_PASSWORD, SEX, USER_LEVEL_TYPE, WEALTH1, CELL_PHONE_NUMBER)

              VALUES (@Name, @Password, 'M', 1, 0, @PhoneNo) ";

//执行插入语句               

int count =helper.UDIManager(sql, p);   

           //成功返回1.失败返回2         

             if (count> 0)

                {

                  

                    response =1;

                  

                }

                else

                   response = 2;

            

           stringjsonString= new string(response);

            returnjsonString;

            returnjsonString;

        }

       }

       #region 用户登陆

        public unsafe string DC_Login(stringparameters, string format)

        {

            stringjsonString = string.Empty;

            char*cLoginName;

            char*cPassword;

            StateMethods.sscanf(parameters,format, &cLoginName, &cPassword,);

            stringLoginName= new string(cLoginName);

            stringpassword = new string(cPassword);

           

               SqlParameter[] p= new SqlParameter[]

                {

                    newSqlParameter("@LoginNamee,@passwor",LoginName,passwor);

                };

              

                stringsql = @"SELECT * FROM USER_INFO

       WHEREDONGYOU_CODE = @LoginNamee AND USER_PASSWORD = @Password )

       //执行登陆语句               

int count =helper.UDIManager(sql, p);   

           //成功返回1.失败返回2         

             if (count> 0)

                {

                  

                    response =1;

                  

                }

                else

                   response= 2;

           stringjsonString= new string(response);

            returnjsonString;

        }


    }


Demo下载地址:http://www.dongyo.cn/bbs/forum.php?mod=viewthread&tid=3169&extra=page%3D1%26filter%3Dauthor%26orderby%3Ddateline%26orderby%3Ddateline

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 内容概要 《计算机试卷1》是一份综合性的计算机基础和应用测试卷,涵盖了计算机硬件、软件、操作系统、网络、多媒体技术等多个领域的知识点。试卷包括单选题和操作应用两大类,单选题部分测试学生对计算机基础知识的掌握,操作应用部分则评估学生对计算机应用软件的实际操作能力。 ### 适用人群 本试卷适用于: - 计算机专业或信息技术相关专业的学生,用于课程学习或考试复习。 - 准备计算机等级考试或职业资格认证的人士,作为实战演练材料。 - 对计算机操作有兴趣的自学者,用于提升个人计算机应用技能。 - 计算机基础教育工作者,作为教学资源或出题参考。 ### 使用场景及目标 1. **学习评估**:作为学校或教育机构对学生计算机基础知识和应用技能的评估工具。 2. **自学测试**:供个人自学者检验自己对计算机知识的掌握程度和操作熟练度。 3. **职业发展**:帮助职场人士通过实际操作练习,提升计算机应用能力,增强工作竞争力。 4. **教学资源**:教师可以用于课堂教学,作为教学内容的补充或学生的课后练习。 5. **竞赛准备**:适合准备计算机相关竞赛的学生,作为强化训练和技能检测的材料。 试卷的目标是通过系统性的题目设计,帮助学生全面复习和巩固计算机基础知识,同时通过实际操作题目,提高学生解决实际问题的能力。通过本试卷的学习与练习,学生将能够更加深入地理解计算机的工作原理,掌握常用软件的使用方法,为未来的学术或职业生涯打下坚实的基础。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值