<?xml version="1.0" encoding="gb2312"?>
<rss version="2.0">
<channel>
<title><![CDATA[啊D Blog]]></title>
<link>http://www.d99net.net/</link>
<description><![CDATA[新的一天，新的开始~~~]]></description>
<language>zh-cn</language>
<copyright><![CDATA[Copyright 2005 PBlog2 v2.4]]></copyright>
<webMaster><![CDATA[(d99)]]></webMaster>
<generator>PBlog2 v2.4</generator> 
<image>
	<title>啊D Blog</title> 
	<url>http://www.d99net.net/images/logos.gif</url> 
	<link>http://www.d99net.net/</link> 
	<description>啊D Blog</description> 
</image>

			<item>
			<link>http://www.d99net.net/default.asp?id=332</link>
			<title><![CDATA[ASP开发中存储过程应用全接触 [转]]]></title>
			<author>(d99)</author>
			<category><![CDATA[技术文章]]></category>
			<pubDate>Sun,15 Jun 2008 23:39:47 +0800</pubDate>
			<guid>http://www.d99net.net/default.asp?id=332</guid>	
		<description><![CDATA[ASP与存储过程&#40;Stored&nbsp;Procedures)的文章不少，但是我怀疑作者们是否真正实践过。我在初学时查阅过大量相关资料，发现其中提供的很多方法实际操作起来并不是那么回事。对于简单的应用，这些资料也许是有帮助的，但仅限于此，因为它们根本就是千篇一律，互相抄袭，稍微复杂点的应用，就全都语焉不详了。&nbsp;<br/><br/>现在，我基本上通过调用存储过程访问SQL&nbsp;Server，以下的文字都是实践的总结，希望对大家能有帮助。&nbsp;<br/><br/>存储过程就是作为可执行对象存放在数据库中的一个或多个SQL命令。&nbsp;<br/><br/>定义总是很抽象。存储过程其实就是能完成一定操作的一组SQL语句，只不过这组语句是放在数据库中的&#40;这里我们只谈SQL&nbsp;Server)。如果我们通过创建存储过程以及在ASP中调用存储过程，就可以避免将SQL语句同ASP代码混杂在一起。这样做的好处至少有三个：&nbsp;<br/><br/>第一、大大提高效率。存储过程本身的执行速度非常快，而且，调用存储过程可以大大减少同数据库的交互次数。&nbsp;<br/><br/>第二、提高安全性。假如将SQL语句混合在ASP代码中，一旦代码失密，同时也就意味着库结构失密。&nbsp;<br/><br/>第三、有利于SQL语句的重用。&nbsp;<br/><br/>在ASP中，一般通过command对象调用存储过程，根据不同情况，本文也介绍其它调用方法。为了方便说明，根据存储过程的输入输出，作以下简单分类：&nbsp;<br/><br/>1.&nbsp;只返回单一记录集的存储过程&nbsp;<br/><br/>假设有以下存储过程&#40;本文的目的不在于讲述T-SQL语法，所以存储过程只给出代码，不作说明)：&nbsp;<br/><br/>/*SP1*/&nbsp;<br/><br/>Cr&#101;ate&nbsp;PROCEDURE&nbsp;dbo.getUserList&nbsp;<br/><br/>as&nbsp;<br/><br/>set&nbsp;nocount&nbsp;on&nbsp;<br/><br/>begin&nbsp;<br/><br/>sel&#101;ct&nbsp;*&nbsp;from&nbsp;dbo.[userinfo]&nbsp;<br/><br/>end&nbsp;<br/><br/>go&nbsp;<br/><br/>以上存储过程取得userinfo表中的所有记录，返回一个记录集。通过command对象调用该存储过程的ASP代码如下:&nbsp;<br/><br/>&#39;**通过Command对象调用存储过程**&nbsp;<br/><br/>DIM&nbsp;MyComm&#44;MyRst&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Server.Cr&#101;ateObject&#40;&#34;ADODB.Command&#34;)&nbsp;<br/><br/>MyComm.ActiveConnection&nbsp;=&nbsp;MyConStr&nbsp;&#39;MyConStr是数据库连接字串&nbsp;<br/><br/>MyComm.CommandText&nbsp;=&nbsp;&#34;getUserList&#34;&nbsp;&#39;指定存储过程名&nbsp;<br/><br/>&nbsp;MyComm.CommandType&nbsp;=&nbsp;4&nbsp;&#39;表明这是一个存储过程&nbsp;<br/><br/>MyComm.Prepared&nbsp;=&nbsp;true&nbsp;&#39;要求将SQL命令先行编译&nbsp;<br/><br/>Set&nbsp;MyRst&nbsp;=&nbsp;MyComm.Execute&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Nothing&nbsp;<br/><br/>存储过程取得的记录集赋给MyRst，接下来，可以对MyRst进行操作。&nbsp;<br/><br/>在以上代码中，CommandType属性表明请求的类型，取值及说明如下：&nbsp;<br/><br/>-1&nbsp;表明CommandText参数的类型无法确定&nbsp;<br/><br/>1&nbsp;表明CommandText是一般的命令类型&nbsp;<br/><br/>2&nbsp;表明CommandText参数是一个存在的表名称&nbsp;<br/><br/>4&nbsp;表明CommandText参数是一个存储过程的名称&nbsp;<br/><br/>还可以通过Connection对象或Recordset对象调用存储过程，方法分别如下：&nbsp;<br/><br/>&#39;**通过Connection对象调用存储过程**&nbsp;<br/><br/>DIM&nbsp;MyConn&#44;MyRst&nbsp;<br/><br/>Set&nbsp;MyConn&nbsp;=&nbsp;Server.Cr&#101;ateObject&#40;&#34;ADODB.Connection&#34;)&nbsp;<br/><br/>MyConn.open&nbsp;MyConStr&nbsp;&#39;MyConStr是数据库连接字串&nbsp;<br/><br/>Set&nbsp;MyRst&nbsp;=&nbsp;MyConn.Execute&#40;&#34;getUserList&#34;&#44;0&#44;4)&nbsp;&#39;最后一个参断含义同CommandType&nbsp;<br/><br/>Set&nbsp;MyConn&nbsp;=&nbsp;Nothing&nbsp;<br/><br/>&#39;**通过Recordset对象调用存储过程**&nbsp;<br/><br/>DIM&nbsp;MyRst&nbsp;<br/><br/>Set&nbsp;MyRst&nbsp;=&nbsp;Server.Cr&#101;ateObject&#40;&#34;ADODB.Recordset&#34;)&nbsp;<br/><br/>MyRst.open&nbsp;&#34;getUserList&#34;&#44;MyConStr&#44;0&#44;1&#44;4&nbsp;<br/><br/>&#39;MyConStr是数据库连接字串&#44;最后一个参断含义与CommandType相同&nbsp;<br/><br/>2.&nbsp;没有输入输出的存储过程&nbsp;<br/><br/>请看以下存储过程：&nbsp;<br/><br/>/*SP2*/&nbsp;<br/><br/>Cr&#101;ate&nbsp;PROCEDURE&nbsp;dbo.delUserAll&nbsp;<br/><br/>as&nbsp;<br/><br/>set&nbsp;nocount&nbsp;on&nbsp;<br/><br/>begin&nbsp;<br/><br/>del&#101;te&nbsp;from&nbsp;dbo.[userinfo]&nbsp;<br/><br/>end&nbsp;<br/><br/>go&nbsp;<br/><br/>该存储过程删去userinfo表中的所有记录，没有任何输入及输出，调用方法与上面讲过的基本相同，只是不用取得记录集：&nbsp;<br/><br/>&#39;**通过Command对象调用存储过程**&nbsp;<br/><br/>DIM&nbsp;MyComm&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Server.Cr&#101;ateObject&#40;&#34;ADODB.Command&#34;)&nbsp;<br/><br/>MyComm.ActiveConnection&nbsp;=&nbsp;MyConStr&nbsp;&#39;MyConStr是数据库连接字串&nbsp;<br/><br/>MyComm.CommandText&nbsp;=&nbsp;&#34;delUserAll&#34;&nbsp;&#39;指定存储过程名&nbsp;<br/><br/>MyComm.CommandType&nbsp;=&nbsp;4&nbsp;&#39;表明这是一个存储过程&nbsp;<br/><br/>MyComm.Prepared&nbsp;=&nbsp;true&nbsp;&#39;要求将SQL命令先行编译&nbsp;<br/><br/>MyComm.Execute&nbsp;&#39;此处不必再取得记录集&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Nothing&nbsp;<br/><br/>当然也可通过Connection对象或Recordset对象调用此类存储过程，不过建立Recordset对象是为了取得记录集，在没有返回记录集的情况下，还是利用Command对象吧。&nbsp;<br/><br/>3.&nbsp;有返回值的存储过程&nbsp;<br/><br/>在进行类似SP2的操作时，应充分利用SQL&nbsp;Server强大的事务处理功能，以维护数据的一致性。并且，我们可能需要存储过程返回执行情况，为此，将SP2修改如下：&nbsp;<br/><br/>/*SP3*/&nbsp;<br/><br/>Cr&#101;ate&nbsp;PROCEDURE&nbsp;dbo.delUserAll&nbsp;<br/><br/>as&nbsp;<br/><br/>set&nbsp;nocount&nbsp;on&nbsp;<br/><br/>begin&nbsp;<br/><br/>BEGIN&nbsp;TRANSACTION&nbsp;<br/><br/>del&#101;te&nbsp;from&nbsp;dbo.[userinfo]&nbsp;<br/><br/>IF&nbsp;error=0&nbsp;<br/><br/>begin&nbsp;<br/><br/>COMMIT&nbsp;TRANSACTION&nbsp;<br/><br/>return&nbsp;1&nbsp;<br/><br/>end&nbsp;<br/><br/>ELSE&nbsp;<br/><br/>begin&nbsp;<br/><br/>ROLLBACK&nbsp;TRANSACTION&nbsp;<br/><br/>return&nbsp;0&nbsp;<br/><br/>end&nbsp;<br/><br/>return&nbsp;<br/><br/>end&nbsp;<br/><br/>go&nbsp;<br/><br/>以上存储过程，在del&#101;te顺利执行时，返回1，否则返回0，并进行回滚操作。为了在ASP中取得返回值，需要利用Parameters集合来声明参数：&nbsp;<br/><br/>&#39;**调用带有返回值的存储过程并取得返回值**&nbsp;<br/><br/>DIM&nbsp;MyComm&#44;MyPara&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Server.Cr&#101;ateObject&#40;&#34;ADODB.Command&#34;)&nbsp;<br/><br/>MyComm.ActiveConnection&nbsp;=&nbsp;MyConStr&nbsp;&#39;MyConStr是数据库连接字串&nbsp;<br/><br/>MyComm.CommandText&nbsp;=&nbsp;&#34;delUserAll&#34;&nbsp;&#39;指定存储过程名&nbsp;<br/><br/>MyComm.CommandType&nbsp;=&nbsp;4&nbsp;&#39;表明这是一个存储过程&nbsp;<br/><br/>MyComm.Prepared&nbsp;=&nbsp;true&nbsp;&#39;要求将SQL命令先行编译&nbsp;<br/><br/>&#39;声明返回值&nbsp;<br/><br/>Set&nbsp;Mypara&nbsp;=&nbsp;MyComm.Cr&#101;ateParameter&#40;&#34;RETURN&#34;&#44;2&#44;4)&nbsp;<br/><br/>MyComm.Parameters.Append&nbsp;MyPara&nbsp;<br/><br/>MyComm.Execute&nbsp;<br/><br/>&#39;取得返回值&nbsp;<br/><br/>DIM&nbsp;retValue&nbsp;<br/><br/>retValue&nbsp;=&nbsp;MyComm&#40;0)&nbsp;&#39;或retValue&nbsp;=&nbsp;MyComm.Parameters&#40;0)&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Nothing&nbsp;<br/><br/>在MyComm.Cr&#101;ateParameter&#40;&#34;RETURN&#34;&#44;2&#44;4)中，各参数的含义如下：&nbsp;<br/><br/>第一个参数&#40;&#34;RETURE&#34;)为参数名。参数名可以任意设定，但一般应与存储过程中声明的参数名相同。此处是返回值，我习惯上设为&#34;RETURE&#34;；&nbsp;<br/><br/>第二个参数&#40;2)，表明该参数的数据类型，具体的类型代码请参阅ADO参考，以下给出常用的类型代码：&nbsp;<br/><br/>adBigInt:&nbsp;20&nbsp;;&nbsp;<br/><br/>adBinary&nbsp;:&nbsp;128&nbsp;;&nbsp;<br/><br/>adBoolean:&nbsp;11&nbsp;;&nbsp;<br/><br/>adChar:&nbsp;129&nbsp;;&nbsp;<br/><br/>adDBTimeStamp:&nbsp;135&nbsp;;&nbsp;<br/><br/>adEmpty:&nbsp;0&nbsp;;&nbsp;<br/><br/>adInteger:&nbsp;3&nbsp;;&nbsp;<br/><br/>adSmallInt:&nbsp;2&nbsp;;&nbsp;<br/><br/>adTinyInt:&nbsp;16&nbsp;;&nbsp;<br/><br/>adVarChar:&nbsp;200&nbsp;;&nbsp;<br/><br/>对于返回值，只能取整形，且-1到-99为保留值；&nbsp;<br/><br/>第三个参数&#40;4)，表明参数的性质，此处4表明这是一个返回值。此参数取值的说明如下：&nbsp;<br/><br/>0&nbsp;:&nbsp;类型无法确定；&nbsp;1:&nbsp;输入参数；2:&nbsp;输入参数；3：输入或输出参数；4:&nbsp;返回值&nbsp;<br/><br/>以上给出的ASP代码，应该说是完整的代码，也即最复杂的代码，其实&nbsp;<br/><br/>Set&nbsp;Mypara&nbsp;=&nbsp;MyComm.Cr&#101;ateParameter&#40;&#34;RETURN&#34;&#44;2&#44;4)&nbsp;<br/><br/>MyComm.Parameters.Append&nbsp;MyPara&nbsp;<br/><br/>可以简化为&nbsp;<br/><br/>MyComm.Parameters.Append&nbsp;MyComm.Cr&#101;ateParameter&#40;&#34;RETURN&#34;&#44;2&#44;4)&nbsp;<br/><br/>甚至还可以继续简化，稍后会做说明。&nbsp;<br/><br/>对于带参数的存储过程，只能使用Command对象调用&#40;也有资料说可通过Connection对象或Recordset对象调用，但我没有试成过)。&nbsp;<br/><br/>4.&nbsp;有输入参数和输出参数的存储过程&nbsp;<br/><br/>返回值其实是一种特殊的输出参数。在大多数情况下，我们用到的是同时有输入及输出参数的存储过程，比如我们想取得用户信息表中，某ID用户的用户名，这时候，有一个输入参数----用户ID，和一个输出参数----用户名。实现这一功能的存储过程如下：&nbsp;<br/><br/>/*SP4*/&nbsp;<br/><br/>Cr&#101;ate&nbsp;PROCEDURE&nbsp;dbo.getUserName&nbsp;<br/><br/>@UserID&nbsp;int&#44;&nbsp;<br/><br/>@UserName&nbsp;varchar&#40;40)&nbsp;output&nbsp;<br/><br/>as&nbsp;<br/><br/>set&nbsp;nocount&nbsp;on&nbsp;<br/><br/>begin&nbsp;<br/><br/>if&nbsp;@UserID&nbsp;is&nbsp;null&nbsp;return&nbsp;<br/><br/>sel&#101;ct&nbsp;@UserName=username&nbsp;<br/><br/>from&nbsp;dbo.[userinfo]&nbsp;<br/><br/>wh&#101;re&nbsp;userid=@UserID&nbsp;<br/><br/>return&nbsp;<br/><br/>end&nbsp;<br/><br/>go&nbsp;<br/><br/>调用该存储过程的ASP代码如下：&nbsp;<br/><br/>&#39;**调用带有输入输出参数的存储过程**&nbsp;<br/><br/>DIM&nbsp;MyComm&#44;UserID&#44;UserName&nbsp;<br/><br/>UserID&nbsp;=&nbsp;1&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Server.Cr&#101;ateObject&#40;&#34;ADODB.Command&#34;)&nbsp;<br/><br/>MyComm.ActiveConnection&nbsp;=&nbsp;MyConStr&nbsp;&#39;MyConStr是数据库连接字串&nbsp;<br/><br/>MyComm.CommandText&nbsp;=&nbsp;&#34;getUserName&#34;&nbsp;&#39;指定存储过程名&nbsp;<br/><br/>MyComm.CommandType&nbsp;=&nbsp;4&nbsp;&#39;表明这是一个存储过程&nbsp;<br/><br/>MyComm.Prepared&nbsp;=&nbsp;true&nbsp;&#39;要求将SQL命令先行编译&nbsp;<br/><br/>&#39;声明参数&nbsp;<br/><br/>MyComm.Parameters.append&nbsp;MyComm.Cr&#101;ateParameter&#40;&#34;@UserID&#34;&#44;3&#44;1&#44;4&#44;UserID)&nbsp;<br/><br/>MyComm.Parameters.append&nbsp;MyComm.Cr&#101;ateParameter&#40;&#34;@UserName&#34;&#44;200&#44;2&#44;40)&nbsp;<br/><br/>MyComm.Execute&nbsp;<br/><br/>&#39;取得出参&nbsp;<br/><br/>UserName&nbsp;=&nbsp;MyComm&#40;1)&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Nothing&nbsp;<br/><br/>在以上代码中，可以看到，与声明返回值不同，声明输入参数时需要5个参数，声明输出参数时需要4个参数。声明输入参数时5个参数分别为：参数名、参数数据类型、参数类型、数据长度、参数值。声明输出参数时，没有最后一个参数：参数值。&nbsp;<br/><br/>需要特别注意的是：在声明参数时，顺序一定要与存储过程中定义的顺序相同，而且各参数的数据类型、长度也要与存储过程中定义的相同。&nbsp;<br/><br/>如果存储过程有多个参数，ASP代码会显得繁琐，可以使用with命令简化代码：&nbsp;<br/><br/>&#39;**调用带有输入输出参数的存储过程&#40;简化代码)**&nbsp;<br/><br/>DIM&nbsp;MyComm&#44;UserID&#44;UserName&nbsp;<br/><br/>UserID&nbsp;=&nbsp;1&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Server.Cr&#101;ateObject&#40;&#34;ADODB.Command&#34;)&nbsp;<br/><br/>with&nbsp;MyComm&nbsp;<br/><br/>　.ActiveConnection&nbsp;=&nbsp;MyConStr&nbsp;&#39;MyConStr是数据库连接字串&nbsp;<br/><br/>　.CommandText&nbsp;=&nbsp;&#34;getUserName&#34;&nbsp;&#39;指定存储过程名&nbsp;<br/><br/>　.CommandType&nbsp;=&nbsp;4&nbsp;&#39;表明这是一个存储过程&nbsp;<br/><br/>　.Prepared&nbsp;=&nbsp;true&nbsp;&#39;要求将SQL命令先行编译&nbsp;<br/><br/>　.Parameters.append&nbsp;.Cr&#101;ateParameter&#40;&#34;@UserID&#34;&#44;3&#44;1&#44;4&#44;UserID)&nbsp;<br/><br/>　.Parameters.append&nbsp;.Cr&#101;ateParameter&#40;&#34;@UserName&#34;&#44;200&#44;2&#44;40)&nbsp;<br/><br/>　.Execute&nbsp;<br/><br/>end&nbsp;with&nbsp;<br/><br/>UserName&nbsp;=&nbsp;MyComm&#40;1)&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Nothing&nbsp;<br/><br/>假如我们要取得ID为1到10，10位用户的用户名，是不是要创建10次Command对象呢？不是的。如果需要多次调用同一存储过程，只需改变输入参数，就会得到不同的输出：&nbsp;<br/><br/>&#39;**多次调用同一存储过程**&nbsp;<br/><br/>DIM&nbsp;MyComm&#44;UserID&#44;UserName&nbsp;<br/><br/>UserName&nbsp;=&nbsp;&#34;&#34;&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Server.Cr&#101;ateObject&#40;&#34;ADODB.Command&#34;)&nbsp;<br/><br/>for&nbsp;UserID&nbsp;=&nbsp;1&nbsp;to&nbsp;10&nbsp;<br/><br/>　with&nbsp;MyComm&nbsp;<br/><br/>　　.ActiveConnection&nbsp;=&nbsp;MyConStr&nbsp;&#39;MyConStr是数据库连接字串&nbsp;<br/><br/>　　.CommandText&nbsp;=&nbsp;&#34;getUserName&#34;&nbsp;&#39;指定存储过程名&nbsp;<br/><br/>　　.CommandType&nbsp;=&nbsp;4&nbsp;&#39;表明这是一个存储过程&nbsp;<br/><br/>　　.Prepared&nbsp;=&nbsp;true&nbsp;&#39;要求将SQL命令先行编译&nbsp;<br/><br/>　　if&nbsp;UserID&nbsp;=&nbsp;1&nbsp;then&nbsp;<br/><br/>　　　.Parameters.append&nbsp;.Cr&#101;ateParameter&#40;&#34;@UserID&#34;&#44;3&#44;1&#44;4&#44;UserID)&nbsp;<br/><br/>　　　.Parameters.append&nbsp;.Cr&#101;ateParameter&#40;&#34;@UserName&#34;&#44;200&#44;2&#44;40)&nbsp;<br/><br/>　　　.Execute&nbsp;<br/><br/>　　else&nbsp;<br/><br/>　　　&#39;重新给入参赋值&#40;此时参数值不发生变化的入参以及出参不必重新声明)&nbsp;<br/><br/>　　.Parameters&#40;&#34;@UserID&#34;)&nbsp;=&nbsp;UserID&nbsp;<br/><br/>　　　.Execute&nbsp;<br/><br/>　　end&nbsp;if&nbsp;<br/><br/>　end&nbsp;with&nbsp;<br/><br/>　UserName&nbsp;=&nbsp;UserName&nbsp;+&nbsp;MyComm&#40;1)&nbsp;+&nbsp;&#34;&#44;&#34;&nbsp;&#39;也许你喜欢用数组存储&nbsp;<br/><br/>next&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Nothing&nbsp;<br/><br/>通过以上代码可以看出：重复调用同一存储过程时，只需为值发生改变的输入参数重新赋值即可，这一方法在有多个输入输出参数，且每次调用时只有一个输入参数的值发生变化时，可以大大减少代码量。&nbsp;<br/><br/>5.&nbsp;同时具有返回值、输入参数、输出参数的存储过程&nbsp;<br/><br/>前面说过，在调用存储过程时，声明参数的顺序要与存储过程中定义的顺序相同。还有一点要特别注意：如果存储过程同时具有返回值以及输入、输出参数，返回值要最先声明。&nbsp;<br/><br/>为了演示这种情况下的调用方法，我们改善一下上面的例子。还是取得ID为1的用户的用户名，但是有可能该用户不存在&#40;该用户已删除，而userid是自增长的字段)。存储过程根据用户存在与否，返回不同的值。此时，存储过程和ASP代码如下：&nbsp;<br/><br/>/*SP5*/&nbsp;<br/><br/>Cr&#101;ate&nbsp;PROCEDURE&nbsp;dbo.getUserName&nbsp;<br/><br/>--为了加深对&#34;顺序&#34;的印象，将以下两参数的定义顺序颠倒一下&nbsp;<br/><br/>@UserName&nbsp;varchar&#40;40)&nbsp;output&#44;&nbsp;<br/><br/>@UserID&nbsp;int&nbsp;<br/><br/>as&nbsp;<br/><br/>set&nbsp;nocount&nbsp;on&nbsp;<br/><br/>begin&nbsp;<br/><br/>if&nbsp;@UserID&nbsp;is&nbsp;null&nbsp;return&nbsp;<br/><br/>sel&#101;ct&nbsp;@UserName=username&nbsp;<br/><br/>from&nbsp;dbo.[userinfo]&nbsp;<br/><br/>wh&#101;re&nbsp;userid=@UserID&nbsp;<br/><br/>if&nbsp;rowcount&gt;&nbsp;0&nbsp;<br/><br/>return&nbsp;1&nbsp;<br/><br/>else&nbsp;<br/><br/>return&nbsp;0&nbsp;<br/><br/>return&nbsp;<br/><br/>end&nbsp;<br/><br/>go&nbsp;<br/><br/>&#39;**调用同时具有返回值、输入参数、输出参数的存储过程**&nbsp;<br/><br/>DIM&nbsp;MyComm&#44;UserID&#44;UserName&nbsp;<br/><br/>UserID&nbsp;=&nbsp;1&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Server.Cr&#101;ateObject&#40;&#34;ADODB.Command&#34;)&nbsp;<br/><br/>with&nbsp;MyComm&nbsp;<br/><br/>.ActiveConnection&nbsp;=&nbsp;MyConStr&nbsp;&#39;MyConStr是数据库连接字串&nbsp;<br/><br/>.CommandText&nbsp;=&nbsp;&#34;getUserName&#34;&nbsp;&#39;指定存储过程名&nbsp;<br/><br/>.CommandType&nbsp;=&nbsp;4&nbsp;&#39;表明这是一个存储过程&nbsp;<br/><br/>.Prepared&nbsp;=&nbsp;true&nbsp;&#39;要求将SQL命令先行编译&nbsp;<br/><br/>&#39;返回值要最先被声明&nbsp;<br/><br/>.Parameters.Append&nbsp;.Cr&#101;ateParameter&#40;&#34;RETURN&#34;&#44;2&#44;4)&nbsp;<br/><br/>&#39;以下两参数的声明顺序也做相应颠倒&nbsp;<br/><br/>.Parameters.append&nbsp;.Cr&#101;ateParameter&#40;&#34;@UserName&#34;&#44;200&#44;2&#44;40)&nbsp;<br/><br/>.Parameters.append&nbsp;.Cr&#101;ateParameter&#40;&#34;@UserID&#34;&#44;3&#44;1&#44;4&#44;UserID)&nbsp;<br/><br/>.Execute&nbsp;<br/><br/>end&nbsp;with&nbsp;<br/><br/>if&nbsp;MyComm&#40;0)&nbsp;=&nbsp;1&nbsp;then&nbsp;<br/><br/>UserName&nbsp;=&nbsp;MyComm&#40;1)&nbsp;<br/><br/>else&nbsp;<br/><br/>UserName&nbsp;=&nbsp;&#34;该用户不存在&#34;&nbsp;<br/><br/>end&nbsp;if&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Nothing&nbsp;<br/><br/>6.&nbsp;同时返回参数和记录集的存储过程&nbsp;<br/><br/>有时候，我们需要存储过程同时返回参数和记录集，比如在利用存储过程分页时，要同时返回记录集以及数据总量等参数。以下给出一个进行分页处理的存储过程：&nbsp;<br/><br/>/*SP6*/&nbsp;<br/><br/>Cr&#101;ate&nbsp;PROCEDURE&nbsp;dbo.getUserList&nbsp;<br/><br/>@iPageCount&nbsp;int&nbsp;OUTPUT&#44;&nbsp;--总页数&nbsp;<br/><br/>@iPage&nbsp;int&#44;&nbsp;--当前页号&nbsp;<br/><br/>@iPageSize&nbsp;int&nbsp;--每页记录数&nbsp;<br/><br/>as&nbsp;<br/><br/>set&nbsp;nocount&nbsp;on&nbsp;<br/><br/>begin&nbsp;<br/><br/>--创建临时表&nbsp;<br/><br/>cr&#101;ate&nbsp;table&nbsp;#t&nbsp;&#40;ID&nbsp;int&nbsp;IDENTITY&#44;&nbsp;--自增字段&nbsp;<br/><br/>userid&nbsp;int&#44;&nbsp;<br/><br/>username&nbsp;varchar&#40;40))&nbsp;<br/><br/>--向临时表中写入数据&nbsp;<br/><br/>ins&#101;rt&nbsp;into&nbsp;#t&nbsp;<br/><br/>sel&#101;ct&nbsp;userid&#44;username&nbsp;from&nbsp;dbo.[UserInfo]&nbsp;<br/><br/>o&#114;der&nbsp;by&nbsp;userid&nbsp;<br/><br/>--取得记录总数&nbsp;<br/><br/>declare&nbsp;@iRecordCount&nbsp;int&nbsp;<br/><br/>set&nbsp;@iRecordCount&nbsp;=&nbsp;rowcount&nbsp;<br/><br/>--确定总页数&nbsp;<br/><br/>IF&nbsp;@iRecordCount%@iPageSize=0&nbsp;<br/><br/>SET&nbsp;@iPageCount=CEILING&#40;@iRecordCount/@iPageSize)&nbsp;<br/><br/>ELSE&nbsp;<br/><br/>SET&nbsp;@iPageCount=CEILING&#40;@iRecordCount/@iPageSize)+1&nbsp;<br/><br/>--若请求的页号大于总页数，则显示最后一页&nbsp;<br/><br/>IF&nbsp;@iPage&nbsp;&gt;&nbsp;@iPageCount&nbsp;<br/><br/>Sel&#101;ct&nbsp;@iPage&nbsp;=&nbsp;@iPageCount&nbsp;<br/><br/>--确定当前页的始末记录&nbsp;<br/><br/>DECLARE&nbsp;@iStart&nbsp;int&nbsp;--start&nbsp;record&nbsp;<br/><br/>DECLARE&nbsp;@iEnd&nbsp;int&nbsp;--end&nbsp;record&nbsp;<br/><br/>Sel&#101;ct&nbsp;@iStart&nbsp;=&nbsp;&#40;@iPage&nbsp;-&nbsp;1)&nbsp;*&nbsp;@iPageSize&nbsp;<br/><br/>Sel&#101;ct&nbsp;@iEnd&nbsp;=&nbsp;@iStart&nbsp;+&nbsp;@iPageSize&nbsp;+&nbsp;1&nbsp;<br/><br/>--取当前页记录&nbsp;<br/><br/>sel&#101;ct&nbsp;*&nbsp;from&nbsp;#t&nbsp;wh&#101;re&nbsp;ID&gt;&nbsp;@iStart&nbsp;and&nbsp;ID&nbsp;&lt;@iEnd&nbsp;<br/><br/>--删除临时表&nbsp;<br/><br/>Dro&#112;&nbsp;TABLE&nbsp;#t&nbsp;<br/><br/>--返回记录总数&nbsp;<br/><br/>return&nbsp;@iRecordCount&nbsp;<br/><br/>end&nbsp;<br/><br/>go&nbsp;<br/><br/>在上面的存储过程中，输入当前页号及每页记录数，返回当前页的记录集，总页数及记录总数。为了更具典型性，将记录总数以返回值的形式返回。以下是调用该存储过程的ASP代码&#40;具体的分页操作略去):&nbsp;<br/><br/>&#39;**调用分页存储过程**&nbsp;<br/><br/>DIM&nbsp;pagenow&#44;pagesize&#44;pagecount&#44;recordcount&nbsp;<br/><br/>DIM&nbsp;MyComm&#44;MyRst&nbsp;<br/><br/>pagenow&nbsp;=&nbsp;Request&#40;&#34;pn&#34;)&nbsp;<br/><br/>&#39;自定义函数用于验证自然数&nbsp;<br/><br/>if&nbsp;CheckNar&#40;pagenow)&nbsp;=&nbsp;false&nbsp;then&nbsp;pagenow&nbsp;=&nbsp;1&nbsp;<br/><br/>pagesize&nbsp;=&nbsp;20&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Server.Cr&#101;ateObject&#40;&#34;ADODB.Command&#34;)&nbsp;<br/><br/>with&nbsp;MyComm&nbsp;<br/><br/>.ActiveConnection&nbsp;=&nbsp;MyConStr&nbsp;&#39;MyConStr是数据库连接字串&nbsp;<br/><br/>.CommandText&nbsp;=&nbsp;&#34;getUserList&#34;&nbsp;&#39;指定存储过程名&nbsp;<br/><br/>.CommandType&nbsp;=&nbsp;4&nbsp;&#39;表明这是一个存储过程&nbsp;<br/><br/>.Prepared&nbsp;=&nbsp;true&nbsp;&#39;要求将SQL命令先行编译&nbsp;<br/><br/>&#39;返回值&#40;记录总量)&nbsp;<br/><br/>.Parameters.Append&nbsp;.Cr&#101;ateParameter&#40;&#34;RETURN&#34;&#44;2&#44;4)&nbsp;<br/><br/>&#39;出参&#40;总页数)&nbsp;<br/><br/>.Parameters.Append&nbsp;.Cr&#101;ateParameter&#40;&#34;@iPageCount&#34;&#44;3&#44;2)&nbsp;<br/><br/>&#39;入参&#40;当前页号)&nbsp;<br/><br/>.Parameters.append&nbsp;.Cr&#101;ateParameter&#40;&#34;@iPage&#34;&#44;3&#44;1&#44;4&#44;pagenow)&nbsp;<br/><br/>&#39;入参&#40;每页记录数)&nbsp;<br/><br/>.Parameters.append&nbsp;.Cr&#101;ateParameter&#40;&#34;@iPageSize&#34;&#44;3&#44;1&#44;4&#44;pagesize)&nbsp;<br/><br/>Set&nbsp;MyRst&nbsp;=&nbsp;.Execute&nbsp;<br/><br/>end&nbsp;with&nbsp;<br/><br/>if&nbsp;MyRst.state&nbsp;=&nbsp;0&nbsp;then&nbsp;&#39;未取到数据，MyRst关闭&nbsp;<br/><br/>recordcount&nbsp;=&nbsp;-1&nbsp;<br/><br/>else&nbsp;<br/><br/>MyRst.close&nbsp;&#39;注意：若要取得参数值，需先关闭记录集对象&nbsp;<br/><br/>recordcount&nbsp;=&nbsp;MyComm&#40;0)&nbsp;<br/><br/>pagecount&nbsp;=&nbsp;MyComm&#40;1)&nbsp;<br/><br/>if&nbsp;cint&#40;pagenow)&gt;&nbsp;=cint&#40;pagecount)&nbsp;then&nbsp;pagenow=pagecount&nbsp;<br/><br/>end&nbsp;if&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Nothing&nbsp;<br/><br/>&#39;以下显示记录&nbsp;<br/><br/>if&nbsp;recordcount&nbsp;=&nbsp;0&nbsp;then&nbsp;<br/><br/>Response.Write&nbsp;&#34;无记录&#34;&nbsp;<br/><br/>elseif&nbsp;recordcount&nbsp;&gt;&nbsp;0&nbsp;then&nbsp;<br/><br/>MyRst.open&nbsp;<br/><br/>do&nbsp;until&nbsp;MyRst.EOF&nbsp;<br/><br/>......&nbsp;<br/><br/>loop&nbsp;<br/><br/>&#39;以下显示分页信息&nbsp;<br/><br/>......&nbsp;<br/><br/>else&nbsp;&#39;recordcount=-1&nbsp;<br/><br/>Response.Write&nbsp;&#34;参数错误&#34;&nbsp;<br/><br/>end&nbsp;if&nbsp;<br/><br/>对于以上代码，只有一点需要说明：同时返回记录集和参数时，若要取得参数，需先将记录集关闭，使用记录集时再将其打开。&nbsp;<br/><br/>7.&nbsp;返回多个记录集的存储过程&nbsp;<br/><br/>本文最先介绍的是返回记录集的存储过程。有时候，需要一个存储过程返回多个记录集，在ASP中，如何同时取得这些记录集呢？为了说明这一问题，在userinfo表中增加两个字段：usertel及usermail，并设定只有登录用户可以查看这两项内容。<br/><br/>/*SP7*/&nbsp;<br/><br/>Cr&#101;ate&nbsp;PROCEDURE&nbsp;dbo.getUserInfo&nbsp;<br/><br/>@userid&nbsp;int&#44;&nbsp;<br/><br/>@checklogin&nbsp;bit&nbsp;<br/><br/>as&nbsp;<br/><br/>set&nbsp;nocount&nbsp;on&nbsp;<br/><br/>begin&nbsp;<br/><br/>if&nbsp;@userid&nbsp;is&nbsp;null&nbsp;o&#114;&nbsp;@checklogin&nbsp;is&nbsp;null&nbsp;return&nbsp;<br/><br/>sel&#101;ct&nbsp;username&nbsp;<br/><br/>from&nbsp;dbo.[usrinfo]&nbsp;<br/><br/>wh&#101;re&nbsp;userid=@userid&nbsp;<br/><br/>--若为登录用户，取usertel及usermail&nbsp;<br/><br/>if&nbsp;@checklogin=1&nbsp;<br/><br/>sel&#101;ct&nbsp;usertel&#44;usermail&nbsp;<br/><br/>from&nbsp;dbo.[userinfo]&nbsp;<br/><br/>wh&#101;re&nbsp;userid=@userid&nbsp;<br/><br/>return&nbsp;<br/><br/>end&nbsp;<br/><br/>go&nbsp;<br/><br/>以下是ASP代码：&nbsp;<br/><br/>&#39;**调用返回多个记录集的存储过程**&nbsp;<br/><br/>DIM&nbsp;checklg&#44;UserID&#44;UserName&#44;UserTel&#44;UserMail&nbsp;<br/><br/>DIM&nbsp;MyComm&#44;MyRst&nbsp;<br/><br/>UserID&nbsp;=&nbsp;1&nbsp;<br/><br/>&#39;checklogin&#40;)为自定义函数，判断访问者是否登录&nbsp;<br/><br/>checklg&nbsp;=&nbsp;checklogin&#40;)&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Server.Cr&#101;ateObject&#40;&#34;ADODB.Command&#34;)&nbsp;<br/><br/>with&nbsp;MyComm&nbsp;<br/><br/>　.ActiveConnection&nbsp;=&nbsp;MyConStr&nbsp;&#39;MyConStr是数据库连接字串&nbsp;<br/><br/>　.CommandText&nbsp;=&nbsp;&#34;getUserInfo&#34;&nbsp;&#39;指定存储过程名&nbsp;<br/><br/>　.CommandType&nbsp;=&nbsp;4&nbsp;&#39;表明这是一个存储过程&nbsp;<br/><br/>　.Prepared&nbsp;=&nbsp;true&nbsp;&#39;要求将SQL命令先行编译&nbsp;<br/><br/>　.Parameters.append&nbsp;.Cr&#101;ateParameter&#40;&#34;@userid&#34;&#44;3&#44;1&#44;4&#44;UserID)&nbsp;<br/><br/>　.Parameters.append&nbsp;.Cr&#101;ateParameter&#40;&#34;@checklogin&#34;&#44;11&#44;1&#44;1&#44;checklg)&nbsp;<br/><br/>　Set&nbsp;MyRst&nbsp;=&nbsp;.Execute&nbsp;<br/><br/>end&nbsp;with&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Nothing&nbsp;<br/><br/>&#39;从第一个记录集中取值&nbsp;<br/><br/>UserName&nbsp;=&nbsp;MyRst&#40;0)&nbsp;<br/><br/>&#39;从第二个记录集中取值&nbsp;<br/><br/>if&nbsp;not&nbsp;MyRst&nbsp;is&nbsp;Nothing&nbsp;then&nbsp;<br/><br/>　Set&nbsp;MyRst&nbsp;=&nbsp;MyRst.NextRecordset&#40;)&nbsp;<br/><br/>　UserTel&nbsp;=&nbsp;MyRst&#40;0)&nbsp;<br/><br/>　UserMail&nbsp;=&nbsp;MyRst&#40;1)&nbsp;<br/><br/>end&nbsp;if&nbsp;<br/><br/>Set&nbsp;MyRst&nbsp;=&nbsp;Nothing&nbsp;<br/><br/>以上代码中，利用Recordset对象的NextRecordset方法，取得了存储过程返回的多个记录集。&nbsp;<br/><br/>至此，针对ASP调用存储过程的各种情况，本文已做了较为全面的说明。最后说一下在一个ASP程序中，调用多个存储过程的不同方法。&nbsp;<br/><br/>在一个ASP程序中，调用多个存储过程至少有以下三种方法是可行的：&nbsp;<br/><br/>1.&nbsp;创建多个Command对象&nbsp;<br/><br/>DIM&nbsp;MyComm&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Server.Cr&#101;ateObject&#40;&#34;ADODB.Command&#34;)&nbsp;<br/><br/>&#39;调用存储过程一&nbsp;<br/><br/>......&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Nothing&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Server.Cr&#101;ateObject&#40;&#34;ADODB.Command&#34;)&nbsp;<br/><br/>&#39;调用存储过程二&nbsp;<br/><br/>......&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Nothing&nbsp;<br/><br/>......&nbsp;<br/><br/>2.&nbsp;只创建一个Command对象，结束一次调用时，清除其参数&nbsp;<br/><br/>DIM&nbsp;MyComm&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Server.Cr&#101;ateObject&#40;&#34;ADODB.Command&#34;)&nbsp;<br/><br/>&#39;调用存储过程一&nbsp;<br/><br/>.....&nbsp;<br/><br/>&#39;清除参数&#40;假设有三个参数)&nbsp;<br/><br/>MyComm.Parameters.del&#101;te&nbsp;2&nbsp;<br/><br/>MyComm.Parameters.del&#101;te&nbsp;1&nbsp;<br/><br/>MyComm.Parameters.del&#101;te&nbsp;0&nbsp;<br/><br/>&#39;调用存储过程二并清除参数&nbsp;<br/><br/>......&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Nothing&nbsp;<br/><br/>此时要注意：清除参数的顺序与参数声明的顺序相反，原因嘛，我也不知道。&nbsp;<br/><br/>3.&nbsp;利用Parameters数据集合的Refresh方法重置Parameter对象&nbsp;<br/><br/>DIM&nbsp;MyComm&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Server.Cr&#101;ateObject&#40;&#34;ADODB.Command&#34;)&nbsp;<br/><br/>&#39;调用存储过程一&nbsp;<br/><br/>.....&nbsp;<br/><br/>&#39;重置Parameters数据集合中包含的所有Parameter对象&nbsp;<br/><br/>MyComm.Parameters.Refresh&nbsp;<br/><br/>&#39;调用存储过程二&nbsp;<br/><br/>.....&nbsp;<br/><br/>Set&nbsp;MyComm&nbsp;=&nbsp;Nothing&nbsp;<br/><br/>一般认为，重复创建对象是效率较低的一种方法，但是经测试&#40;测试工具为Microsoft&nbsp;Application&nbsp;Center&nbsp;Test)，结果出人意料：&nbsp;<br/><br/>方法2&nbsp;&gt;&nbsp;=&nbsp;方法1&nbsp;&gt;&nbsp;&gt;&nbsp;方法3&nbsp;<br/><br/>方法2的运行速度大于等于方法1&#40;最多可高4%左右)，这两种方法的运行速度远大于方法3&#40;最多竟高达130%)，所以建议在参数多时，采用方法1，在参数较少时，采用方法2。&nbsp;<br/><br/>]]></description>
		</item>
		
			<item>
			<link>http://www.d99net.net/default.asp?id=331</link>
			<title><![CDATA[四川震灾 史上最无耻的捐款行为。[转]]]></title>
			<author>(d99)</author>
			<category><![CDATA[杂谈]]></category>
			<pubDate>Sat,17 May 2008 23:41:33 +0800</pubDate>
			<guid>http://www.d99net.net/default.asp?id=331</guid>	
		<description><![CDATA[如果些事是真的话，这样的人还配做老师吗？&nbsp;<br/><div class="UBBPanel"><div class="UBBTitle"><img src="http://www.d99net.net/images/flash.gif" alt="" style="margin:0px 2px -3px 0px" border="0"/>Flash动画</div><div class="UBBContent"><a id="temp3016_href" href="http://www.d99net.net/javascript:MediaShow('swf','temp3016','http://static.video.qq.com/v1/res/qqplayerout.swf?f=3&amp;vid=4jeUgFCwvhM','400','300')"><img name="temp3016_img" src="http://www.d99net.net/images/mm_snd.gif" style="margin:0px 3px -2px 0px" border="0" alt=""/><span id="temp3016_text">在线播放</span></a><div id="temp3016"></div></div></div><br/><a target="_blank" href="http://static.video.qq.com/v1/res/qqplayerout.swf?f=3&amp;vid=4jeUgFCwvhM">http://static.video.qq.com/v1/res/qqplayerout.swf?f=3&amp;vid=4jeUgFCwvhM</a><br/><br/>网上出现如下推理（但未经确实）<br/>======================================================<br/><span style="color:Red">我来推理整事情的发生经过吧，大家想想是不是这样子的：&nbsp;<br/>电视台接到一个电话，是市慈善总会打来的：&nbsp;<br/>--喂~~是市电视台吗？&nbsp;<br/>--嗯~嗯~是的是的。请问有什么事？&nbsp;<br/>--我想告诉你们吖，我们市三中吖在这次抗震救灾中表现比较突出，全校师生共捐了11万多呢，我们想把这件事宣扬出去，好激励社会有更多的人参与到这场捐款救的活动中来。你们去采访一下好吗？&nbsp;<br/>--这样啊~~太好了（我们正想找点这样子的材料呢），我们这就办~~&nbsp;<br/>于是电视台就扛着长枪短炮赶到学校，找到校长：&nbsp;<br/>--你是校长吗？你好你好！！我是电视台的。&nbsp;<br/>--你好你好，我是校长~~进来坐坐~~&nbsp;<br/>--听说你们校这次抗震救灾中全校师生共捐了11万多，是吧？&nbsp;<br/>--（有点不好意思）哪里哪里，这是我们该做的。&nbsp;<br/>--这样太好了，我们拿，想把当时的情形重现一下，好在晚上的新闻中播放。这样好不好？&nbsp;<br/>--不太好吧？都已经捐过了，怎么重现？再说我们做人是很低调的，不用了不用了！&nbsp;<br/>--啊！校长，由于你们学校表现比较实出，比较典形。在新闻中放出来可以激励更多的人更多的台体参与到这场抗震救灾中来，这样就可以更多的帮到受灾的人，不是很好吗？&nbsp;<br/>--这~~这~~这~~~那好吧！&nbsp;<br/>于是就补拍了。。&nbsp;<br/>关于上传视频的那位同学，我认为他没有参加捐款，所以没通知道。不过他我觉得他手机不错，视频很清晰，家里应该很多米。。&nbsp;</span><br/><br/><br/>我也希望这次捐款拍下来的不是真，像上面推理那样，是用于宣扬~~~]]></description>
		</item>
		
			<item>
			<link>http://www.d99net.net/default.asp?id=330</link>
			<title><![CDATA[有人入侵了别人服务器，挂我QQ，用心何在？]]></title>
			<author>(d99)</author>
			<category><![CDATA[杂谈]]></category>
			<pubDate>Wed,14 May 2008 18:15:55 +0800</pubDate>
			<guid>http://www.d99net.net/default.asp?id=330</guid>	
		<description><![CDATA[在QQ空间里，有人说我破坏了他的服务器<br/>内容如下：<br/><img src="http://www.d99net.net/attachments/month_0805/f20085141884.jpg" border="0" alt=""/><br/><br/>我N久没有检测国内的服务器，更不要说破坏~&nbsp;我也没有在什么服务器上留过我的QQ~<br/><br/>破坏别人服务器并挂我QQ的人，不知用心何在&#44;我只能说那个人实在可耻~~<br/><br/>欢迎服务器给破坏的朋友去报案，并协助公安进行处理~~~]]></description>
		</item>
		
			<item>
			<link>http://www.d99net.net/default.asp?id=329</link>
			<title><![CDATA[今年我们国家实在是多灾之年~~~]]></title>
			<author>(d99)</author>
			<category><![CDATA[杂谈]]></category>
			<pubDate>Tue,13 May 2008 20:11:33 +0800</pubDate>
			<guid>http://www.d99net.net/default.asp?id=329</guid>	
		<description><![CDATA[今年算是多灾之年，军人和普通老百姓一起抗灾&#44;感受到国家和人民团结的一面&#44;希望&nbsp;“四川强烈地震”&nbsp;的灾难早日过去~~~<br/>在灾难和困难面前，我们更需要坚强和团结~~~<br/><div class="UBBPanel"><div class="UBBTitle"><img src="http://www.d99net.net/images/flash.gif" alt="" style="margin:0px 2px -3px 0px" border="0"/>Flash动画</div><div class="UBBContent"><a id="temp7193_href" href="http://www.d99net.net/javascript:MediaShow('swf','temp7193','http://player.ku6.com/refer/LltQCiIr9nhxwGb1/v.swf','400','300')"><img name="temp7193_img" src="http://www.d99net.net/images/mm_snd.gif" style="margin:0px 3px -2px 0px" border="0" alt=""/><span id="temp7193_text">在线播放</span></a><div id="temp7193"></div></div></div><br/><span style="color:Red">四川大地震</span><br/><div class="UBBPanel"><div class="UBBTitle"><img src="http://www.d99net.net/images/flash.gif" alt="" style="margin:0px 2px -3px 0px" border="0"/>Flash动画</div><div class="UBBContent"><a id="temp85167_href" href="http://www.d99net.net/javascript:MediaShow('swf','temp85167','http://player.youku.com/player.php/sid/XMjczMzkzODA=/v.swf','400','300')"><img name="temp85167_img" src="http://www.d99net.net/images/mm_snd.gif" style="margin:0px 3px -2px 0px" border="0" alt=""/><span id="temp85167_text">在线播放</span></a><div id="temp85167"></div></div></div><br/><span style="color:Red">手足口病&#44;大量儿童感染~~~</span><br/><div class="UBBPanel"><div class="UBBTitle"><img src="http://www.d99net.net/images/flash.gif" alt="" style="margin:0px 2px -3px 0px" border="0"/>Flash动画</div><div class="UBBContent"><a id="temp24688_href" href="http://www.d99net.net/javascript:MediaShow('swf','temp24688','http://player.youku.com/player.php/sid/XMjcyNzEwNTI=/v.swf','400','300')"><img name="temp24688_img" src="http://www.d99net.net/images/mm_snd.gif" style="margin:0px 3px -2px 0px" border="0" alt=""/><span id="temp24688_text">在线播放</span></a><div id="temp24688"></div></div></div><br/><span style="color:Red">胶济铁路火车相撞</span><div class="UBBPanel"><div class="UBBTitle"><img src="http://www.d99net.net/images/flash.gif" alt="" style="margin:0px 2px -3px 0px" border="0"/>Flash动画</div><div class="UBBContent"><a id="temp6125_href" href="http://www.d99net.net/javascript:MediaShow('swf','temp6125','http://player.youku.com/player.php/sid/XMjU4MDAzNDA=/v.swf','400','300')"><img name="temp6125_img" src="http://www.d99net.net/images/mm_snd.gif" style="margin:0px 3px -2px 0px" border="0" alt=""/><span id="temp6125_text">在线播放</span></a><div id="temp6125"></div></div></div><br/><span style="color:Red">奥运圣火</span><div class="UBBPanel"><div class="UBBTitle"><img src="http://www.d99net.net/images/flash.gif" alt="" style="margin:0px 2px -3px 0px" border="0"/>Flash动画</div><div class="UBBContent"><a id="temp88371_href" href="http://www.d99net.net/javascript:MediaShow('swf','temp88371','http://player.youku.com/player.php/sid/XMjU3MDcxNzY=/v.swf','400','300')"><img name="temp88371_img" src="http://www.d99net.net/images/mm_snd.gif" style="margin:0px 3px -2px 0px" border="0" alt=""/><span id="temp88371_text">在线播放</span></a><div id="temp88371"></div></div></div><br/><br/><span style="color:Red">西藏爆乱</span><br/><img src="http://www.d99net.net/attachments/month_0805/o2008514183310.jpg" border="0" alt=""/><br/><br/><span style="color:Red">2008年春节南方雪灾</span><div class="UBBPanel"><div class="UBBTitle"><img src="http://www.d99net.net/images/flash.gif" alt="" style="margin:0px 2px -3px 0px" border="0"/>Flash动画</div><div class="UBBContent"><a id="temp15075_href" href="http://www.d99net.net/javascript:MediaShow('swf','temp15075','http://player.youku.com/player.php/sid/XMTc1NDE1OTY=/v.swf','400','300')"><img name="temp15075_img" src="http://www.d99net.net/images/mm_snd.gif" style="margin:0px 3px -2px 0px" border="0" alt=""/><span id="temp15075_text">在线播放</span></a><div id="temp15075"></div></div></div><br/><br/><br/><br/><br/>]]></description>
		</item>
		
			<item>
			<link>http://www.d99net.net/default.asp?id=328</link>
			<title><![CDATA[如何解析Delphi中WebBrowser的BeforeNavigate2事件中的PostData]]></title>
			<author>(d99)</author>
			<category><![CDATA[技术文章]]></category>
			<pubDate>Mon,12 May 2008 14:32:10 +0800</pubDate>
			<guid>http://www.d99net.net/default.asp?id=328</guid>	
		<description><![CDATA[procedure&nbsp;TfrmMain.wbMainBeforeNavigate2&#40;Sender:&nbsp;TObject;<br/>&nbsp;&nbsp;&nbsp;const&nbsp;pDisp:&nbsp;IDispatch;&nbsp;var&nbsp;URL&#44;&nbsp;Flags&#44;&nbsp;TargetFrameName&#44;&nbsp;PostData&#44;<br/>&nbsp;&nbsp;&nbsp;Headers:&nbsp;OleVariant;&nbsp;var&nbsp;Cancel:&nbsp;WordBool);<br/>var<br/>&nbsp;&nbsp;&nbsp;i:integer;<br/>&nbsp;&nbsp;&nbsp;postStr:String;<br/>&nbsp;&nbsp;&nbsp;postAry:array&nbsp;of&nbsp;byte;<br/>begin<br/><br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;postAry&nbsp;:=&nbsp;PostData&nbsp;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;i:=0&nbsp;To&nbsp;Length&#40;postAry)&nbsp;do<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;postStr&nbsp;:=&nbsp;postStr&nbsp;+&nbsp;chr&#40;postAry[i]);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ShowMessage&#40;postStr);<br/><br/>&nbsp;<br/>end;<br/>]]></description>
		</item>
		
			<item>
			<link>http://www.d99net.net/default.asp?id=327</link>
			<title><![CDATA[Windows网络编程经验小结 [转]]]></title>
			<author>(d99)</author>
			<category><![CDATA[技术文章]]></category>
			<pubDate>Mon,12 May 2008 14:31:06 +0800</pubDate>
			<guid>http://www.d99net.net/default.asp?id=327</guid>	
		<description><![CDATA[1.&nbsp;如果在已经处于&nbsp;ESTABLISHED状态下的socket&#40;一般由端口号和标志符区分）调用<br/><br/>closesocket（一般不会立即关闭而经历TIME_WAIT的过程）后想继续重用该socket：<br/><br/>BOOL&nbsp;bReuseaddr=TRUE;<br/><br/>setsockopt&#40;s&#44;SOL_SOCKET&nbsp;&#44;SO_REUSEADDR&#44;&#40;const&nbsp;char*)&amp;bReuseaddr&#44;sizeof&#40;BOOL));<br/><br/>&nbsp;<br/><br/>&nbsp;<br/><br/>2.&nbsp;如果要已经处于连接状态的soket在调用closesocket后强制关闭，不经历<br/><br/>TIME_WAIT的过程：<br/><br/>BOOL&nbsp;&nbsp;bDontLinger&nbsp;=&nbsp;FALSE;&nbsp;<br/><br/>setsockopt&#40;s&#44;SOL_SOCKET&#44;SO_DONTLINGER&#44;&#40;const&nbsp;char*)&amp;bDontLinger&#44;sizeof&#40;BOOL));<br/><br/>&nbsp;<br/><br/>&nbsp;<br/><br/>3.在send&#40;)&#44;recv&#40;)过程中有时由于网络状况等原因，发收不能预期进行&#44;而设置收发时限：<br/><br/>int&nbsp;nNetTimeout=1000;//1秒<br/><br/>//发送时限<br/><br/>setsockopt&#40;socket，SOL_S0CKET&#44;SO_SNDTIMEO，&#40;char&nbsp;*)&amp;nNetTimeout&#44;sizeof&#40;int));<br/><br/>//接收时限<br/><br/>&nbsp;setsockopt&#40;socket，SOL_S0CKET&#44;SO_RCVTIMEO，&#40;char&nbsp;*)&amp;nNetTimeout&#44;sizeof&#40;int));<br/><br/>&nbsp;<br/><br/>&nbsp;<br/><br/>4.在send&#40;)的时候，返回的是实际发送出去的字节&#40;同步)或发送到socket缓冲区的字节<br/><br/>&#40;异步);系统默认的状态发送和接收一次为8688字节&#40;约为8.5K)；在实际的过程中发送数据<br/><br/>和接收数据量比较大，可以设置socket缓冲区，而避免了send&#40;)&#44;recv&#40;)不断的循环收发：<br/><br/>//&nbsp;接收缓冲区<br/><br/>int&nbsp;nRecvBuf=32*1024;//设置为32K<br/><br/>setsockopt&#40;s&#44;SOL_SOCKET&#44;SO_RCVBUF&#44;&#40;const&nbsp;char*)&amp;nRecvBuf&#44;sizeof&#40;int));<br/><br/>//发送缓冲区<br/><br/>int&nbsp;nSendBuf=32*1024;//设置为32K<br/><br/>setsockopt&#40;s&#44;SOL_SOCKET&#44;SO_SNDBUF&#44;&#40;const&nbsp;char*)&amp;nSendBuf&#44;sizeof&#40;int));<br/><br/>&nbsp;<br/><br/>&nbsp;<br/><br/>5.&nbsp;如果在发送数据的时，希望不经历由系统缓冲区到socket缓冲区的拷贝而影响<br/><br/>程序的性能：<br/><br/>int&nbsp;nZero=0;<br/><br/>setsockopt&#40;socket，SOL_S0CKET&#44;SO_SNDBUF，&#40;char&nbsp;*)&amp;nZero&#44;sizeof&#40;nZero));<br/><br/>&nbsp;<br/><br/>&nbsp;<br/><br/>6.同上在recv&#40;)完成上述功能&#40;默认情况是将socket缓冲区的内容拷贝到系统缓冲区)：<br/><br/>int&nbsp;nZero=0;<br/><br/>setsockopt&#40;socket，SOL_S0CKET&#44;SO_RCVBUF，&#40;char&nbsp;*)&amp;nZero&#44;sizeof&#40;int));<br/><br/>&nbsp;<br/><br/>&nbsp;<br/><br/>7.一般在发送UDP数据报的时候，希望该socket发送的数据具有广播特性：<br/><br/>BOOL&nbsp;&nbsp;bBroadcast=TRUE;&nbsp;<br/><br/>setsockopt&#40;s&#44;SOL_SOCKET&#44;SO_BROADCAST&#44;&#40;const&nbsp;char*)&amp;bBroadcast&#44;sizeof&#40;BOOL));<br/><br/>&nbsp;<br/><br/>&nbsp;<br/><br/>8.在client连接服务器过程中，如果处于非阻塞模式下的socket在connect&#40;)的过程中可<br/><br/>以设置connect&#40;)延时&#44;直到accpet&#40;)被呼叫&#40;本函数设置只有在非阻塞的过程中有显著的<br/><br/>作用，在阻塞的函数调用中作用不大)<br/><br/>BOOL&nbsp;bConditionalAccept=TRUE;<br/><br/>setsockopt&#40;s&#44;SOL_SOCKET&#44;SO_CONDITIONAL_ACCEPT&#44;&#40;const&nbsp;char*)&amp;bConditionalAccept&#44;sizeof&#40;BOOL));<br/><br/>&nbsp;<br/><br/>&nbsp;<br/><br/>9.如果在发送数据的过程中&#40;send&#40;)没有完成，还有数据没发送)而调用了closesocket&#40;)&#44;以前我们<br/><br/>一般采取的措施是&#34;从容关闭&#34;shutdown&#40;s&#44;SD_BOTH)&#44;但是数据是肯定丢失了，如何设置让程序满足具体<br/><br/>应用的要求&#40;即让没发完的数据发送出去后在关闭socket)？<br/><br/>struct&nbsp;linger&nbsp;{<br/><br/>&nbsp;&nbsp;u_short&nbsp;&nbsp;&nbsp;&nbsp;l_onoff;<br/><br/>&nbsp;&nbsp;u_short&nbsp;&nbsp;&nbsp;&nbsp;l_linger;<br/><br/>};<br/><br/>linger&nbsp;m_sLinger;<br/><br/>m_sLinger.l_onoff=1;//&#40;在closesocket&#40;)调用&#44;但是还有数据没发送完毕的时候容许逗留)<br/><br/>//&nbsp;如果m_sLinger.l_onoff=0;则功能和2.)作用相同;<br/><br/>m_sLinger.l_linger=5;//&#40;容许逗留的时间为5秒)<br/><br/>setsockopt&#40;s&#44;SOL_SOCKET&#44;SO_LINGER&#44;&#40;const&nbsp;char*)&amp;m_sLinger&#44;sizeof&#40;linger));<br/><br/>Note:1.在设置了逗留延时，用于一个非阻塞的socket是作用不大的，最好不用;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.如果想要程序不经历SO_LINGER需要设置SO_DONTLINGER，或者设置l_onoff=0；<br/><br/>&nbsp;<br/><br/>&nbsp;<br/><br/>10.还一个用的比较少的是在SDI或者是Dialog的程序中，可以记录socket的调试信息：<br/><br/>&#40;前不久做过这个函数的测试，调式信息可以保存，包括socket建立时候的参数&#44;采用的<br/><br/>具体协议，以及出错的代码都可以记录下来）<br/><br/>BOOL&nbsp;bDebug=TRUE;<br/><br/>setsockopt&#40;s&#44;SOL_SOCKET&#44;SO_DEBUG&#44;&#40;const&nbsp;char*)&amp;bDebug&#44;sizeof&#40;BOOL));<br/><br/>&nbsp;<br/><br/>&nbsp;<br/><br/>11.附加：往往通过setsockopt&#40;)设置了缓冲区大小，但还不能满足数据的传输需求，<br/><br/>我的习惯是自己写个处理网络缓冲的类，动态分配内存;下面我将这个类写出，希望对<br/><br/>初学者有所帮助：<br/><br/>&nbsp;<br/><br/>]]></description>
		</item>
		
			<item>
			<link>http://www.d99net.net/default.asp?id=326</link>
			<title><![CDATA[300万深圳人上街看圣火传递&#44;场面超强大]]></title>
			<author>(d99)</author>
			<category><![CDATA[杂谈]]></category>
			<pubDate>Fri,09 May 2008 18:36:48 +0800</pubDate>
			<guid>http://www.d99net.net/default.asp?id=326</guid>	
		<description><![CDATA[那天家里有事，没能到达深圳市区观看圣火，但看了电视现场直播，看到满路都是人，热闹到极点&#44;我也很激动~~~<br/><br/><img src="http://www.d99net.net/attachments/month_0805/i200859182951.jpg" border="0" alt=""/><br/><img src="http://www.d99net.net/attachments/month_0805/p200859183043.jpg" border="0" alt=""/><br/><img src="http://www.d99net.net/attachments/month_0805/a200859183054.jpg" border="0" alt=""/><br/><img src="http://www.d99net.net/attachments/month_0805/x200859204814.jpg" border="0" alt=""/><br/><img src="http://www.d99net.net/attachments/month_0805/d200859214457.jpg" border="0" alt=""/><br/><br/><div class="UBBPanel"><div class="UBBTitle"><img src="http://www.d99net.net/images/flash.gif" alt="" style="margin:0px 2px -3px 0px" border="0"/>Flash动画</div><div class="UBBContent"><a id="temp80218_href" href="http://www.d99net.net/javascript:MediaShow('swf','temp80218','http://player.youku.com/player.php/sid/XMjY3OTIyMDQ=/v.swf','400','300')"><img name="temp80218_img" src="http://www.d99net.net/images/mm_snd.gif" style="margin:0px 3px -2px 0px" border="0" alt=""/><span id="temp80218_text">在线播放</span></a><div id="temp80218"></div></div></div><br/><div class="UBBPanel"><div class="UBBTitle"><img src="http://www.d99net.net/images/flash.gif" alt="" style="margin:0px 2px -3px 0px" border="0"/>Flash动画</div><div class="UBBContent"><a id="temp47106_href" href="http://www.d99net.net/javascript:MediaShow('swf','temp47106','http://player.youku.com/player.php/sid/XMjY3NTM3ODQ=/v.swf','400','300')"><img name="temp47106_img" src="http://www.d99net.net/images/mm_snd.gif" style="margin:0px 3px -2px 0px" border="0" alt=""/><span id="temp47106_text">在线播放</span></a><div id="temp47106"></div></div></div><br/><div class="UBBPanel"><div class="UBBTitle"><img src="http://www.d99net.net/images/flash.gif" alt="" style="margin:0px 2px -3px 0px" border="0"/>Flash动画</div><div class="UBBContent"><a id="temp46442_href" href="http://www.d99net.net/javascript:MediaShow('swf','temp46442','http://player.youku.com/player.php/sid/XMjY4NTczNjQ=/v.swf','400','300')"><img name="temp46442_img" src="http://www.d99net.net/images/mm_snd.gif" style="margin:0px 3px -2px 0px" border="0" alt=""/><span id="temp46442_text">在线播放</span></a><div id="temp46442"></div></div></div><br/>]]></description>
		</item>
		
			<item>
			<link>http://www.d99net.net/default.asp?id=325</link>
			<title><![CDATA[5.8日 奥运圣火在深圳传递路线]]></title>
			<author>(d99)</author>
			<category><![CDATA[杂谈]]></category>
			<pubDate>Mon,05 May 2008 13:02:27 +0800</pubDate>
			<guid>http://www.d99net.net/default.asp?id=325</guid>	
		<description><![CDATA[奥运圣火深圳当然要去支持一下了&#44;呵~~~<br/><br/>奥运圣火深圳传递路线图<br/><br/>5.8日奥运圣火在深圳传递路线市民中心广场出发→福中三路→益田路→深南大道→华侨城→南海立交→深圳大学西门→创业路→凯宾斯基酒店→后海大道→滨海大道→滨河路→福田体育公园→宝安立交→宝安南路→深南中路→大剧院广场→上步路→笋岗西路→体育中心西广场<br/><br/>深圳商报<br/><br/><a href="http://sz.house.sina.com.cn/news/2008-05-05/08457395.html" target="_blank">http://sz.house.sina.com.cn/news/2008-05-05/08457395.html</a><br/><br/><img src="http://images.sz.house.sina.com.cn/cr/2008/0505/3516782795.jpg" border="0" alt=""/><br/><br/>【本报讯】北京奥运会火炬接力传递活动&#40;深圳站)定于2008年5月8日在我市举行。根据《中华人民共和国道路交通安全法》第三十九条规定，市公安交通管理部门将对奥运火炬传递行经道路实施临时禁止通行措施，具体通告如下：<br/><br/>　　一、北京奥运会火炬接力传递活动当日，市公安交通管理部门将对火炬接力传递行经地点前后道路实施禁止机动车、非机动车通行的限制措施，具体时间、路段如下：<br/><br/>　　&#40;一)7∶00至8∶30，福中三路&#40;益田路口至金田路口)双方向；<br/><br/>　　&#40;二)8∶00至8∶30，益田路&#40;深南益田立交至福中三路口)双方向；<br/><br/>　　&#40;三)8∶00至10∶40，深南路-深南大道&#40;深南益田立交至深南南海立交)东往西方向；<br/><br/>　　&#40;四)10∶40至12∶00，南海&nbsp;大道&#40;深南南海立交至创业路口)双方向；<br/><br/>　　&#40;五)11∶00至12∶00，创业路&#40;南海&nbsp;大道口至后海&nbsp;大道口)双方向；<br/><br/>　　&#40;六)11∶00至12∶00，后海&nbsp;大道&#40;创业路口至滨海&nbsp;大道辅道口)双方向；<br/><br/>　　&#40;七)11：00至12：00，滨海&nbsp;大道辅道&#40;滨海白石立交至滨海后海滨立交)西往东方向；<br/><br/>　　&#40;八)11：00至12：00，后海滨路&#40;滨海后海滨立交至海德三路口)双方向；<br/><br/>　　&#40;九)11：00至12：00，海德三路&#40;后海滨路口至海德四路口)双方向；<br/><br/>　　&#40;十)11：00至13：30，海德四路&#40;海德三路口至文心五路口)双方向；<br/><br/>　　&#40;十一)12：30至13：30，文心五路&#40;海德四路口至滨海&nbsp;大道辅道口)双方向；<br/><br/>　　&#40;十二)13：00至18：00，滨海&nbsp;大道-滨河大道&#40;文心五路口至滨河宝安立交)西往东方向；<br/><br/>　　&#40;十三)16：30至18：00，宝安南路&#40;滨河宝安立交至深南路口)双方向；<br/><br/>　　&#40;十四)17：00至18：00，深南路&#40;宝安路口至上步路口)双方向；<br/><br/>　　&#40;十五)17：00至18：30，上步路&#40;深南路口至笋岗路口)双方向；<br/><br/>　　&#40;十六)17：30至19：30，笋岗路&#40;上步路口至黄木岗立交)双方向。<br/><br/>　　二、沿线道路公交站点在交通限制时段内临时取消。<br/><br/>　　三、沿线道路支路口、停车场出入口在交通限制时段内禁止机动车辆通行。<br/><br/>　　四、在交通限制时段内，沿线道路禁止停车；市体育中心、福中三路&#40;金田路口至益田路口)、市民中心广场、红树林公园内禁止停放车辆，请有关主管部门通知各单位做好管理工作，并提前清理场地。<br/><br/>　　五、沿线道路在交通限制时段内，停止各种占道施工，并提前恢复好路面。<br/><br/>　　六、封闭深南路-深南大道&#40;深南益田立交至深南南海立交)东往西方向期间，机动车、非机动车可以绕道滨海&nbsp;大道-滨河大道、北环大道-泥岗路通行；封闭滨海&nbsp;大道-滨河大道&#40;文心五路口至滨河宝安立交)西往东方向期间，机动车、非机动车可以绕道深南路-深南大道、北环大道-泥岗路通行。<br/><br/>　　七、对沿线道路受影响的单位、住宅区和市民，请提前自行做好调节。<br/><br/>　　八、限制通行的道路和时间可能会临时调整，请广大驾驶员、行人注意交通标志标线的变化，服从公安民警的指挥。<br/><br/>　　凡违反本通告规定的，公安机关交通管理部门将依照道路交通管理法律法规的有关规定予以处罚。&nbsp;<br/><br/><br/>]]></description>
		</item>
		
			<item>
			<link>http://www.d99net.net/default.asp?id=324</link>
			<title><![CDATA[911恐怖大骗局-脆弱的变化第二版]]></title>
			<author>(d99)</author>
			<category><![CDATA[杂谈]]></category>
			<pubDate>Sun,27 Apr 2008 04:53:44 +0800</pubDate>
			<guid>http://www.d99net.net/default.asp?id=324</guid>	
		<description><![CDATA[<div class="UBBPanel"><div class="UBBTitle"><img src="http://www.d99net.net/images/flash.gif" alt="" style="margin:0px 2px -3px 0px" border="0"/>Flash动画</div><div class="UBBContent"><a id="temp7780_href" href="http://www.d99net.net/javascript:MediaShow('swf','temp7780','http://player.youku.com/player.php/sid/XMjM3MTU3OTI=/v.swf','400','300')"><img name="temp7780_img" src="http://www.d99net.net/images/mm_snd.gif" style="margin:0px 3px -2px 0px" border="0" alt=""/><span id="temp7780_text">在线播放</span></a><div id="temp7780"></div></div></div><br/><br/>非常值的一看]]></description>
		</item>
		
			<item>
			<link>http://www.d99net.net/default.asp?id=322</link>
			<title><![CDATA[Cookie注入是怎样产生的 [原创]]]></title>
			<author>(d99)</author>
			<category><![CDATA[技术文章]]></category>
			<pubDate>Sat,29 Mar 2008 01:34:43 +0800</pubDate>
			<guid>http://www.d99net.net/default.asp?id=322</guid>	
		<description><![CDATA[现在很多网站都加了防注入系统代码，你输入注入语句将无法注入~~<br/>感觉这样的防注入系统不错，但防注入系统没有注意到&nbsp;Cookies&nbsp;的问题！<br/>所以就有了Cookies注入~~<br/><br/>我们来研究一下怎样情况下才会有Cookies注入!<br/>如果你学过ASP<br/>你应该会知道&nbsp;<span style="color:Red">Request.QueryString&nbsp;</span>&#40;GET)&nbsp;或&nbsp;<span style="color:Red">Request.Form&nbsp;</span>&#40;POST)!<br/>呵，没错，这就是我们用于读取用户发给WEB服务器的指定键中的值!<br/>我们有时为了简化代码，会写成&nbsp;<br/>ID=<span style="color:Red">Request</span>&#40;&#34;ID&#34;)<br/>这样写法是简单了，但问题就来了~~~<br/>我们先看WEB服务是怎样读取数据的&#44;他是先取GET中的数据，没有再取POST中的数据&#44;还会去取Cookies中的数据&#40;晕&#44;书上没有这么说&#44;这是和小高交流时才知道~~看来书说的不全~~)<br/><br/>我们再看看防注入系统&#44;他会检测GET和POST中的数据，如果有特殊字符&#40;这里当然是注入字符了)!<br/>就禁止数据的提交!&nbsp;但他没有检测Cookies的数据！问题就来了~~~<br/>那我们怎样测试是否有Cookies注入问题~<br/><br/>请先看下面的的连接&#40;示例用&#44;所以连接不是真的)<br/><br/><span style="color:Red">http://www.xxx.com/1.asp?id=123</span><br/><br/>如果我们只输&nbsp;<span style="color:Red">http://www.xxx.com/1.asp</span><br/><br/>时，就不能看到正常的数据，因为没有参数!<br/>我们想知道有没有Cookies问题&#40;也就是有没有Request&#40;&#34;XXX&#34;)格式问题)&#44;<br/>先用IE输入&nbsp;<br/><span style="color:Red">http://www.xxx.com/1.asp</span><br/>加载网页&#44;显示不正常（没有输参数的原因)<br/>之后在IE输入框再输入<br/><span style="color:Red">javascript:alert&#40;document.cookie=&#34;id=&#34;+escape&#40;&#34;123&#34;));</span><br/>按回车&#44;你会看到弹出一个对话框&nbsp;内容是:&nbsp;<span style="color:Red">id=123&nbsp;</span><br/>之后，你刷新一个网页，如果正常显示，表示是用<br/><span style="color:Red">Request&#40;&#34;ID&#34;)</span>&nbsp;这样的格式收集数据~~~~&#44;这种格式就可以试Cookies注入了<br/><br/>在输入框中输入<br/><span style="color:Red">javascript:alert&#40;document.cookie=&#34;id=&#34;+escape&#40;&#34;123&nbsp;and&nbsp;3=3&#34;));</span><br/>刷新页面&#44;如果显示正常&#44;可以再试下一步&#40;如果不正常&#44;就有可能也有过滤了)<br/><br/><span style="color:Red">javascript:alert&#40;document.cookie=&#34;id=&#34;+escape&#40;&#34;123&nbsp;and&nbsp;3=4&#34;));</span>刷新一下页面<br/>如果不正常显示，这就表示有注入了~~~<br/><br/>如果程序员是用&nbsp;<br/><span style="color:Red">Request.QueryString</span><br/>或&nbsp;<br/><span style="color:Red">Request.Form</span><br/>收集数据的话，是无法利用Cookies绕过防注入系统进行注入的，因为服务程序是直截从GET或POST中读取数据的，Cookies是否有数据&#44;WEB服务器是不理的&#44;所以就无法利用了！~<br/><br/>--------------------------------------------------------------------------<br/>为了方便不懂的朋友了解<br/><span style="color:Red">javascript:alert&#40;document.cookie=&#34;id=&#34;+escape&#40;&#34;123&#34;));</span><br/>的意思&#44;我说明一下<br/><span style="color:Red">document.cookie=&#34;id=&#34;+escape&#40;&#34;123&#34;)&nbsp;</span>&nbsp;就是把&nbsp;123&nbsp;保存到Cookies&nbsp;的&nbsp;ID&nbsp;中<br/><span style="color:Red">alert&#40;xxx)</span>&nbsp;就是弹对话框<br/><br/><br/>后话<br/>==========================================================<br/>Cookie注入已不算是什么新技术，但还算是很管用的方法&#44;或者有一天，防注入系统会加入Cookies注入检测!<br/><br/>啊D&nbsp;2008-03-29<br/><a href="http://www.d99net.net" target="_blank">http://www.d99net.net</a><br/>]]></description>
		</item>
		
</channel>
</rss>