ASP.net隨機數應用執行個體

來源:互聯網
上載者:User
家可能都用過Chinaren的校友錄,不久前它的留言簿上加了一個防止灌水的方法,就是系統每次產生一個由隨機的數字和字母組成的圖片,每次留言必須正確地輸入這些隨機產生的字元,否則不能添加留言。這是一個很好的防止惡意攻擊的方法,其核心的技術就是如何產生隨機數。Chinaren網站是使用PHP實現的,而我們可以充分利用ASP.net的強大功能很輕易地實現。

在.net Framework中提供了一個專門用來產生隨機數的類System.Random,使用這個類時必須匯入System命名空間。當然,命名空間System在每個ASP.net頁面中都是自動匯入的,所以我們可以直接使用這個類。

對於隨機數,大家都知道,電腦不可能產生完全隨機的數字,所謂的隨機數發生器都是通過一定的演算法對事先選定的隨機種子做複雜的運算,用產生的結果來近似的類比完全隨機數,這種隨機數被稱作偽隨機數。偽隨機數是以相同的機率從一組有限的數字中選取的。所選數字並不具有完全的隨機性,但是從實用的角度而言,其隨機程度已足夠了。偽隨機數的選擇是從隨機種子開始的,所以為了保證每次得到的偽隨機數都足夠地“隨機”,隨機種子的選擇就顯得非常重要。如果隨機種子一樣,那麼同一個隨機數發生器產生的隨機數也會一樣。一般地,我們使用同系統時間有關的參數作為隨機種子,這也是.net Framework中的隨機數發生器預設採用的方法。

我們可以使用兩種方式初始化一個隨機數發生器:

第一種方法不指定隨機種子,系統自動選取目前時間作為隨機種子:

Random ro = new Random();

第二種方法可以指定一個int型參數作為隨機種子:


int iSeed=10;

Random ro = new Random(10);

之後,我們就可以使用這個Random類的對象來產生隨機數,這時候要用到Random.Next()方法。這個方法使用相當靈活,你甚至可以指定產生的隨機數的上下限。

不指定上下限的使用如下:

int iResult;

iResult=ro.Next();

下面的代碼指定返回小於100的隨機數:

int iResult;

int iUp=100;

iResult=ro.Next(iUp);

而下面這段代碼則指定傳回值必須在50-100的範圍之內:


int iResult;

int iUp=100;

int iDown=50;

iResult=ro.Next(iDown,iUp);

除了Random.Next()方法之外,Random類還提供了Random.NextDouble()方法產生一個範圍在0.0-1.0之間的隨機的雙精確度浮點數:


double dResult;

dResult=ro.NextDouble();

另外一個與Random.NextDouble()方法相似的方法是Random.Sample(),它跟Random.NextDouble()方法唯一的區別在於存取層級,我們可以看看它們的原始聲明:


protected virtual double Sample();

public virtual double NextDouble();

Random.Sample()方法是保護方法,只允許子類的對象訪問,而Random.Sample()方法則可以看作是Random.Sample()的公開版本。一般地,使用者在Random的子類中重寫Sample()方法來得到更一般的分布。 這個例子中,我們使用Random.Next()方法來產生隨機數。

下面這個函數是這個例子的核心,我們利用他來產生一個隨機的int數組:

private int []GetRandomArray(int Length,int Up,int Down){ int iFirst=0; int []rtArray=new Int32[Length]; Random ro=new Random(Length*unchecked((int)DateTime.Now.Ticks)); iFirst=ro.Next(Up,Down); rtArray[0]=iFirst; for(int i=1;i

讀者或許都注意到了,我們採用了一種相當麻煩的方式來產生這個隨機數組,為什麼不簡單地使用如下代碼呢?請先看下面代碼,這裡我們使用了系統時間作為隨機種子,連續擷取兩個隨機數,並且將其輸出:

< %@ Page Language="C#" Debug="true" Trace="false" TraceMode="SortByCategory"% >< % @Import namespace="System" % >
< script language=C# runat=server >
public void Page_Load(object sender,EventArgs e){ int re=0; int re1=0; GetRandomDefault(ref re); GetRandomDefault(ref re1); RandomNum.Text=re.ToString(); RandomNum.Text+=" "+re1.ToString();}private void GetRandomDefault(ref int re){ Random ro=new Random(unchecked((int)DateTime.Now.Ticks)); re=ro.Next(10,20);}private void GetRandomByInt(ref byte []re){ Random ro=new Random(); ro.NextBytes(re);}
< /script >
< html >
< head >
< title >隨機數測試< /title >
< meta http-equiv="Content-Type" content="text/html; charset=gb2312" >
< /head >

< body bgcolor="#FFFFFF" text="#000000" >
< form runat=server >
< asp:Label id="RandomNum" runat=server / >

< /form >
< /body >
< /html >

下面是筆者機器上產生的結果的:

是的,如你所見,產生了一樣的兩個隨機數,無論重複多少次,都是一樣的。原因在哪裡呢?

不要以為使用系統時間作為隨機種子就萬無一失了——如果應用程式在一個較快的電腦上運行,則該電腦的系統時鐘可能沒有時間在此建構函式的調用之間變更,Random 的不同執行個體的種子值可能相同。這種情況下,我們就需要另外的演算法來保證產生的數位隨機性。所以為了保證產生的隨機數足夠“隨機”,我們不得不使用複雜一點的方法來獲得隨機種子。

在上面的這段程式中,我們首先使用系統時間作為隨機種子,然後將上一次產生的隨機數跟迴圈變數和一個與系統時間有關的整型參數相乘,以之作為隨機種子,從而得到了每次都不同的隨機種子,保證了產生足夠“隨機”的隨機數。

得到整型的隨機數組以後,我們將它變成字串,然後使用System.Drawing中與GDI+相關的類產生一個圖片並且在網頁上顯示出來。

  產生圖片的ASP.net頁面全部代碼如下:

< %@ Page Language="C#" Debug="true" Trace="false" TraceMode="SortByCategory"% >< % @Import namespace="System.Drawing" % >< % @Import namespace="System.Drawing.Imaging" % >< % @Import namespace="System.Drawing.Text" % >< % @Import namespace="System.IO" % >< script language=C# runat=server >
public void Page_Load(object sender,EventArgs e){ string strNum=GetRandomString();
string strFontName;
int iFontSize;
int iWidth;
int iHeight;
strFontName="宋體";
iFontSize=12;
iWidth=10*strNum.Length;
iHeight=25;

Color bgColor=Color.Yellow;
Color foreColor=Color.Red;

Font foreFont=new Font(strFontName,iFontSize,FontStyle.Bold);

Bitmap Pic=new Bitmap(iWidth,iHeight,PixelFormat.Format32bppArgb);
Graphics g=Graphics.FromImage(Pic);
Rectangle r=new Rectangle(0,0,iWidth,iHeight);

g.FillRectangle(new SolidBrush(bgColor),r);

g.DrawString(strNum,foreFont,new SolidBrush(foreColor),2,2);
MemoryStream mStream=new MemoryStream();
Pic.Save(mStream,ImageFormat.Gif);
g.Dispose();
Pic.Dispose();

Response.ClearContent();
Response.ContentType="image/GIF";
Response.BinaryWrite(mStream.ToArray());
Response.End();
}
private int []GetRandomArray(int Length,int Up,int Down)
{
int iFirst=0;
int []rtArray=new Int32[Length];
Random ro=new Random(Length*unchecked((int)DateTime.Now.Ticks));
iFirst=ro.Next(Up,Down);
rtArray[0]=iFirst;
for(int i=1;i< Length;i++)
{
Random ri=new Random(i*iFirst*unchecked((int)DateTime.Now.Ticks));
rtArray[i]=ri.Next(Up,Down);
iFirst=rtArray[i];
}
return rtArray;
}

其中產生圖片的部分相對複雜,但由於不是本文的主題所在,所以本文不對之做詳細說明,有興趣的讀者可以參考杜亮編寫的《親密接觸ASP.net》一書中的相關內容。

最後我們可以編寫一個普通的HTML頁面來查看效果,只要把圖片的src屬性指向這個頁面就行了(這裡我們假設上面那個ASP.net檔案的名字是“RandomPic.aspx”):

< !DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
< HTML >
< HEAD >
< TITLE > New Document < /TITLE >
< META NAME="Generator" CONTENT="EditPlus" >
< META NAME="Author" CONTENT="" >
< META NAME="Keywords" CONTENT="" >
< META NAME="Description" CONTENT="" >
< /HEAD >

< BODY >
< img src="RandomPic.aspx" >
< /BODY >

< /HTML >

在筆者的機器上成功地看到了如下結果:

要實現像Chinaren網站那樣的防惡意攻擊的效果,只需要在留言簿的頁面裡產生隨機數並且編寫相應的JavaScript驗證代碼(事實上這個工作可以交給ASP.net的驗證控制項很容易地完成),然後傳遞到產生圖片的頁面裡產生圖片提示使用者就可以了。

除此以外,隨機數還有其它很多用途,特別是開發遊戲的時候更是必不可少。到此,讀者應該完全掌握在ASP.net中隨機數的產生方法,如此,本文的目的也就達到了。

最後,有興趣的讀者可以試著解決這個問題:

在橋牌遊戲中,發牌可以視作一個隨機過程,但是後續過程受到前面的影響,即已經發出去的牌不可能再次發出。試編寫一個程式類比發牌過程。

作者:未知  請速與本人聯絡

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.