- 465.50 KB
- 2022-07-30 发布
- 1、本文档由用户上传,淘文库整理发布,可阅读全部内容。
- 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,请立即联系网站客服。
- 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细阅读内容确认后进行付费下载。
- 网站客服QQ:403074932
上学吧http://www.shangxueba.com数据窗口自适应打印纸张大小函数名:f_dw_Zoom Writtenby Vial.Z 参数: datawindowdw_print-->要打印的数据窗口 integer nMinZoom-->极限缩小比例(缩小范围不能太大,否则不清晰) 返回值: -1 error 0 找不到合适的值 >0 找到的合理值 作用: 纸张大小满足数据窗口的要求,返回100; 当数据窗口宽度太大,无法在一页纸张上打印时,该程序寻找一个最佳缩小比例值, 使得数据窗口的内容恰好能在当前设定的纸张下打印出来。 如窗口缩小到85%可以在一页上打印时,返回值为85-------------------------------------------------------*/ifnotIsValid(dw_print)then return-1endifdw_print.object.datawindow.print.preview=true /*预览模式必须打开*/dw_print.SetRedraw(FALSE) /*调整放大比例过程中,停止重绘控件,节省程序时间*/stringls_H_Page /*水平打印占据的页数*/stringls_zoom /*设定的缩小百分比整数值*/Integerli_max=100 /*从百分百大小开始测试*/integerli_min /*极限缩小值,最多缩小到nn%*/Integerli_use /*当前测试值*/Integerli_OK =0 /*最优可用值*/Integerli_count=0 /*算法循环执行的次数*/li_min=nMinZoom /*赋最小测试值*/li_use=li_max /*从原始大小(100)开始测试。逐渐缩小放大比例*/dowhileli_min<=li_max li_count++ /*调整zoom值,并测试当前宽度打印时横向所占的面数*/ ls_zoom=string(li_use) dw_print.modify("datawindow.zoom="+上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comls_zoom) ls_H_Page=dw_print.describe("evaluate('PageCountAcross()',"+string(dw_print.object.datawindow.firstrowonpage)+")" ) ifInteger(ls_H_Page)=1then /*一页足以打印出来*/ li_OK=li_use /*记录这个可用的缩小比例*/ li_min=li_use+1 else li_max=li_use-1 endif choosecaseli_max-li_min caseIS<0 exit case0 li_use=li_min case1 li_use=li_min caseelse li_use=Int((li_max+li_min)/2) /*小于等于的最小整数*/ endchoose loop/*还原窗口原大小*/ifli_OK<>100then dw_print.modify("datawindow.zoom=100")endifdw_print.object.datawindow.print.preview=false dw_print.SetRedraw(TRUE) /*恢复重绘控件*/returnli_OK使用框架跨域运行不丢失session的方法首先说明原理:系统是认一个一个程序范围的,一般来说,一个IE默认为一个程序范围. 框架因为有了跨域的内容,所以它首先默认的是框架程序本身的程序范围,这样使得框架内的程序范围得不到确认. 为了让这个IE默认为框架内的程序范围,所以我使用了多次跳转.上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com 首先,跳出本框架,进入一个无框架的需要session值的网站页面(就叫它B服务器的页面),并在这个页面中生成一个session以便系统自动生成一个sessionID,然后又跳回到有框架的页面.因为系统已经为这个IE生成了一个sessionID,所以只要不关掉这个IE,系统一直以为这个IE是本程序范围的.这样,再次生成的session值就得以在这个ID中生存下来. 也就达到了骗过系统的目的. 再补充一点,二次跳转使用了不同的方式,原因是我需要把框架外的信息丢弃,而要保存框架内的信息. 而不同的跳转方式会丢弃或保存跳转前的信息的。 程序实现方式: 文件1: 框架文件:index.htm(运行在服务器A上) 奇豪门业 文件2:index.asp(运行在服务器B上,作用跳转和生成sessionID) <% ifsession("xm2")=""then session("xm2")="eee" '上面这一句的目的只是为了使用session,让系统为这个IE生成一个sessionID,并且判断一下是不是已经跳转过,免得引起死循环。 %> <% ,上面这一句是回到框架,注意:只能用上面这个跳转的方法,别用下面的跳转方法。 else Response.Redirect"index2.asp" '上面一句才是真正地跳转运行服务器B上的程序!注意:也只能用这方法跳! endif%> 经过以上的跳转,本IE已经有了服务器B上的sessionID,也就是说,框架虽然是在服务器A上的主框架运行,但它可以确保服务器B上的session不丢失,达到跨域运行的目的。使用MD5变换算法防穷举(冲撞)破译密码 MD5是在Web应用程序中最常用的密码加密算法。由于MD5是不可逆的,因而经过MD5计算得到后的密文,不能通过逆向算法得到原文。 回顾在Web应用程序中使用MD5加密文本密码的初衷,就是为了防止数据库中保存的密码不幸泄露后被直接获得。但攻击者不但拥有数据量巨大的密码字典,而且建立了很多MD5原文/密文对照数据库,能快速地找到常用密码的MD5密文,是破译MD5密文的高效途径。然而,MD5密文数据库所使用的是最常规的MD5加密算法:原文-->MD5-->密文。因此,我们可以使用变换的MD5算法,使现成的MD5密文数据库无所作为。 下面演示一些变换算法的例子 当然,在其它的Web开发语言中,也大同小异,完全能得到相同的结果。变换一:循环MD5 最容易理解的变换就是对一个密码进行多次的MD5运算。自定义一个函数,它接受$data和$times两个形参,第一个是要加密的密码,第二个是重复加密的次数。实现这种变换有两种算法—— 0) { $data = md5($data); $times--; return md5_1_2($data, $times); //实现递归 } else { return $data; }}?>变换二:密文分割MD5 尽管用户的密码是不确定的字符串,但是只要经过一次MD5运算后,就会得到一个由32个字符组成的字符串,这时可以再针对这个定长字符串变换。有点BT的算法是,把这段密文分割成若干段,对每段都进行一次MD5运算,然后把这堆密文连成一个超长的字符串,最后再进行一次MD5运算,得到仍然是长度为32位的密文。当然,这种密文分割的具体算法是数之不尽的,比如可以把原密文分割成16段每段两字符、8段每段4字符,或者每一段的字符数不相等……变换三:附加字符串干涉 在加密过程的一个步骤中,附加一个内容确定的字符串(比如说用户名),干涉被加密的数据。不可以用随机字串,因为这样会使原算法无法重现。这种算法在某些情况下是很具有优势的,比如说用于大量的用户密码加密,可以把用户名作为附加干涉字串,这样攻击者就算知道你的算法,也很难从他们手中的字典中一下子生成海量的对照表,然后大量地破译用户密码,只能有针对性的穷举为数不多的用户。变换四:大小写变换干涉 由于PHP所提供的md5()函数返回的密文中的英文字母全部都是小写的,因此我们可以把它们全部转为大写,然后再进行一次MD5运算。变换五:字符串次序干涉 把MD5运算后的密文字符串的顺序调转后,再进行一次MD5运算。变换六、变换七、变换八…… MD5变换算法是数之不尽的,甚至无须自己再去创造,就用上面的五个互相组合就可以搞出很BT的算法。比如说先循环加密后再分割,并在每一段上附加一个字符串再分别加密,然后变换大小写并颠倒字符串顺序后连成一个长字符串再进行MD5运算…… 如果真的很不幸,由于某些漏洞,比如说SQL Injection或者文件系统中的数据库被下载而异致用户密码数据暴露,那么MD5变换算法就能大大地增加破译出密码原文的难度,首先就是使网上很多的MD5原文/密文对照数据库(要知道,这是破译MD5最高效的方法)没有用了,然后就是使攻击者用常规算法去穷举一串由变换算法得到的密文而搞得焦头烂额。当然,MD5变换算法特别适合用于非开源的Web程序使用,虽说用在开源的程序中优势会被削弱(大家都知道算法),但是也能抑制MD5原文/密文对照数据库的作用。要进行这些复杂的变换运算,当然就要花费的更多的系统开销了,然而对于安全性要求很严格的系统来说,多付出一些来换取高一点的安全性,是完全值得的。使用Java范型需要注意的地方1、静态方法要想范化,需要指定其类型参数2、非范化类型中的实例方法要想范化,也需要制定其类型参数。 3、范化类型中的实力方法可以直接使用其类型本身的类型参数。 上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com4、范型不是协变的,即List不是List的子类。 5、不能实例化范型类型的数组,即newList[3]是不合法的,提示除非类型参数是一个未绑定的通配符,即newList<?>[3]是合法的。 6、构造延迟,在代码编写时我们不能通过类型参数来构造一个该类型的实例,原因是我们不知道如何构造,类型参数的实际类型是在运行时确定的。 7、对于注意5所描述的问题我们有一个解决方法是Listlist=(List[])newObject[3];但是如果是运行时建立数组呢,类型信息是运行时确定的,那就换种写法T[]tarray=(T[])newObject[3]; 8、上面的数组构造是不被推荐的,最好的方法是将类型信息传递到方法中,如method(Classtype){V[]array=(V[])Array.newInstance(type,length);},可以参考ArrayList类的toArray(T[]a)方法的实现。 9、构造通配符引用,如果set是一个Set<?>类型,则Set<?>set2=newHashSet<?>(set);是不合法的,改成Set<?>set2=newHashSet 上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com浅谈ASP程序实现自动采集程序及入库<%'声明取得目标信息的函数,通过XML组件进行实现。FunctionGetURL(url)SetRetrieval=CreateObject("Microsoft.XMLHTTP")WithRetrieval.Open"GET",url,False.SendGetURL=bytes2bstr(.responsebody)'对取得信息进行验证,如果信息长度小于100则说明截取失败iflen(.responsebody)<100thenresponse.write"获取远程文件"&url&"失败。"response.endendifEndWithSetRetrieval=NothingEndFunction'二进制转字符串,否则会出现乱码的!functionbytes2bstr(vin)strreturn=""fori=1tolenb(vin)thischarcode=ascb(midb(vin,i,1))ifthischarcode<&h80thenstrreturn=strreturn&chr(thischarcode)elsenextcharcode=ascb(midb(vin,i+1,1))strreturn=strreturn&chr(clng(thischarcode)*&h100+cint(nextcharcode))i=i+1endifnextbytes2bstr=strreturnendfunction'声明截取的格式,从Start开始截取,到Last为结束FunctionGetKey(HTML,Start,Last)filearray=split(HTML,Start)filearray2=split(filearray(1),Last)GetKey=filearray2(0)EndFunctionDimSoftid,Url,Html,Title上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com'获取要取页面的IDSoftId=Request("Id")Url="http://www3.skycn.com/soft/"&SoftId&".html"Html=GetURL(Url)'以截取天空软件的软件名为例子Title=GetKey(Html,"","")'打开数据库,准备入库dimconnstr,conn,rs,sqlconnstr="DBQ="+server.mappath("db1.mdb")+";DefaultDir=;DRIVER={MicrosoftAccessDriver(*.mdb)};"setconn=server.createobject("ADODB.CONNECTION")conn.openconnstrsetrs=server.createobject("adodb.recordset")sql="select[列名]from[表名]where[列名]='"&Title&"'"rs.opensql,conn,3,3ifrs.eofandrs.bofthenrs("列名")=Titlers.updatesetrs=nothingendifsetrs=nothingResponse.Write"采集完毕!"%>朴素(Naive)字符串匹配算法代码 作为最原始的字符串匹配算法,它的时间复杂度是O((n-m+1)m) #include\"stdio.h\" //计算字符串的长度 intLength(char*s) { intcount=0; while(*s++!=\’\\0\’) count++; returncount; } //字符串匹配 voidNaiveStringMatching(char*t,char*p) { intn=Length(t); int上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comm=Length(p); if(n\"); Stringline=in.readLine(); StringBufferbuf=newStringBuffer(line); for(inti=0;i4millionboardevaluations).AninterestingquoteillustratingthecomputationalintensityofGOgamesonafull19×19boardisthat“thenumberofpossibleGOgamesfarexceedsthenumberofatomsintheuniverse”(moredetailsandderivationhere)InterestingFacts:LowerboundonnumberofpossibleGOgameson19×19boardisabout10^(10^48).Upperboundis10^(10^171). 我们选择蒙特卡罗算法的原因之一是围棋中应用极小极大算法(MinimaxAlgorithm,一种在棋类中常用的选择“最佳”的下一步着法的算法,参考这里)来计算2步或3步之后的着法产生的计算量就非常巨大(在9x9的棋盘上计算4步着法就需要做81^4(大于4百万)次盘面估值)。有一句非常形象的话来形象围棋(19x19)的计算复杂度:远大于宇宙中所有原子的个数(参考这里)。实际上围棋(19x19)的计算下限的10^(10^48),上限是10^(10^171)。 Soanotherwayweusedtoevaluatehow“good”amoveiswastousetheMonteCarlomethod.WhattheMonteCarlomethoddoesinthiscasetoestimatehowgoodorbadacertainmoveisforagivenboardpositionistoplay“virtualgames”illustratingwhatwouldhappeniftwoRandomAIs(AIsplayingcompletelyrandomly)playedoutthosemoves.Thewayitdoesthisistostartfromthisboardpositionandplayeachoftheviablemovesinafixednumberofgameswithallsubsequentmovesbeingcompletelyrandom.Thenafterallofthe”virtualgames”arefinished,wewouldaveragethetotalscoresofeachgameandletitrepresentthe“goodness”oftheoriginalmovewhichspawnedthatgame.Finallybychoosingthemovewiththehighestaveragescore,theMonteCarloAIwouldthenplaythismoveintheactualgameitself,basedontheassumptionthatthemoveswhichscorebetteroveralargenumberofrandomgameswouldbe“better”movesingeneral.上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com 因此我们使用蒙特卡罗算法来评估一个着法有多好(差)。蒙特卡罗算法评估某一着法有多好(差)的方法是由两个随机AI(选择的着法完全随机)对一个给定的盘面下若干盘“虚拟棋”。从一个给定的盘面开始,然后对每一可行着法计算指定数量的后续着法完全随机的“虚拟棋”。之后,我们统计所有可行走法的平均值,以反映出“好”的着法。最后是选择有着最高的平均值的着法,蒙特卡罗AI在真正的棋局中应用这一着法。这是基于假设这一高分着法通常比其它的选择产生的结局都要好来做的。 Forourproject,weletourAIplayabout500virtualgamesforeachmove,whichonslowercomputersactuallycantakeawhile,butitisstillfarfasterthantryingtousetheMinimaxAlgorithmtolookaheadjust4moves(justover1millionevaluationscomparedto4million+).Inaddition,theresultsoftheMonteCarloAIareprettygoodasitcangenerallydefeatmostofourotherAIs(MinimaxAIlooking2or3movesaheadandRandomAIs),anditevenputupadecentfightagainstsomebeginnerhumanplayersaswell. 在我们的项目中,我们让AI对每一个着法下500局“虚拟棋”。这也有不小的计算量,如果机器比较“破落”,可能需要计算挺长的一段时间。但它仍然比用极小极大算法向前计算4步(计算量大约是9x9棋盘计算4步(约需评估4百多万个盘面,见前文)的1百万倍)要快得多。蒙特卡罗AI的效果很好,它通常能够打败极大极小算法AI(计算2或3步)和随机AI,这样的棋力跟初学围棋的人类差不多。本文最初发表于赖勇浩(恋花蝶)的博客,http://blog.csdn.net/lanphaday,如蒙转载,敬请保留全文完整,未经许可,不得用以商业用途。 WorthnotingisthatoneveryimportantfactorforhowwelltheMonteCarlomethodworksinthiscaseisthescoringfunctionwhichyouusetodecideaplayer’sscoregivenacertainboardposition.Theoneweusedwhichisverystraightforwardandrelativelysimpleinthatitjustassignsanemptyspottowhoeverhasthecloseststonestothatspot,withtiesbeingbrokenbynumberofstonesnearit.Thisisn’tthemostaccurateoreffectivescoringmethod,butitworkeddecentlywellenoughforourpurposes. 值得注意的是蒙特卡罗算法依赖于一个很重要的因素,那就是对特定盘面的估值函数。我们用了一个简单的函数:把空的点归属于最近的棋子,如果有多个棋子,则平分。它可能不够准确和高效,但对于我们来说,已经足够。 TheAIwedeveloppedusingMonteCarlomethodswasoneofthebetterAIswemade,butitisstillnowherenearthecapabilitiesofadecentlyexperiencedamateurhumanplayer.Especially,theAIstartslosingoutneartheendgamewhentacticsmeanalotmorethanoverallstrategy(whichMonteCarloandMinimaxseemtodowellat).Andthefactthatweareusingrandommovestoplayeach“virtualgame”meansthatwecangetverydifferentresultseachtimeweplayit,especiallyneartheendgamewhereresultsofmovesreallydependonthequalityofsubsequentmoves,whichinthiscasearecompletelyrandom.上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com 我们开发的蒙特卡罗算法AI是我们开始的AI中较好的一个,但它与训练有素的棋手仍然相距甚远。尤其在游戏将结束时,战术比策略显得更为重要,AI就容易输棋(蒙特卡罗算法和极小极大算法都有这种问题)。我们使用随机着法来下每一个局“虚拟棋”,所以我们每一次都会得到不同的结果。在将近结局的时候,最后的结果依赖于后续着法的质量,而在这里后续着法是完全随机的,所以效果差强人意。 GOisconsideredbymanytobethemostcomplicatedgameweknowoftodate,anditisveryunlikelythatwewillbeabletocomeevenmarginallyclosetosolvingthegameanytimesoon(wanttoeventrywritingout10^(10^48)?).Butitseemsequallyunlikelythatpeoplewillgiveupontryinganytimesooneither,ashasbeenprovenbyhumantenacityinthefaceofother“insurmountable”oddsinthepast(landingontheMoon…). 围棋被认为是目前为止最复杂的游戏,而且我们不可能在很近的将来解决它。但大家都不会放弃,因为已经证明人类在面对“不可逾越”的问题上是坚忍不拔的(例如登月)。 NOTE:whenIsaid“random”inthispost,Inaturallymeanthepseudorandomnumbergeneratorscomputersuse,whichisn’treallyrandom,butwasmorethancloseenoughforourproject. 注意:本文中的“随机”是指计算机使用的伪随机数,而非真随机,但从项目中来看已经不错了。每一位中国程序员都应该精通英语Cnprog是程序技术问题问答网站Stackoverflow的中文克隆(就像Solidot是技术社区Slashdot的中文克隆),英语是全世界事实上的通用语言,也是软件开发中的标准语言,但是问题是“每一位程序员都应该精通英语吗”? 一位在上海生活了9年的工程师和高管JonHancock认为他们必须掌握,他说,“如果你等待文档所用的语言,工具和库都被翻译到本地语言,那么你将永远是一位边缘程序员。”他以个人经历为例,“无论何时提出技术文档选用何种语言之类问题时候,(中国)官员毫无例外的要求只用英文。他们想让程序员们强迫学习英文。他们理解一个面向全球市场的技术社区所使用的语言肯定是英语。如果语言不统一,那么尝试去传达功能和传达技术要求就变得几乎不可能。在这一点上,英语保留下了选择。但这是对于要求和最终产品而言。如果学习和基本知识交流呢?”在上海举行的BarCamps会议上,所有与会者都是使用英语。但是当中国人使用自己的语言,交流就会更迅速和更深入。作者称虽说世界是平的,但其实并不平坦,保留中文选择也是必要的。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com猫吃老鼠的STL实现方法一、看到猫吃老鼠问题,感觉如果用STL将更加简单。在实现时将问题稍作修改,变成总共n个老鼠,每隔m个吃一个,求最后剩下哪一个,并用STL实现。 二、代码 #include #include usingnamespacestd; inteat(constinttotal,constintspace) { if(total<=0||space<=0) { return-1; } vectorv; vector::iteratorit; //初使化向量 for(inti=1;i<=total;++i) { v.push_back(i); } intj=1; it=v.begin(); while(v.size()>1) { //如果数到第m个,则删除它,并且从头开始数 //迭代器不需要后移,因为删除之后自动就指向下一个元素 if(space==j) { v.erase(it); j=1; } else { ++it; ++j; } //如果到最后了,让迭代器指向第一个元素 if(it>=v.end()) { it=上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comv.begin(); } } //现在只有一个元素了,那么第一个元素就是我们需要的 return(*v.begin()); } voidmain(void) { inttotal; intspace; total=5; space=1; cout<<\"总共:\"<sckClosedThen.sckServer.Close .sckServer.Accept(requestID) EndWithEndSub 下面我们来建立客户端程序:新建一个工程,名为Client,把窗体名为Client,在上面加入一个winsock控件,名为sckClient,协议为TCP/IP协议。再加一个按钮cmdConnect在窗体模块中加入代码:PrivateSubform_Load() WithMe .sckClient.RemoteHost="127.0.0.1"'设置远程IP,本例设为本机。 .sckClient.RemotePort=88917'远程端口,就为server中的设置一样. EndWithEndSubPrivatesubcmdConnect_Click() SckClient.ConnectEndsub 至此,单击Connect按钮我们的两个工程已经可以进行通信了,但看不见,你可以在Client中的sckClient_Connect事件中加入代码:debug.print“Connetionsuccessful!”来查看。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com 这仅是第一步,一点工作也做不了,下面我们来为它们添加功能。为了简单,本文章只实现一点小小的功能―――关机,重启,注销。好,开始吧! 在Server工程中新建一个模块,Name为modApi,这个模快为一些API函数,添加如下API函数:PublicDeclareFunctionExitWindowXXXLib"user32"Alias"ExitWindowXXX"(ByValuFlagsAsLong,ByValdwReservedAsLong)AsLongPublicConstEWX_LOGOFF=0PublicConstEWX_REBOOT=2PublicConstEWX_SHUTDOWN=1PublicDeclareFunctionClipCursorLib"user32"Alias"ClipCursor"(lpRectAsAny)AsLongPublicTypeRECT LeftAsLong TopAsLong RightAsLong BottomAsLongEndType 注:在两个socket中编程中,进行通信的重要事件是DataArrival事件,用于接收远程数据。利用C#实现分布式数据库查询 本文提出了在.Net环境下使用一种新的开发语言C#结合ADO.Net数据访问模型来开发分布式数据库系统,大大简化了开发过程…… 随着传统的数据库、计算机网络和数字通信技术的飞速发展,以数据分布存储和分布处理为主要特征的分布式数据库系统的研究和开发越来越受到人们的关注。但由于其开发较为复杂,在一定程度上制约了它的发展。基于此,本文提出了在.Net环境下使用一种新的开发语言C#结合ADO.Net数据访问模型来开发分布式数据库系统,大大简化了开发过程。 1分布式数据库系统就其本质而言,分布式数据库系统的数据在逻辑上是统一的,而在物理上却是分散的。与集中式数据库相比它有如下主要优点: ·解决组织机构分散而数据需要相互联系的问题。 ·均衡负载。负载在各处理机间分担,可避免临界瓶颈。 ·可靠性高。数据分布在不同场地,且存有多个副本,即使个别场地发生故障,不致引起整个系统的瘫痪。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com·可扩充性好。当需要增加新的相对自主的组织单位时,可在对当前机构影响最小的情况下进行扩充。分布式数据库系统虽然有诸多优点,但它同时也带来了许多新问题。如:数据一致性问题、数据远程传递的实现、通信开销的降低等,这使得分布式数据库系统的开发变得较为复杂。幸运的是,微软的.Net开发环境为我们提供了C#开发语言和ADO.Net数据访问模型,结合两者来开发分布式数据库系统能够大大简化开发工作。 2远程处理框架和ADO.Net 开发分布式数据库系统需要解决的两个重要问题是:各场地间的数据通信以及对数据库的操作及管理。使用C#结合ADO.Net能够高效、可靠地解决这两方面的问题。具体表现为,在C#中通过使用.Net远程处理框架能够方便地解决数据、命令远程传递问题;C#通过ADO.Net对数据库进行操作,使分布式数据库系统中对数据库的各种操作变得高效、可靠,同时易于解决数据一致性问题。 2.1.Net远程处理框架实现数据和命令的远程传递有三种方式。第一种是使用报文或消息的方式,把要传送的数据转化为流格式,再通过套接字编程用报文的形式发送到远程主机。此种方法麻烦,不易实现。第二种是使用WebService,即各远程主机提供一个数据库查询服务的WebService。这种方式只能对单个场地进行查询,无法实现多场地的联合查询。第三种是使用.Net远程处理框架(.NetRemotingFramework)技术,它将远程调用的技术细节隐藏起来,服务程序只需通过简单的设置就可以把本地对象变成为远程提供服务的远程对象,客户端可以像访问本地对象一样透明地访问远程对象,所有的消息、报文等都交给.NetRemoting对象处理,大大简化了开发。远程处理的一般过程如图1所示:首先,服务器端创建一个服务器类的实例,远程处理系统创建一个表示该类的代理对象,并向客户端对象返回一个对该代理的引用。当客户端调用方法时,远程处理基础结构连接检查类型信息,并通过信道将该调用发送到服务器进程。侦听信道获得该请求并将其转发给服务器远程处理系统,服务器远程处理系统查找(或在必要时创建)并调用被请求的对象。然后,此过程将反向进行,服务器远程处理系统将响应捆绑成消息并由服务器信道发送到客户端信道。最后,客户端远程处理系统通过代理将调用的结果返回给客户端对象。 2.2ADO.NetADO.Net以XML为核心,是.Net数据库应用程序的解决方案。它使用离线数据结构,数据源中的数据被缓存到数据集(DataSet)对象中,用户无须锁定数据源,数据以XML格式保存。 2.2.1ADO.Net管理数据一致性在分布式数据库系统中,很可能出现多个用户同时访问和修改数据的情况,因此,对于分布式数据库系统,数据一致性是不可或缺的。ADO.Net通过使用乐观一致性方案来控制数据一致性(实际上DataSet对象被设计成支持使用乐观一致性控制上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com机制),即数据行只有在数据库中真正被更新时才会被锁定,而在悲观一致性方案中,数据行在从被提取出来到在数据库中更新这段时间内一直被锁定。因此,使用ADO.Net能够在更少的时间内响应数量巨大的用户。另外,在分布式数据库系统中,还会经常遇到当用户修改自从提取出来以来已经被修改的行时,违反一致性原则。对此问题ADO.Net也作了很好地解决,即使用DataSet对象为每一条修改过的记录维护两个版本:原始版本和更新版本,在更新的记录被写回数据库之前,先要把数据集中记录的原始版本与数据库中的当前版本进行比较,如果两个版本匹配,就在数据库中更新记录;否则,就会出现违反一致性原则的错误。3实例开发一个家用电器连锁店设有一个总部和许多分店,总部和分店以及各分店之间经常需要进行各种信息的查询(如:商品当日价目表、各店销售状况和库存信息等),对此组织机构建立分布式数据库查询系统,可实现总部和各店信息的共享,便于统一管理。3.1系统设计 3.1.1系统结构图总部和各分店都配置了一台具有固定IP的服务器,其它电脑通过集线器与服务器相连,总部和各分店的服务器通过通信网络联接起来。 3.1.2系统实现步骤系统实现分为三个主要步骤。首先,为总部和各分店设计数据库。由于数据量较大,故采用SQLServer为每个分店创建销售和库存数据库,同时为总部创建员工数据库、整个连锁店的存货数据库、信用卡客户数据库以及供应商信息数据库等。其次,需要建立一个提供数据库服务(DbServer)的动态链接库(dll),将查询时所要用到的一些服务(如:远程对象的发布和获取等)和函数(如:本地异地数据表的查询、数据表的远程创建和删除、表间的连接和合并等)置入该dll中,各分店都需要使用这个dll,以便查询时对一些服务和函数进行调用。最后,根据实际需要开发客户端查询界面。3.2系统实现的关键技术 3.2.1远程对象的发布与获取系统运行后所要做的第一个工作是发布本地的远程对象并获取其它各店所发布的远程对象。发布远程对象时,首先要设置一个网络端口号,然后创建并注册一个通道,最后发布该服务器端的激活对象。其它场地的服务器根据IP地址和网络端口号即可方便地获取所发布的远程对象。实现远程对象发布和获取的关键代码如下: 远程对象的发布: //创建一个通道实例,port为指定的网络端口号 TcpChannelMyChannel=newTcpChannel(Int32.Parse(port)); //注册通道 ChannelServices.RegisterChannel(MyChannel); //发布该服务器端激活对象 RemotingConfiguration.RegisterWellKnownServiceType(typeof(DbServer),"STORE",上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comWellKnownObjectMode.Singleton); 远程对象的获取: //根据IP地址和端口号获取相应的远程对象 try {myDbServer=(DbServer)Activator.GetObject(typeof(DbServer),"tcp://"+ip+":"+p+"/STORE");} //捕捉异常 catch(NullReferenceExceptionnullExp) {MessageBox.Show("指定的url地址不可到达"+nullExp.Message);} catch(RemotingExceptionremExp) {MessageBox.Show("指定获得的对象定义不对"+remExp.Message);} 3.2.2数据库的访问 通过ADO.Net访问数据库,可以方便地连接数据库,将数据源中的数据导入DataSet对象中,在DataSet对象中可对数据表进行各种操作,而且DataSet对象本身也可远程传递。这为开发分布式数据库系统带来极大方便。实现数据库访问的关键代码如下所示: //建立数据库的连接 stringSqlConn="InitialCatalog=Store;DataSource=Localhost;Userid=sa;Password=;"; SqlConnectionConn=newSqlConnection (SqlConn); Conn.Open();//打开数据库 //将数据源中的数据导入到数据集对象 try{ DataSetds=newDataSet(); DataTabledt=newDataTable("Result"); SqlDataAdapteradapter=newSqlDataAdapter(); SqlCommandmySqlDataSetCmd=newSqlCommand (CmdString,Conn);//CmdString为要执行的命令 adapter.SelectCommand=mySqlDataSetCmd; adapter.Fill(dt); ds.Tables.Add(dt);} finally {Conn.Close();//关闭数据库的连接} 3.2.3查询分布式数据库系统中的查询一般分为三类:本地查询、远程查询和联合查询。本地查询和集中式数据库的查询没什么区别;对于远程查询,只要获取远程对象后,调用查询函数,即可方便地实现;最复杂的是联合查询,涉及到多场地之间数据的查询、表的远程创建、传递、连接、合并等技术。下面以实例介绍联合查询的实现。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com第二连锁店要查询离其较近的第三、第四连锁店中所有北京的供应商所供应的空调的库存信息以便调货,可通过以下步骤实现。首先,获取总部以及第三、第四连锁店所发布的远程对象。接着,通过远程对象在总部创建一临时数据表t1,将查询到的所有北京的供应商信息存放在t1表中(各分店只有供应商名,并不知其所在地,只有总部才有供应商的详细信息),再将t1表保存到第三和第四连锁店。然后让t1表分别与两店的库存表作连接,找出所有北京供应商所供应的空调库存信息(如空调名称、型号、个数、价格等信息),并将连接结果t2和t3数据表返回到第二连锁店。最后对t2和t3两表进行合并,并使用DataGrid控件显示出来。上述实现中,包含了不同场地之间数据表的复制、传递、连接等,所用到的一些函数(如:远程创建数据表、表与表间的远程连接、合并等)都放在dll中,可以方便地调用。 4结束语 利用C#的.NetRemoting技术能够方便地解决各场地间数据的通信问题。另外,C#通过ADO.Net访问数据库,使得对数据库的操作及管理变得更加高效、可靠。这两种技术的使用,有效地解决了开发分布式数据库系统的主要问题,大大减轻了系统开发工作量,并且提高了系统的可靠性和安全性。利用ASP发送和接收XML数据的处理方法因为要做移动梦网WAP的一些接口,所以要用到这种方式,接下来会有ASP.net版本的,这个是ASP版本的,利用了MSXML2.XMLHTTP对像。 request.asp dimHttps setHttps=server.createobject("MSXML2.XMLHTTP") '定义一个XMLHTTP对像 Https.open"POST","http://127.0.0.1/testpost/response.asp",false Https.send"echo 123456 987654 11111 22222 " ifHttps.readystate=4then response.write"提交成功" 'readstate读取状态为4则成功,继续后面的,不成功当然就不用继续处理了 dimobjstream setobjstream=Server.CreateObject("adodb.stream") '定义一个stream,因为读过来的直接拿出来是乱码的,所以得处理一下 objstream.Type=1 objstream.Mode=3 objstream.Open objstream.WriteHttps.responseBody objstream.Position=0 objstream.Type=2上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com objstream.Charset="GB2312" html=objstream.ReadText '转好码,就放到html里,好关闭这些对像 objstream.Close setobjstream=nothing sethttps=nothing endif response.writehtml response.asp '创建DOMDocument对象 Setxml=Server.CreateObject("msxml2.DOMDocument") xml.async=False '装载POST数据 xml.LoadRequest Ifxml.parseError.errorCode<>0Then response.write"不能正确接收数据"&"Description:"&xml.parseError.reason&"<br>Line:"&xml.parseError.Line EndIf setblogchild=xml.getElementsByTagName("misc_command") 'the_text=blogchild.item(0).childnodes(1).text 'the_text=blogchild.item(0).text 'fori=0toblogchild.length-1 response.writethe_text 利用这种方法,ASP里调用Servlet或WebService都是很轻松的!利用ASP+JMAIL进行邮件群发的新思路背景: Email地址存于MSSql一用户信息表中,数量上万。 公司自有服务器,集SMTP,POP3,WWW,FTP,MSSql,DNS等多种服务于一身。 JMAIL有MailMerge对象,但是免费版不能用 要求: 用ASP+JMAIL,利用公司SMTP向所有用户发送EMAIL 思路: 直接读取数据库,多次循环发送,会对本来配置不高的服务器造成很大压力。最好能对EMAIL分批发送,每批发送间隔一段时间,以此来缓解对服务器造成的压力。 实现: 上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com 对EMAIL分批 读出记录到recordset,利用常见的分页程序,将所有记录分页,每页作为一批,有多少页就分多少批 间隔延迟 在每页执行完毕后用来延迟跳转 减少执行时间: 在循环的过程中,循环添加收件人,而不要循环发送,即 fori=1tors.pagesize msg.AddRecipientrs("Email") rs.movenext next msg.Send("smtp.abc.com") 减小邮件大小 循环添加收件人,会造成一封Email的收件人很多,这样一封Email的就会很大。 所以,在以上代码的基础上改进一下,在循环内做个判断,当收件人Email数量到达 20的时候就发送一次。即: fori=1tors.pagesize msg.AddRecipientrs("Email") ifimod20=0then ’每20个收信人作为一封Email发送一次 msg.Send("smtp.abc.com") msg.ClearRecipients ’清除已发送的收信人 endif rs.movenext next msg.Send("smtp.abc.com") ’发送余下的 页面 Mail.asp 包含邮件主题、正文的表单,;一个iframe页面, SendMail.asp 包含后台发送程序,循环,延迟跳转等。 缺点: 发送过程中不能离开该页面 发送的时间较长,与设置的每批发送数量、网络带宽、SMTP服务器性能有关 改进: 可以在Mail.asp中包含多个iframe页面,每个页面从不同的page开始发,相当于多线程发送,对smtp服务器压力会增大,但能缩短发送时间.可考虑在不同的page中采用不同的smtp服务器,例如包含多个iframe页面,在偶数页用smtp.abc.com,在奇数页用smtp.123.com。这样既减轻服务器压力,也达到多线程发送缩短发送时间的目的。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com快速排序算法:Python研究Python中,写一个快速排序练练手: ''' qsort.py Quicksort CreatedonJun18,2009 @author:Liao ''' fromrandomimportRandom defquick_sort(arr): iflen(arr)>1: qsort(arr,0,len(arr)-1) defqsort(arr,start,end): base=arr[start] pl=start pr=end whilepl=base: pr-=1 ifpl==pr: break else: arr[pl],arr[pr]=arr[pr],arr[pl] whileplstart: qsort(arr,start,pl-1) ifpr+1""Then 后面的回车去掉(这个地方微软写错了) 2.5)配置iis,设置“自定义错误页面”,将500;100的类型设为URL,同时URL设为/500-100.asp 2.6)将500-100.asp另存为utf-8编码将个性化进行到底VB中打造个性进度条VB的第三方控件ccrpProgressBar是一个进度条的控件,可以有多种形态供选择。比起VB中自带的进度条控件ProgressBar更有个性。使用实例: 用ccrpProgressBar制作各式各样的进度条 在VB中自带了一个进度条控件ProgressBar,但功能简单。我向大家推荐一个VB的第三方进度条控件ccrpProgressBar。该控件功能强大,有多种形态供选择,而且只需要简单的设置控件的属性就能实现,非常的好用。下面通过一个例子向大家介绍该控件的用法。 (1)加载控件 启动VisualBasic6.0,创建一个工程并保存为"工程1.vbp",同时产生一个名为"Form1"的窗口。在工具箱的空白处单击鼠标右键,从弹出的快捷菜单中启动"部件"窗口,如图1所示。 点击"浏览"按钮,从存放ccrpProgressBar控件的文件夹中找到ccrpprg.ocx文件。 点击"应用"后ccrpProgressBar控件就添加到工具箱中。如图2。 (2)设计窗体和控件 向窗体中添加9个ccrpProgressBar控件和一个Timer控件。如图3。 Timer控件属性页的设置如图4所示。Interval的值设置为100,与ccrpProgressBar控件的默认值一致。Enabled设置为False。 (3)ccrpProgressBar控件的主要属性 ·Max:最大值。默认100。 ·Min:最小值。默认0。 ·Value:进度条的当前值。 ·Alignment:显示表示进度的文字的位置。分别为vbCenter(中间),vbLeftJustify(左边),vbRightJustify(右边)。 ·Appearance:进度条的3种外观。分别为prgFlat(平面),prg3D(立体)上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comprg3Draised(立体凸起)。 ·BackColor:进度条的背景色。 ·FillColor:进度条的颜色。 ·ForeColor:表示进度文字的字体颜色。 ·Picture:进度条可用图片表示进度,从这里选择需要的图片。 ·Shape:进度条的形状。有prgRectangle(默认),prgEllipse和prgRoundedRect三种。 ·Smooth:是否平滑显示进度。True为平滑显示进度。 ·Vertical:是否垂直显示进度条。True为垂直显示。 ·Style:进度条的风格。当选ChkGraphical时为用图片表示进度。 ·AutoCaption:表示进度的"文字提示"所采用的表现形式。CcrpPercentage为百分比的形式,ccrpValueOfMax为类似1of100的表现形式。Value为数字的表现形式。 (4)本例中ccrpProgressBar控件属性的具体设置 本例中共使用了9个ccrpProgressBar控件,每个ccrpProgressBar控件的具体设置如下: 1.CcrpProgressBar1:保持属性各项不变。 2.CcrpProgressBar2:Appearance的值设置为prg3D(表示用立体外观)。 3.CcrpProgressBar3:Appearance的值设置为prg3Draised(立体凸起),AutoCaption设为ccrpPercentage(百分比的形式表示进度),Alignment设为vbLeftJustify(表示进度的文字靠左)。 4.CcrpProgressBar4:BorderStyle设置为ccrpFixedSingle,AutoCaption设为ccrpPercentage(百分比的形式表示进度),Alignment设置为vbCenter(表示进度的文字在中间) 5.CcrpProgressBar5:Style设置为chkGraphical(用图片来表示进度)。单击"Picture"属性,选择你准备好的图片。同样,AutoCaption也设为百分比的形式表示进度,不过这次Alignment的值设置为vbRightJustify(进度文字靠右)。6.CcrpProgressBar6:Shape设置为prgEllipse(椭圆型),AutoCaption设为ccrpValueOfMax(文字以类似1of100的表现形式) 7.CcrpProgressBar7:Shape设置为prgRoundedRect(圆角矩形),AutoCaption设为ccrpValue(数字形式)。 8.CcrpProgressBar8:Vertical设置为True,表示垂直显示进度条。Smooth设置为True,表示平滑显示进度。 9.CcrpProgressBar9:Vertical属性同8的设置,不过这回给它加上百分比显示,AutoCaption设为ccrpPercentage。 上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com然后再分别调整好9个CcrpProgressBar控件的FillColor和ForeColor属性,搭配好颜色。使界面更协调。 (5)编写代码 设置好控件的属性后,在程序中加入以下代码,完成进度条的功能。DimiAsIntegerPrivateSubForm_Load() Timer1.Enabled=True '2个垂直显示的进度条的位置 WithccrpProgressBar8 .Left=5280 .Top=360 .Height=3800 .Width=396 EndWith WithccrpProgressBar9 .Left=6200 .Top=360 .Height=3800 .Width=396 EndWithEndSubPrivateSubTimer1_Timer() Ifi=100Then End EndIf ccrpProgressBar1.Value=i ccrpProgressBar2.Value=i ccrpProgressBar3.Value=i ccrpProgressBar4.Value=i ccrpProgressBar5.Value=i ccrpProgressBar6.Value=i ccrpProgressBar7.Value=i ccrpProgressBar8.Value=i ccrpProgressBar9.Value=i i=i+1'变量i自增EndSub 运行程序,运行中的效果如图5所示。将SSH与PHP相连接确保传输数据的安全上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comSSH可以通过将联机的封包加密的技术进行资料的传递;使用SSH可以把传输的所有数据进行加密,即使有人截获到数据也无法得到有用的信息。同时数据经过压缩,大大地加快了传输的速度。总之,通过SSH的使用,可以确保资料传输比较安全并且传输效率较高。不过,并非所有人知道PHP可以与SSH连接的特性以及与执行远程命令的能力,不过这方面却非常有用。由于我们可以在很多不同的方面利用PHP,因此它有很多设置选项来控制其行为。一组庞大的可选参数能够保证您可以将PHP用于许多不同的目的,但这同时也意味着这些参数和服务端配置的组合会带来一些安全问题。笔者一直在PHPCLI应用程序中使用SSH,笔者是从cronjobs中使用它的,不过一开始并非十分简单,可以说颇费周折。关于安全使用Shell2函数的手册也不是十分实用,笔者进行了多次试验之后才有了今天这篇小文章,愿您读了之后能为您配置PHP节省一点儿时间。 在这篇文章中,笔者需要假设: 你正在运行的操作系统是Debian/Ubuntu。如果你运行的不是Debian/Ubuntu,你可能需要用你的Linux发行版本提供的数据包管理器来替换本文对应内容。 你运行的是PHP5.如果你运行的不是PHP5,可用PHP4代替之。 你对PHP和服务器管理有基本的了解。 你已经安装了PHP。 先决条件 安装程序包 首先,让我们安装下面的程序包: sudoaptitudeupdate sudoaptitudeinstallphp5-devphp5-cliphp-pearbuid-essential\ openssl-devzlib1g-dev 安装完成进入下一步。 编译libssh2 在从sourceforge网站下载了Libssh2之后,我们需要编译它,不过不要担心,你只需要按照如下的方法操作: cd/usr/src wgethttp://surfnet.dl.sourceforge.net/sourceforge/libssh2/libssh2-0.14.tar.gz tar-zxvflibssh2-0.14.tar.gz cdlibssh2-0.14/ ./configure makeallinstall 如果你想检查是否有了一个新版本,可以查看SF.NET.不过,0.14这个版本就足够了。 安装 安装ssh2.so 下一步,我们需要将libssh和PHPr链接起来。有一个PECL模块可以完成这个功能。我们可以使用PEAR安装它。 pearinstall-fssh2 -f参数确保SSH2被安装,即使并没有一个稳定的选择对象。你还可以使用如下的包名称:ssh2-beta来强行运行。 现在你需要确保我们这个新的SSH2.SO模块被PHP加载。编辑你的php.ini文件(对于CLI实用程序:/etc/php5/cli/php.ini,对于Apache实用程序:/etc/php5/apache2/php.ini)上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com extension=ssh2.so 这应该放在“DynamicExtensions”的下面,大约在第515行左右。 PHP支持SSH编写代码 你刚刚在PHP中启用了SSH2。那么现在应该如何利用它呢?有两个选择。SSH支持: 1.执行方法: 这告诉你的服务器的操作系统来执行什么东西,并且通过管道传回到你的脚本。 2.外壳方法:这种方法在操作系统中打开一个实际的外壳,这正像通过终端应用程序登录时所操作的那样。有一些路由器并没有一个完全的POSIX一致性实施过程,而是在你登录时立即运行其自身的应用程序。这时你就需要这种方法。 下面我们分别详述之: 第一种方法:执行 你最好为下面的代码创建函数或者是一个类,不过本文仅仅起到一个为您提供基本观念的作用,所以说你可以如此开始: if(!function_exists("ssh2_connect"))die("functionssh2_connectdoesn'texist") //loginatserver1.example.comonport22 if(!($con=ssh2_connect("server1.example.com",22))){ echo"fail:unabletoestablishconnection\n"; }else{ //trytoauthenticatewithusernameroot,passwordsecretpassword if(!ssh2_auth_password($con,"root","secretpassword")){ echo"fail:unabletoauthenticate\n"; }else{ //allright,we'rein! echo"okay:loggedin...\n"; //executeacommand if(!($stream=ssh2_exec($con,"ls-al"))){ echo"fail:unabletoexecutecommand\n"; }else{ //collectreturningdatafromcommand stream_set_blocking($stream,true); $data=""; while($buf=fread($stream,4096)){ $data.=$buf; } fclose($stream); } }上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com第二种方法:外壳 同样道理,你也可以为如下的代码编写函数或者一个类。不过,本文仅仅提供基本观念: if(!function_exists("ssh2_connect"))die("functionssh2_connectdoesn'texist") //loginatserver1.example.comonport22 if(!($con=ssh2_connect("server1.example.com",22))){ echo"fail:unabletoestablishconnection\n"; }else{ //trytoauthenticatewithusernameroot,passwordsecretpassword if(!ssh2_auth_password($con,"root","secretpassword")){ echo"fail:unabletoauthenticate\n"; }else{ //allright,we'rein! echo"okay:loggedin...\n"; //createashell if(!($shell=ssh2_shell($con,'vt102',null,80,40,SSH2_TERM_UNIT_CHARS))){ echo"fail:unabletoestablishshell\n"; }else{ stream_set_blocking($shell,true); //sendacommand fwrite($shell,"ls-al\n"); sleep(1); //&collectreturningdata $data=""; while($buf=fread($shell,,4096)){ $data.=$buf; } fclose($shell); } } } 小提示:有时服务器忙碌,或者一个连接出错,缓冲区没有数据,PHP脚本就会停止从一个命令输出(即使命令并没有完成!)中收集数据。你可以为此进行如下的操作: ssh2_exec($con,'ls-al;echo"__COMMAND_FINISHED__"'); 现在,在你不断地检查缓冲区的循环中,只需要看一下COMMAND_FINISHED。因为你就可以知道你拥有了所有的数据。为了避免无限循环(死循环),可以用一个10秒的超时限制: $time_start=time(); $data=""; while(true){ $data.=fread($stream,4096);上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com if(strpos($data,"__COMMAND_FINISHED__")!==false){ echo"okay:commandfinished\n"; break; } if((time()-$time_start)>10){ echo"fail:timeoutof10secondshasbeenreached\n"; break; } } 在上面的例子中,你最好将stream_set_blocking设为false。 通过SSH发送文件 ssh2_scp_send($con,"/tmp/source.dat","/tmp/dest.dat",0644); 如果不能正常工作 请检查如下的几个方面: 依照本文检查你操作的每一步 在服务器端,在sshd_config中必须启用“PasswordAuthenticationyes”。在大多数服务器上默认值是yes,不过有些情况下,你可能需要将下面的一行加入到文件中,即亲自动手打开这个功能: /etc/ssh/sshd_config: #Changetoyestoenabletunnelledcleartextpasswords PasswordAuthenticationyes 如果作了改变,就需要重新启动SSH: /etc/init.d/sshrestart将Java应用注册为后台服务上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com项目中有一个java应用程序,交付后用户要求要把这个程序做成后台服务程序,即:系统启动后该程序可以自动启动,并且在前台不要出现运行窗口,维护人员只要在“服务管理”(Windows)中选择启动或停止即可.解决办法如下:Linux在Linux中注册后台服务程序相对容易,只需编辑/etc/init.d/boot.local文件,在boot.local文件里加上下面这句脚本:/iapappserver/MessageServer2.1/run.sh其中run.sh是java应用的运行脚本Windows在Windows下的情况较为复杂,需要使用Windows提供的两个工具:instsrv.exe(下载)和Srvany.exe(下载).instsrv: 这个工具是把win32程序变成系统服务。基本用法: instsrv [服务名] [应用程序绝对路径] (增加服务)instsrv [服务名] REMOVE (删除服务)但是并不是所有程序都适合做系统服务的,注册成系统服务后就是无法启动的,这时就需要用到srvany.srvany: 这个工具就是用来解决上面的工具中的问题,你注册的时候把它当作你要的服务,在用它来启动你的应用程序。基本用法: instsrv [服务名] [srvany的绝对路径]具体步骤如下:1.注册服务: path\instsrv 服务名 path\srvany.exe2.regedit打开注册表3.进入HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\服务名4.右键-新建-项 填入 Parameters5.打开Parameters,右键-新建-字符串值 Application6.双击Application 填入 应用程序的绝对路径,如: D:\workspace\app\main.exe7.右键-新建-字符串值AppDirectory 8.双击AppDirectory 填入 应用程序的工作目录,如: D:\workspace\app\9.启动服务。在Parameters里还可以添加很多键值: AppDirectory 工作目录 AppParameters 你的应用程序的参数。 AppEnvironment 运行环境变量。建一个XMLHttpRequest对象池 在ajax应用中,通常一个页面要同时发送多个请求,如果只有一个XMLHttpRequest对象,前面的请求还未完成,后面的就会把前面的覆盖掉,如果每次都创建一个新的XMLHttpRequest对象,也会造成浪费。解决的办法就是创建一个XMLHttpRequset的对象池,如果池里有空闲的对象,则使用此对象,否则将创建一个新的对象。 下面是我最近写的一个简单的类:/** * XMLHttpRequest Object Pool *上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com * @author legend * @link http://www.ugia.cn/?p=85 * @Copyright www.ugia.cn */ var XMLHttp = { _objPool: [], _getInstance: function () { for (var i = 0; i < this._objPool.length; i ++) { if (this._objPool[i].readyState == 0 || this._objPool[i].readyState == 4) { return this._objPool[i]; } } // IE5中不支持push方法 this._objPool[this._objPool.length] = this._createObj(); return this._objPool[this._objPool.length - 1]; }, _createObj: function () { if (window.XMLHttpRequest) { var objXMLHttp = new XMLHttpRequest(); } else { var MSXML = [’MSXML2.XMLHTTP.5.0’, ’MSXML2.XMLHTTP.4.0’, ’MSXML2.XMLHTTP.3.0’, ’MSXML2.XMLHTTP’, ’Microsoft.XMLHTTP’]; for(var n = 0; n < MSXML.length; n ++) { try { var objXMLHttp = new ActiveXObject(MSXML[n]); break; } catch(e)上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com { } } } // mozilla某些版本没有readyState属性 if (objXMLHttp.readyState == null) { objXMLHttp.readyState = 0; objXMLHttp.addEventListener("load", function () { objXMLHttp.readyState = 4; if (typeof objXMLHttp.onreadystatechange == "function") { objXMLHttp.onreadystatechange(); } }, false); } return objXMLHttp; }, // 发送请求(方法[post,get], 地址, 数据, 回调函数) sendReq: function (method, url, data, callback) { var objXMLHttp = this._getInstance(); with(objXMLHttp) { try { // 加随机数防止缓存 if (url.indexOf("?") > 0) { url += "&randnum=" + Math.random(); } else { url += "?randnum=" + Math.random(); } open(method, url, true);上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com // 设定请求编码方式 setRequestHeader(’Content-Type’, ’application/x-www-form-urlencoded; charset=UTF-8’); send(data); onreadystatechange = function () { if (objXMLHttp.readyState == 4 && (objXMLHttp.status == 200 || objXMLHttp.status == 304)) { callback(objXMLHttp); } } } catch(e) { alert(e); } } }}; 示例: 建立数据仓库:入门的八个诀窍 当使用SQL上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comServer技术建立一个数据仓库时,你可能会面临一些挑战。我将给你一些建议来克服它们。当然,每个环境可能会给建立数据仓库所面临的挑战增添自己的难度,但是这些建议大多数都是通用的,足以应用于许多公司着手构建商业智能(BI)应用。 1.管理部门的支持。这是你必须要克服的第一个,也是最重要的挑战。它困扰着技术人员(当然包括你),因为它涉及政治而不是软件。但是让我们记住是谁签发你的薪水。如果管理部门不相信他们需要一个数据仓库,那你的所有技能都是无用的。 不幸的是上层管理人员至今仍经常认为数据仓库是另一个系统,他们需要投资却不能立即获得回报。你的工作就是使他们确信他们不会是在购买一些无用的东西——数据仓库会通过使企业中分散的数据关联起来,从而帮助他们做出更好、更明智的决定。在采用了数据仓库之后组织运行方式完全改变是并不罕见的。有时它会帮助建立一个概念证明模型(POC)项目来证明商业智能的力量。POC数据仓库将只包含所有数据的一小部分,并将只显示给一小部分人,以便测试。即使你并没有获准采用POC,你也应该证明数据仓库的某些部分将有益于你的用户,这么做使他们有兴趣并确信这个系统将帮助他们使他们的工作更有效。 2.数据可用性。数据仓库将不一定明显或不一定容易获得的多个数据源的数据结合起来。根据公司的规模不同,你可能需要到多个办公室和许多雇员谈话来弄清楚你可以从哪获得那些用于生成你的用户想要的分析视图的必要的数据。再次,根据你的公司的政治氛围的不同,你可能发现要获得所有的必要数据元素很困难。因为你用的数据可能包含机密和高敏感性的细节。此外,一些数据可能只能通过一个外部实体所提供的报告访问,而他不会给你他们的数据源的访问权限。 你怎么克服这个挑战?首先,一定要说服每个人你不会取代他们的工作。数据仓库是用来补充的而不是取代任何已存在的系统。如果有管理层站在你这边,你就不会有太多内部员工的问题。但是如果你不能访问数据源——因为不可预见的原因——那么你可能就需要用创造性来解决这一问题了。如果数据只能通过报告屏幕或纸上来获得,那么你可能需要找到个方法来捕获这个数据,可能通过抓取报告屏幕或扫描文档。 3.数据源的复杂性。有时你很幸运,你需要的所有的数据元素都在你选择的数据库管理系统(DBMS)中。更多时候,数据是分散在多个数据库管理系统中的,电子表格、电子邮件系统、电子文档,甚至纸张上。是的,我们是在21世纪,但是记住我的话——还是有一些其它的公司是把某些数据只保存在纸上的。这是你的工作,找出怎样从分散的数据源获得数据并转化为共同的形式,然后录入到你的数据仓库中去的方法。 4.数据质量。许多交易处理应用通常是由对其使用的工具具有有限的知识或经验的人利用快速发展的技术放到一起的。这并没有贬低的意思;一个人必然要从某一处开始,而初级程序员是公司可以使用的最实惠的资源。麻烦的是如果这个应用没有验证数据那你很可能发现字符串类型的数据是缩写的、拼错了或完全遗漏了。对于交易级别的报告,这可能不是什么大问题,但是当你试图给数据分组并提供给你的用户作做决定的能力时,数据质量就是至关重要的了。 例如,看一下下面的用户姓名: a.ACMEBootOutlet b.ACMEbt上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comoutlt c.A.C.M.E d.Boots(ACME) e.Acmebootstore(outlet) 人眼可以很容易的辨识出上面的每一个都是指同一个事务实体。但是对于计算机程序来说,每一个值代表一个不同的用户。不幸的是利用集成服务(或者数据转移服务)包没有容易的方法来校正所有的不好的数据。SQLServer2005集成服务提供了模糊查询转化,它可以大大简化你的数据清理工作。但即使如此,你可能还是需要文职人员帮忙修正数据。 5.你的用户数目和技术领悟力。帮助一些用户获得他们所需的数据以便作出决策并不是一件容易的事。过去,数据仓库是给高层管理人员使用的。但是慢慢的,数据仓库转向了大多数人群。看到不一定做决策的用户使用数据仓库和商业智能应用是很平常的。 一旦你的用户看到了数据仓库的强大力量,他们将会想从数据访问到获取交易级报告等任何事情都使用数据仓库。你的用户群越大,保证每个人都满意并培训他们恰当使用你的应用程序就越困难。如果使用恰当,商业智能应用可以发挥很大的作用,但它并不是适合所有的商业需求。你经常得传送不好的消息,那就是数据仓库并不是满足你的用户期望的功能的可选工具。 6.维度慢慢改变。你的应用必须反映出移植到仓库中的数据源所发生的数据变化。维表中的数据特别容易变化。但你怎么维护记录的历史变化呢? 第一个也是最简单的方法是重写现有的记录而不跟踪变动。幸运的是,这个方法被许多维度所接受。例如,如果一个部门名称从“财务”变为“财务和会计”,你很可能并不需要记录这种历史变化。但是,从客户和学生的角度看,常常有必要保持跟踪姓名、婚姻状态、教育程度和其它属性的变化——你的应用必要能够获得当前的以及历史的数值。 管理维度慢慢改变的第二个方法是数值发生变化时创建一个新的记录,并将旧的记录标记为旧记录。 第三个也是最后的一个方法是维护在维表的同一行中不同列的变化域的历史数值。 到此,我们已经介绍了如何处理数据仓库维度中的值的变化。但是分析服务维度怎么处理呢?要反映属性值的变化你必须重新处理维度。但是如果你完全处理维度,你就不得不也重新处理多维数据集,如果你的多维数据集包含大量数据,那这就可能不太现实了。幸运的是你可以经常使用渐进式更新(过程更新)选项来避免重新处理多维数据集。 7.事实变化。通常人们认为事实表中的记录是静态的——一旦这条记录录入到了仓库中你的工作就结束了,是吗?不幸的是这个回答是“它取决于。”在某些情况下像在一个数据仓库跟踪病人的住院情况,所有的记录通常都是静态的。如果你从1月1日到2月5日住院,那这条记录不太可能改变。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com 但是考虑到零售行业,所有的销售都不是最终的——我肯定你知道有些人经常将它们购买的货物因为各种原因而退回商店。一些公司管理这种交易为一系列信用和负债来结算每笔交易。但在其它的情况下你必须更新或删除事实表记录,甚至在它们添加到了数据仓库之后。例如,如果一个股票交易记录不正确,用一个相反的交易来结算是不能接受的。还有另一个问题要考虑:你可能不希望你的客户知道你的交易系统中存在的问题。甚至你希望他们只在数据被修正后才看到数据。 处理事实变化的一个方法是将数据放在暂存区域直到它经过了质量检查,然后将其移植到仓库中。然而有时甚至是最全面的测试也无法捕获数据源中的所有错误,你可能需要通过处理这些包含错误数据的部分来更新多维数据集。这就是为什么有必要保持你的分析服务部分尽可能的小以便处理可以相对快一些。 另一个处理这个挑战的方法是采用一个回写分区。采用多维数据集回写,你没有真的改变关系数据仓库中的数据;而是在一个单独的分区中添加了一条记录。当用户查询一个特殊的测量值组时,分析服务将只读分区的数据和回写分区的数据结合起来,然后显示结果。当然,执行这样的查询计算会额外增加分析服务器的执行时间,并会造成性能下降。 8.实现安全。就像任何其它的商业应用一样,必须保护对你的数据仓库和多维数据集的访问。每个用户可能只被允许看到数据仓库的一小部分,这取决于他们的工作职务或责任范围。分析服务通过可以与分析服务角色相关联的Windows帐户来保证安全。你可以以非常小的粒度级以单个多维数据集单元为单位来实行数据保护。 不幸的是为每一个用户创建一个单独的角色不仅麻烦而且还会引起性能问题——尤其对于分析服务2005之前的版本。建议如果可能的话你把你的用户分为较少的几种角色。如果每一个单独的用户需要有她自己的权限设置,那么你需要实现一个安全维度。一旦你有了这样的安全维度,每一个MDX查询都将根据目前的用户身份进行输出过滤。 当然我无法在一篇文章里介绍所有的数据仓库问题。也没有任何人可以说他熟悉建立数据仓库解决方案所遇到的每一个问题。但是,如果你打算尝试实现这样的解决方案,你应该谨慎的考虑你将要面临的是什么。做好准备工作,准备迎接挑战。简单快捷实现ASP在线发邮件功能在编写网上应用程序时,经常碰到需要在线发送邮件的问题,邮件内容是由程序动态决定的,如果你采用的是ASP方式来编写网上应用程序,如何简单、快捷地实现这一功能呢?笔者在实践中利用ASP的com组件功能,在vb中实现了一个发邮件的小组件,在ASP中只通过轻松调用,就可以实现该功能。所有邮件处理机制都被封装在这个组件中,使用起来极为方便。下面将详细介绍该组件的基本开发原理以及在ASP中的应用。 1.利用Winsock控件与发送邮件的smtp联系 和smtp的联系包括握手、发送数据以及关闭等全过程,主要程序如下: 建立一个frmsendmail的窗体,其中包含一个winsock控件,有以下几个公共变量: publicmstmpasstring //发送邮件的stmp上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com publicmfromasstring //from地址 publicmtoasstring //到达地址 publicmsubjectasstring //邮件主题 publicmtextasstring //邮件正文 sock.connectmstmp,25 //和发送邮件的stmp建立联系 privatesubsock_connect() sflag=sfconn //连接成功后设置参数 endsub privatesubsock_dataarrival(byvalbytestotalaslong) onerrorgotodaerr dimsasstring sock.getdatas selectcasesflag casesfstart casesfconn sflag=sfhelo //发出握手信息hello send"helo"&&mmyname casesfhelo sflag=sffrom send"mailfrom:"&&getreal(mfrom) casesffrom ifleft(s,3)〈〉"250"thengotosrverr //如果成功发送接收邮件地址sflag=sfrcpt send"rcptto:"&&getreal(mto) casesfrcpt ifleft(s,3)〈〉"250"thengotosrverr //如果成功开始发送数据 sflag=sfdata send"data" casesfdata ifleft(s,3)〈〉"354"thengotosrverr sflag=sfsendover//数据包括4项,最后以.结束 send"from:"&&mfrom send"to:"&&mto send"subject:"&&msubject&&vbcrlf上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com sendmtext send"." casesfsendover ifleft(s,3)〈〉"250"thengotosrverr sflag=sfstart sendok=true send"quit" endselect exitsubendsub 2.将上述功能封装在一个类中 由于ASP能使用的组件中不能存在控件,所以要通过类模块来封装上述窗体。首先在类初始化时建立一窗体: privatesubclass_initialize() setfrm=newfrmsendmail endsub 把窗体的公共变量作为属性封装在类模块中。 该窗体的函数接口为: publicsubsend() frm.sendstart endsub 3.注册该组件 将上述工程编译成dll文件,通过vb注册或手工注册都可以。 4.在ASP中的应用 调用方法如下: setsmail=server.createobject("sendmailx.mail") smail.stmp="166.166.1.1" smail.logfile="e:\logs\mail.log" smail.mfrom=mfromname&&"〈"&&mfromaddr&&"〉" smail.mto=mtoname&&"〈"&&mtoaddr&&"〉" smail.msubject=msubject smail.mtext=mtext smail.send 其中变量可以通过赋值,也可以来自上一个request页面。缓冲技术提高JSP程序的性能和稳定性一、概述上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com在Web应用中,有些报表的生成可能需要数据库花很长时间才能计算出来;有的网站提供天气信息,它需要访问远程服务器进行SOAP调用才能得到温度信息。所有这一切都属于复杂信息的例子。在Web页面中加入过多的复杂信息可能导致Web服务器、数据库服务器负荷过重。JSP代码块缓冲为开发者带来了随意地增加各种复杂信息的自由。JSP能够在标记库内封装和运行复杂的Java代码,它使得JSP页面文件更容易维护,使得非专业开发人员使用JSP页面文件更加方便。现在已经有许多标记库,它们或者是商业产品,或者是源代码开放产品。但这些产品中的大多数都只是用标记库的形式实现原本可以用一个简单的JavaScriptlet实现的功能,很少有产品以某种创造性的方式使用定制标记,提供在出现JSP定制标记库之前几乎不可能实现的用法。OSCache标记库由OpenSymphony设计,它是一种开创性的JSP定制标记应用,提供了在现有JSP页面之内实现快速内存缓冲的功能。虽然已经有一些供应商在提供各种形式的缓存产品,但是,它们都属于面向特定供应商的产品。OSCache能够在任何JSP1.1兼容的服务器上运行,它不仅能够为所有用户缓冲现有JSP代码块,而且能够以用户为单位进行缓冲。OSCache还包含一些提高可伸缩性的高级特性,比如:缓冲到磁盘,可编程的缓冲刷新,异常控制,等等。另外,正如OpenSymphony的其他产品,OSCache的代码也在一个开放源代码许可协议之下免费发行。本文以一个假想的拍卖网站设计过程为例,介绍OSCache的工作过程。这个假想的Web网站将包含:一个报告最近拍卖活动的管理页面;一个功能完整、带有各种宣传信息的主页;一个特殊的导航条,它包含了用户所有尚未成交的拍卖活动信息。 二、管理页面拍卖网站包含一个管理报表,数据库服务器需要数秒时间才能创建这样一个报表。报表生成时间长这一点很重要,因为我们可能让多个管理员监视系统运行情况,同时又想避免管理员每次访问时都重新生成这个报表。为了实现这一点,我们将把整个页面封装到一个应用级的缓冲标记之内,这个缓冲标记每隔1小时刷新。其他供应商提供的一些产品也具有类似的功能,只是OSCache比它们做得更好。为简单计,我们将不过多地关注格式问题。在编写管理页面时,我们首先把标记库声明加入到页面:<%@tagliburi="cachetags"prefix="cache"%> 接下来我们要用cache标记来包围整个页面。cache标记的默认缓冲时间是1小时。<cache:cache>....复杂的管理报表....</cache:cache> 现在管理页面已经被缓冲。如果管理员在页面生成后的一个小时之内再次访问同一页面,他看到的将是以前缓存的页面,不需要由数据库服务器再次生成这个报表。 三、主页上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com拍卖网站的主页显示网站活动情况,宣传那些即将结束的拍卖活动。我们希望显示出正在进行的拍卖活动数量,当前登录用户数量,在短期内就要结束的拍卖活动的清单,以及当前时间。这些信息有着不同的时间精确度要求。网站上的拍卖活动通常持续数天,因此我们可以把缓冲有效拍卖活动数量的时间定为6个小时。用户数量的变化显然要频繁一些,但这里我们将把这个数值每次缓冲15分钟。最后,我们希望页面中显示的当前时间总是精确的页面访问时间。 在主页中声明标记库之后,我们首先以不带缓冲的方式直接输出当前日期: 现在是:<%=newjava.util.Date()%> 接下来,我们要显示一个清单,列出那些将在短期内结束的拍卖活动:<cache:cache><ul><%//构造一个包含最近拍卖活动的IteratorIteratorauctions=....while(auctions.hasMore()){Auctionauction=(Auction)auctions.next();%><li><%=auction%></li%<}%></ul></cache:cache>最后,我们希望显示出正在进行的拍卖活动的数量,这个数字需要缓冲6小时。由于cache标记需要的是缓冲数据的秒数,我们把6小时转换成21600秒:<cache:cachetime="21600"><%//查询数据库得到拍卖活动总数intauctionCount=....%>本网站正在进行的拍卖活动有<%=auctionCount%>个!</cache> 可以看到,我们只用少量的代码就构造出了一个带有复杂缓冲系统的主页。这个缓冲系统对页面各个部分分别进行缓冲,而且各个部分的缓冲时间完全符合它们各自的信息变化频繁程度。由于有了缓冲,现在我们可以在主页中放入更多的内容;而在以前没有缓冲的情况下,主页中放入过多的内容会导致页面访问速度变慢,甚至可能给数据库服务器带来过重的负载。 四、导航条假设在规划网站的时候,我们决定在左边导航条的下方显示购物车内容。我们将显示出用户所拍卖的每一种商品的出价次数和当前报价,以及所有那些当前用户出价最高的商品的清单。我们利用会话级的缓冲能力在导航条中构造上述功能。把下面的代码放入模板或者包含文件,以便网站中的其他页面引用这个导航条:<cache:cachekey="navbar"scope="session"time="300"><%//提取并显示当前的出价信息%></cache:cache>在这里我们引入了两个重要的属性,即key和scope。在本文前面的代码中,由于cache标记能够自动为代码块创建唯一的key,所以我们不需要手工设置这个key属性。但在这里,我们想要从网站的其余部分引用这个被缓冲的代码块,因此我们显式定义了该cache标记的key属性。第二,scope属性用来告诉cache标记当前代码块必须以用户为单位缓冲,而不是为所有用户缓冲一次。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com在使用会话级缓冲时应该非常小心,应该清楚:虽然我们可以让复杂的导航条减少5倍或10倍的服务器负载,但它将极大地增加每个会话所需要的内存空间。在CPU能力方面增加可能的并发用户数量无疑很理想,但是,一旦在内存支持能力方面让并发用户数量降低到了CPU的限制之下,这个方案就不再理想。正如本文前面所提到的,我们希望从网站的其余部分引用这个缓冲的代码块。这是因为,当一个用户增加了一个供拍卖的商品、或者出价竞购其他用户拍卖的商品时,我们希望刷新缓冲,使得导航条下一次被读取时具有最新的内容。虽然这些数据可能因为其他用户的活动而改变,但如果用户在网站上执行某个动作之后看到自己的清单仍未改变,他可能会感到非常困惑。OSCache库提供的flush标记能够刷新缓冲内容。我们可以把下面的代码加入到处理用户动作且可能影响这一区域的页面之中:<cache:flushkey="navbar"scope="session"/>当用户下次访问它时,navbar缓冲块将被刷新。至此为止,我们这个示例网站的构造工作已经完成且可以开始运行。下面我们来看看OSCache的异常处理能力。即使缓冲的内容已经作废,比如在缓冲块内出现了Java异常,OSCache标记库仍旧允许我们用编程的方法显示这些内容。有了这种异常控制功能,我们可以拆除数据库服务器和Web服务器之间的连接,而网站仍能够继续运行。JSP1.2规范引入了TryCatchFinally接口,这个接口允许标记本身检测和处理Java异常。因此,标记可以结合这种异常处理代码,使得JSP页面更简单、更富有条理。 OpenSymphony正在计划实现其他的缓冲机制以及一个可管理性更好的主系统,它将使我们能够对缓冲使用的RAM和磁盘空间进行管理。一旦有了这些功能,我们就能够进一步提高网站的响应速度和可靠性。衡量程序员的工作效率与其他领域一样,在软件开发领域中,管理者需要评估程序员的绩效和项目的进度。然而,如何定义恰如其分的评价体系,很令人挠头。 计算代码行数(sourcelinesofcode,SLOC)是最常用的方式之一。不过,最近ShaharYair和SteveMcConnell指出了该方法的一系列重要缺陷。首先,使用代码行数之和无法有效评估一个项目的实际进度,因为它更注重行为而不是结果。最终产品在多大程度上依赖于代码的性能和质量,这也是代码行数无法说明的。因此,聚焦于此实际上是非常有限的工作效率测量方式。 SLOC无法表明要解决的问题的复杂性,也不能以可维护性、灵活性、扩展性等等因素来说明最终产品的质量。说到质量,它反而可能起到负面作用。通过重构、使用设计模式会减少代码行数,同时提升代码质量。代码量大,可能意味着有更多不必要的代码、更高不必要的复杂性、更加僵化难懂。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com 更危险的是,要用这样一种不完整的视角来评价开发人员的绩效,会起到错误的激励作用。开发人员会因此更注重代码的数量,而不顾其对产品质量的损害,也不会从最终产品的角度考虑去优化他们的工作,他们甚至可能有意编写更多冗长无益的代码。“测量什么,就得到什么”,SteveMcConnel回忆。 他指出,有些问题可以通过测量度量功能点数解决掉。那么决定程序大小的因素就变成了输入、输出、查询和文件的数目。不过这种方式也有其缺陷。McConnell提出一些操作性上的问题,比如必须要有一个大家认可的功能点测量机制,而且要想把每个功能点映射到程序员身上也不容易。DanielYokomizo是一位经过认证的功能点专家,他在评论中明确指出了这种方式的其他问题:缺少测量功能点复杂度的工具;还需要考虑诸如代码共享、框架、程序库之类的事情。这些都会影响到完成一个功能的时间。 有很多人参与了对于测量方式的讨论,他们都同意这些做法有其局限,不过他们都觉得衡量开发人员的绩效还是有必要的。实际上,不少人认为SLOC可以作为基础,在其之上通过考虑多种不同因素来进行更复杂的分析。McConnell提出了四条分析开发人员工作效率的必备指导原则,他们也都同意。这四条原则如下: 1、不要指望单一维度的工作效率测量方式能告诉你每个人的真实情况。 2、不要指望任何测量方式可以在很小的粒度上区分出每个人的工作效率差异。这些方式可以为你提出问题,却不会告诉你答案。 3、牢记:趋势总是比单独一点的测量来得重要。 4、问问你自己:为什么要测量个人的工作效率? 测量开发人员的工作效率在什么样的上下文中才是有意义的?有哪些条件?这些条件该如何组合?许多问题仍没有答案。如果你有过类似经验可以分享,请不要犹豫。关于JSP防范SQL注入攻击 SQL注入攻击的总体思路: 发现SQL注入位置; 判断服务器类型和后台数据库类型; 确定可执行情况 对于有些攻击者而言,一般会采取sql注入法。下面我也谈一下自己关于sql注入法的感悟。注入法: 从理论上说,认证网页中会有型如: select*fromadminwhereusername=’XXX’andpassword=’YYY’的语句,若在正式运行此句之前,如果没有进行必要的字符过滤,则很容易实施SQL注入。 如在用户名文本框内输入:abc’or1=1--在密码框内输入:123则SQL语句变成: select*fromadminwhereusername=’abc’or1=1andpassword=’123’上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com不管用户输入任何用户名与密码,此语句永远都能正确执行,用户轻易骗过系统,获取合法身份。 猜解法: 基本思路是:猜解所有数据库名称,猜出库中的每张表名,分析可能是存放用户名与密码的表名,猜出表中的每个字段名,猜出表中的每跫锹寄谌荨?BR> 还有一种方式可以获得你的数据库名和每张表的名。 就是通过在形如:http://www..cn/news?id=10’的方式来通过报错获得你的数据库名和表名! 对于jsp而言我们一般采取一下策略来应对: 1、PreparedStatement 如果你已经是稍有水平开发者,你就应该始终以PreparedStatement代替Statement. 以下是几点原因 1、代码的可读性和可维护性. 2、PreparedStatement尽最大可能提高性能. 3、最重要的一点是极大地提高了安全性. 到目前为止,有一些人(包括本人)连基本的恶义SQL语法都不知道. Stringsql="select*fromtb_namewherename=’"+varname+"’andpasswd=’"+varpasswd+"’"; 如果我们把[’or’1’=’1]作为name传入进来.密码随意,看看会成为什么? select*fromtb_name=’or’1’=’1’andpasswd=’随意’; 因为’1’=’1’肯定成立,所以可以任何通过验证.更有甚者: 把[’;droptabletb_name;]作为varpasswd传入进来,则: select*fromtb_name=’随意’andpasswd=’’;droptabletb_name;有些数据库是不会让你成功的,但也有很多数据库就可以使这些语句得到执行. 而如果你使用预编译语句.你传入的任何内容就不会和原来的语句发生任何匹配的关系.(前提是数据库本身支持预编译,但上前可能没有什么服务端数据库不支持编译了,只有少数的桌面数据库,就是直接文件访问的那些只要全使用预编译语句,你就用不着对传入的数据做任何过虑.而如果使用普通的statement,有可能要对drop,;等做费尽心机的判断和过虑. 2、正则表达式 2.1、检测SQLmeta-characters的正则表达式/(\')|(\’)|(\-\-)|(\#)|(#)/ix 2.2、修正检测SQLmeta-characters的正则表达式/((\=)|(=))[^\n]*((\')|(\’)|(\-\-)|(\;)|(:))/i 2.3、典型的SQL注入攻击的正则表达式/\w*((\')|(\’))((\o)|o|(\O))((\r)|r|(\R))/ix 2.4、检测SQL注入,UNION查询关键字的正则表达式/((\')|(\’))union/ix(\')|(\’)-单引号和它的hex等值union-union关键字。 2.5、检测MSSQLServerSQL注入攻击的正则表达式/exec(\s|\+)+(s|x)p\w+/ix3、字符串过滤 publicstaticStringfilterContent(Stringcontent){ Stringflt="’|and|exec|insert|select|delete|update|count|*|% |chr|mid|master|truncate|char|declare|;|or|-|+|,"; Stringfilter[]=flt.split("|"); for(inti=0;i { content.replace(filter[i],上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com""); } returncontent; } 、不安全字符屏蔽 本部分采用js来屏蔽,起的作用很小,这样用屏蔽关键字的方法虽然有一定作用,但是在实际应用中这些SQL的关键字也可能成为真正的查询关键字,到那是被你屏蔽了那用户不是不能正常的使用了。只要在代码规范上下点功夫就可以了。 凡涉及到执行的SQL中有变量时,用JDBC(或者其他数据持久层)提供的如:PreparedStatement就可以,切记不要用拼接字符串的方法就可以了. 功能介绍:检查是否含有"’","\\","/" 参数说明:要检查的字符串 返回值:0:是1:不是 函数名是 functioncheck(a) { return1; fibdn=newArray("’","\\","/"); i=fibdn.length; j=a.length; for(ii=0;ii=li_WS_Width orli_my_Height+li_800bc>=li_WS_Height then w_1.WindowState=maximized! else w_1.WindowState=normal! /*居中*/ w_1.X=(li_WS_Width- li_my_Width)/2 w_1.Y=(li_WS_Height-li_my_Height)/2 endif caseelse /*1024×768...*/ ifli_my_Width+li_1024bc>=li_WS_Widthor li_my_Height+li_1024bc>=li_WS_Heightthen w_1.WindowState=maximized! else w_1.WindowState=normal! /*居中*/ w_1.X=(li_WS_Width- li_my_Width)/2 w_1.Y=(li_WS_Height-li_my_Height)/2 endifendchoose改进的ASP备份SQLServer数据库 选择操作:备份 恢复
数据库名:">
文件路径:(备份或恢复的文件路径)
<% 'SQLServer数据库的备份与恢复! ifrequest("action")="backupdatabase"Then dimsqlserver,sqlname,sqlpassword,sqlLoginTimeout,databasename,bak_file,act sqlserver="localhost" sqlname="sa" sqlpassword上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com="password" sqlLoginTimeout=15 databasename=trim(request("databasename")) bak_file=trim(request("bak_file")) bak_file=replace(bak_file,"$1",databasename) act=lcase(request("act")) ifdatabasename=""then response.write"inputdatabasename" else ifact="backup"then Setsrv=Server.CreateObject("SQLDMO.SQLServer") srv.LoginTimeout=sqlLoginTimeout srv.Connectsqlserver,sqlname,sqlpassword Setbak=Server.CreateObject("SQLDMO.Backup") bak.Database=databasename bak.Devices=Files bak.Action=0 bak.Initialize=1 'bak.Replace=True bak.Files=bak_file bak.SQLBackupsrv iferr.number>0then response.writeerr.number&"
" response.writeerr.description&"" endif Response.write"备份成功!" elseifact="restore"then '恢复时要在没有使用数据库时进行! Setsrv=Server.CreateObject("SQLDMO.SQLServer") srv.LoginTimeout=sqlLoginTimeout srv.Connectsqlserver,sqlname,sqlpassword Setrest=Server.CreateObject("SQLDMO.Restore") rest.Action=0'fulldbrestore rest.Database=databasename rest.Devices=Files rest.Files=bak_file rest.ReplaceDatabase=True'Forcerestoreoverexistingdatabase iferr.number>0then response.writeerr.number&"
" response.writeerr.description&"" endif rest.SQLRestoresrv Response.write"恢复成功!" else Response.write"没有选择操作" endif endif endif %>辅导:Java中的表达式 表达式 由运算符和变量、常数或常量组成的式子称为表达式。例如2+3,a*b等。表达式是组成程序的基本单位,也是程序运算时的基本单位。 在程序代码内部,每个表达式都有自己对应的数据类型,具体参看下表:序号运算符结果类型1算术运算符数字型位运算符移位运算符递增、递减运算符2比较运算符布尔型逻辑运算符3赋值运算符和变量类型一致4条件运算符和两个值中类型高的一致表达式结果类型 提示:对于序号1和2的运算符组成的表达式,由于比较直观,就不再单独举例了,对于3和4说明如下: intn=10; intm=10; n=(m=10);//则表达式m=10的类型是变量m的类型,也是m的值 booleanb=false; booleanb1=true; b=(b1=true);//则表达式b1=true的类型是布尔型,值是true doubled; d=10>0?1.0:2;//由于1.0是double型,2是整数型,则表达式的类型是double 对于由多个运算符组成的表达式,其最终的类型由最后一个运算符决定。 在实际的程序代码中,大部分的表达式不能单独成为代码中的一行,否则程序会提示语法错误,例如: inta=10; intb=上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com20; a+b;//不能单独成行 在表达式中,能够单独成行的运算符包括赋值运算符和递增、递减运算符。 总结 本部分系统的讲解了Java语言中运算符的知识,并且介绍了实际使用过程中需要注意的问题,在学习时需要熟记每种运算符的作用,然后在实际项目中根据需要使用对应的运算符来实现程序的功能。调用软键盘的解决方法 输入: 使用软键盘 得到一个字符串中的最大长度的数字**//// ///获取字符串最长的数字 /// ///输入字符串 ///最长数字 publicstringGetMaxLenNumber(stringinputStr) { //将字符串中的字符存放到数组中,便于处理 char[]strCharArray=inputStr.ToCharArray(); //开始处理的位置 intstartPos=0; //当前处理的字符长度 inttempCharCount=0; //数字的最长长度 intmaxLen=0; //数组的总长度 intlen=strCharArray.Length; intpos=0; while(startPosmaxLen) { maxLen=tempMax; pos=startPos; } } else { //不是数字 tempMax=0; startPos++; break; } tempCharCount++; } if(startPos+tempCharCount==len) { break; } tempCharCount=0; } strings=inputStr.Substring(pos,maxLen); returns; }代码简单描述初学Java语言之多态初体验本文面向Java初学者,我们在教材上经常会看到Java是多态的,可是一般的教科书只停留在理论上,很少有实际操作。现在把多态个概念用代码简单描述一下,由于本人水平有限,所以难免有不足之处。 首先我们有这样几个类,电脑,个人电脑,笔记本电脑。 publicvoidturnOn(){ } } 现在有了电脑这个类,那么个人PC,笔记本都是继承他。 classPCextendsComputer{ publicvoidturnOn(){ System.out.println("PChasturn上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.comon"); } } classNBextendsComputer{ publicvoidturnOn(){ System.out.println("NBhasturnon"); } } 我们看到,每个类都有一个turnOn()方法,而在父类中这个方法是空的,子类中各自有不同的实现,到这里可能还不太明显。如果有另外一个方法,要接受这些类作为参数,就像这样 classTest{ publicvoidgo(Computercomputer){ computer.turnOn(); } } 这个方法接收的是基类参数,当然我们是可以把子类传递给方法的,也应该这么做。 go(newPC()); go(newNB()); 这样他就会去调用具体子类的turnOn()方法,所以这两次调用的输出是不一样的.如果不用基类作为参数,我们想调用每个子类的turnOn()方法,那么就要些两个方法体一样的go()而接收不同的参数的重载。 publicvoidgo(PCcomputer){ computer.turnOn(); } publicvoidgo(NBcomputer){ computer.turnOn(); } 这样些也是正确的,但是这样会产生很多重复代码,而且也不易维护,当然这只是多态中最基本的一个部分,Java多态机制还有很多特性,关于这些建议大家看看java编程思想(thinkinjava)这本书,里面讲的很详细,这里只是很简单的描述了一下。打造自己Windows终端服务客户端1.首先确保你的机器上存在mstscax.dll,如果没有这个文件,可以从http://download.microsoft.com/download/whistler/tools/1.0/wxp/en-us/msrdpcli.exe 下载并安装远程桌面连接软件.或者使用WindowXP中自带的mstscax.dll,运行regsvr32mstscax.dll进行注册,ccrun测试使用的mstscax.dll版本号是5.1.2600.0,在Windows2000Server中可以编译。上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com2.运行C++Builder-->Components-->ImportActiveControl,在列表中找到下面的: MicrosoftTerminalServicesActiveClient1.0TypeLibrary(Version1.0) 点击Install,你可以选择将其安装到现在的包中,也可以新建一个,选择Intonewpackage-->点击Browser将其保存为D:\ProgramFiles\Borland\ccrun\mstsc\mstsc.bpk。在Description一栏可以填:MicrosoftTerminalServiceControl,这个名称将出现在安装完成后的Package列表中。点击OK以后,稍等片刻,系统会提示mstsc.bpl将被编译并且安装,是否继续,点击yes。这时如果一切正常的话,系统将提示有两个编译错误(嘿嘿,我指的是正常情况下),难道是BCB的BUG?提示找不到OlePrecedure的定义。我靠。记忆中有个OleProcedure,一个o,一个e,该不会真的是笔误吧。将两处OlePrecedure换成OleProcedure,再次编译,ok了,编译成功,点击Install安装。 3.如果上一个步骤成功的话,在组件面板的ActiveX下将多出两个控件:MsTscAx和MsRdpClient,我们主要是利用MsTscAx控件。 4.MsTscAx控件的常用属性和方法: //桌面高度 MsTscAx1->DesktopHeight=600; //桌面宽度 MsTscAx1->DesktopWidth=800; //在连接前显示的字符串 MsTscAx1->ConnectingText=WideString("Welcome!ccrun."); //连接的服务器地址 MsTscAx1->Server=WideString(edtServer->Text); //窗口/全屏模式 MsTscAx1->FullScreen=false; //文档标题:打造自己的Windows终端服务客户端 //作者:ccrun(老妖)信箱:info@ccrun.com //为防止不负责任的转载者遗漏作者信息,故在此插入此信息,请见谅. //欢迎访问C++Builder研究http://www.ccrun.com //画面色深(通常都是256色) MsTscAx1->ColorDepth=16; //登录用户名 MsTscAx1->UserName=WideString(edtUserName->Text); //断开连接后显示的字符串 MsTscAx1->DisconnectedText=WideString("886,ccrun."); //将位图缓存到磁盘 MsTscAx1->AdvancedSettings->BitmapPeristence=1; //启用数据压缩 MsTscAx1->AdvancedSettings->Compress=1; //上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com连接后运行的Shell程序,当关闭此Shell程序后自动断开连接 MsTscAx1->SecuredSettings->set_StartProgram(WideString("C:\\ccrun\\123.exe")); //连接 MsTscAx1->Connect(); //断开连接 MsTscAx1->Disconnect(); 5.新建一个Project,在Form上拖一个MsTscAx控件,根据上面介绍的属性和方法,相信你在BCB中建立自己的终端服务客户端没问题了。 6.编译后的程序发布时必须在目标机器上存在mstscax.dll文件,并且用Regsvr32注册以后才能正常运行。程序员:最简洁的多重查询的解决方案 我们经常会遇到多重查询问题,而长长的SQL语句往往让人丈二和尚摸不着头脑。特别是客户端部分填入查询条件时,如用普通方法将更是难上加难。 以下巧妙地利用"where1=1"的恒等式(事实上很多,让它值为TRUE即可)解决此问题。 正文概要 ’subject信息标题 ’company发布信息的公司名称 ’content发布信息的内容 ’address公司地址 ’infomation公司简介 ’note相关说明 以上值均由FORM提交,然后通过:subject=trim(Request.Form("subject"))等得到相应的值。 <% ’这个函数很关键!--------------------------- Functionsql(a,b,sqls) ifb<>""then’如果客户端没有提交此值,则不会产生相应的SQL语句。 sqls=sqls&"and"&a&"like’%"&b&"%’" endif sql=sqls EndFunction ’-----------------调用数据库 Setconn=Server.CreateObject("ADODB.Connection") DBpath=Server.MapPath("/database/mydb.mdb") Conn.Open"driver={MicrosoftAccessDriver(*.mdb)};pwd=;dbq="&DBpath Setrs=Server.CreateObject("ADODB.Recordset") sqls="select*frommytablewhere1=1上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html\n上学吧http://www.shangxueba.com" ’以下调用上面的函数即可,可以很多个调用(理论上是任意) sqls=sql("subject",subject,sqls) sqls=sql("company",company,sqls) sqls=sql("content",content,sqls) sqls=sql("address",address,sqls) sqls=sql("infomation",infomation,sqls) sqls=sql("note",note,sqls) sqls=sqls&"orderbyiddesc" rs.opensqls,conn,3,2 %>上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html上学吧为您提供程序员(初级)考试资料下载:http://www.shangxueba.com/share/e8.html
此网页使用了框架,但您的浏览器不支持框架。
数据库名:
文件路径:
" response.writeerr.description&"" endif Response.write"
" response.writeerr.description&"" endif rest.SQLRestoresrv Response.write"恢复成功!" else Response.write"