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