ACM练习建议[转]

转自:ACM练习建议

  一般要做到50行以内的程序不用调试、100行以内的二分钟内调试成功.acm主要是考算法的,主要时间是花在思考算法上,不是花在写程序与debug上。   下面给个计划你练练: 第一阶段: 练经典常用算法,下面的每个算法给我打上十到二十遍,同时自己精简代码, 因为太常用,所以要练到写时不用想,10-15分钟内打完,甚至关掉显示器都可以把程序打 出来. 

1.最短路(Floyd、Dijstra,BellmanFord)  
2.最小生成树(先写个prim,kruscal要用并查集,不好写)   
3.大数(高精度)加减乘除  
4.二分查找. (代码可在五行以内)   
5.叉乘、判线段相交、然后写个凸包.   
6.BFS、DFS,同时熟练hash表(要熟,要灵活,代码要简)   
7.数学上的有:辗转相除(两行内),线段交点、多角形面积公式.  
8. 调用系统的qsort, 技巧很多,慢慢掌握.   
9. 任意进制间的转换

第二阶段: 练习复杂一点,但也较常用的算法。   如:  
1. 二分图匹配(匈牙利),最小路径覆盖   
2. 网络流,最小费用流。   
3. 线段树.  
4. 并查集。   
5. 熟悉动态规划的各个典型:LCS、最长递增子串、三角剖分、记忆化dp  
6.博弈类算法。博弈树,二进制法等。   
7.最大团,最大独立集。   
8.判断点在多边形内。   
9. 差分约束系统.  
10. 双向广度搜索、A*算法,最小耗散优先.

第三阶段: 前两个阶段是打基础,第三阶段是锻炼在比赛中可以快速建立模型、想新算法 。这就要平时多做做综合的题型了。   
1. 把oibh上的论文看看(大概几百篇的,我只看了一点点,呵呵)。  
2. 平时扫扫zoj上的难题啦,别老做那些不用想的题.(中大acm的版主经常说我挑简单的来 做:-P )   
3. 多参加网上的比赛,感受一下比赛的气氛,评估自己的实力.   
4. 一道题不要过了就算,问一下人,有更好的算法也打一下。  
5. 做过的题要记好 :-)   

- 阅读全文 -

第三方改版QQ概况介绍[转]

摘自:http://www.cnbeta.com/articles/40128.htm

目前市面上有很多不同名称的第三方QQ版本,其去广告显IP的核心都是来自珊瑚虫或飘云,真正的原创只有这两个,以下是其他QQ版本的功能对比表.
√:表示该项目为真
×:表示该项目为假
—:表示该项目未验证
☆:表示该版本使用珊瑚虫增强包
★:表示该版本可选珊瑚虫增强包和飘云显IP补丁
注:本比较中不含论坛自用版本和二次修改版本!

表:QQ流行版本比较

  原创作品 使用纯真IP 捆绑插件 界面广告 完整功能 辅助工具
珊瑚虫 √  × √  × √  ×
飘云 √  √  × × √  ×
狂人 √  √  √  √  √ 
传美 √  √  √  √  √ 
阿瑞斯 √  × × × ×
快乐无极   —   —   — √  √ 
海峰 × √  √  √  √ 
威雅 × × × × ×
雨林木风   —   —   — √  √ 


说明:
1.是否使用纯真IP,决定此版本是否能显示网吧,纯真数据库有5MB多,而珊瑚虫数据库不到1MB.一般来说珊瑚虫数据库只能精确到省会城市的区,所以地理位置的选择与你使用的QQ版本无关;
2.几乎所有版本均使用珊瑚虫增强包,显隐身功能无非是珊瑚虫获取IP时所产生的残留数据,并非100%准确.并不是所有的版本都拿此出来宣传,所以能否显示隐身与你使用的QQ版本无关;
3.最忠实于原版的版本还是两个原创,珊瑚虫和飘云,普通用户推荐使用这两个版本.若希望获得更多额外的辅助工具,推荐使用海峰版本.若只想聊天视频或对内存占用有需求,建议使用阿瑞斯版本.

- 阅读全文 -

用.net实现QQ的原代码![转]

转自:用.net实现QQ的原代码!

大家说到QQ协议都觉得很神秘,是因为QQ不像MSN或者ICQ协议都已经官方公布了,而QQ的没有公布。研究它的人也不是特别的多,虽然已经有了基于QQ协议所写成的第三方软件   foicq,   qq   plugins   for   gaim,   LumaQQ,但是由于他们是基于二进制Stream的协议过于复杂,大家阅读代码也有一定的难度,再加上网络上解析QQ协议的文章也不是十分多,所以基于QQ网络协议的应用程序也是寥寥无几的。现在我就把基于HTTP的QQ协议进行一个粗浅的剖析,希望对大家有所帮助。源码部分就用我喜欢的DELPHI和现在比较流行的C#语言对QQ协议的实现进行具体分析。  
 

1、找寻支持QQ   HTTP协议的服务器。  
  大家也许会被一些假像所迷惑,也许会认为QQ的HTTP服务器是基于80口进行通信的(如:218.17.209.23:80),其实不然,正真基于HTTP的服务器应该是:http://tqq.tencent.com:8000,它是一个通过8000口进行通讯的服务器。  
  由于QQ的HTTP服务器并不支持HTTP协议中GET方法,它支持POST方法。所以我们要给QQ的HTTP协议传参数,那么就必需要用POST方式才行。  
 

2、C#和DELPHI是实现HTTP的POST方法的通信。  
  C#:  
      C#里System.Web空间下提供了一个叫做WebClient的对象,使用此对象就可以使C#直接对服务器发送WEB客户端的请求。那么我们要对服务器提交POST方法那么就必须使用其UploadData()方法才行。首先把要请求的信息先转换为字节(因为POST提交的是字符的流数据),然后再做为UploadData()的参数。使用UploadData()进行数据提交,最后返回,POST的回馈信息。如下:  

      WebClient   _client   =   new   WebClient();   
      string   postValues   =   "VER=1.0&CMD=Query_Stat&SEQ=12321&UIN=29501213&TN=50&UN=0";   
      Byte[]   byteArray   =   System.Text.Encoding.ASCII.GetBytes(postValues);   
      Byte[]   pageData   =   _client.UploadData(Host,"POST",byteArray);  
 

  这样,我们就利用C#进行了一次HTTP的POST方法提交了。  
  DELPHI:  
      Delphi里我们利用一个比较流行的第三方VCL,INDY   HTTP(这个组件D6,D7里面自带)进行HTTP通信。使用其的POST方法便可以进行HTTP的POST通信,因为组件比较好用,我就不在其描述具体的过程了。大家可以参考以下代码:  
 

function   PostWebPage(url,para:String;TimeOut:Integer):String;   
  var   
      tmpWeb:TIdHTTP;   
      retrun:String;   
      Proxy:String;   
      i:Integer;   
      paralist:TStrings;   
  begin   
      retrun:='';   
      try   
          paralist:=TStringList.Create;   
          paralist.Text:=_Replacing(para,'&',#13#10);   
          tmpWeb:=TIdHTTP.Create(nil);   
          tmpWeb.ReadTimeout:=TimeOut;   
          for   i:=1   to   3   do   
          begin   
              try   
                  retrun:=tmpWeb.Post(url,paralist);   
              except   end;   
              if   retrun<>''   then   break;   
          end;   
      finally   
              tmpWeb.Disconnect;   
              FreeAndNil(tmpWeb);   
              FreeAndNil(paralist);   
      end;   
      Result:=retrun;   
  end;   


  值在传入、返回时,其是基于UTF-8进行的,C#显示中文是很常,而DELPHI就要进行UTF-8的转换了。大家可通过Utf8ToAnsi()、AnsiToUtf8()进行转换。(编码转换是C#的优越性之一)  
 

3、实现QQ的用户登录。  
  在QQ通信中用户必需要登录后才可以进行互相发送信息等。QQ的登录是很关键的,大家所看到的用户在线,并不是用户的QQ一直连接着服务器,而是定时发送消信给服务器,证明自己还连着线,如果超出时间QQ就认为用户已经掉线了。  
  在登录协议中,QQ的密码是用标准的MD5来进行加密,DELPHI的用户只需要下个MD5加密模块就可以了,而C#自已带有,但是直接用不了,必需进行处理后,才能使其变成标准的MD5,处理代码如下:

 

  public   static   string   MD5(string   toCryString)   
  {   
  MD5CryptoServiceProvider   hashmd5;   
  hashmd5   =   new   MD5CryptoServiceProvider();   
  return   BitConverter.ToString(hashmd5.ComputeHash(Encoding.Default.GetBytes(toCryString))).Replace("-","").ToLower(); 
//asp是小写,把所有字符变小写  
  }    

  了解QQ是如何对用户密码加密后,那么我们就开始真正,解析QQ的HTTP登录协议了,我们把协议当传POST的参数传给服务器,而服务器则回馈相应的信息给客户端:  
  传入协议:  
      VER=1.1&CMD=Login&SEQ=&UIN=&PS=&M5=1&LC=9326B87B234E7235  
      VER是用来说明QQ协议的版本,CMD是说明协议的命令,Login就是指QQ的登录了,SEQ是他的为了防止重复发送而设定的一个标记,一般我们取当前时间数值的一段放入即可。(C#:DateTime.Now.Ticks.ToString().Substring(7,7)   DELPHI:CopyStr(inttostr(GetTickCount()),1,5)),UIN是说明你当前要登录的用户QQ号,PS,是MD5加密过后的密码的值。  
  返回协议:  
      VER=1.1&CMD=Login&SEQ=11281&UIN=&RES=0&RS=0&HI=60&LI=300(成功)  
  RES为0表示成功返回,RS为0表示登录成功。  
      VER=1.1&CMD=Login&SEQ=11422&UIN=315103947&RES=0&RS=1&RA=登录失败  
  RS为1表示登录失败,那么就会出现提示信息RA说明原因。  
 
4、获得QQ名单。  
  如果您加了您的好友,那么您的好友就会放入你的QQ的好友名单里面,那么我们要得到QQ名单就必需给QQ服务器发送得到好友名单的协议(我就不从复已知的参数了):  
      VER=1.1&CMD=List&SEQ=&UIN=&TN=160&UN=0    
  服务器得到协议后如果成功则返回:  
      VER=1.1&CMD=LIST&SEQ=43661&UIN=29501213&RES=0&FN=1&SN=24&UN=561256,1943497,....  
  UN后面则是您好友的QQ号码,每个号码都由,进行分开。那么我们只需要得到UN后面的代码,把它列表化就OK了。C#可以用string.Split(',')把值放入列表进行处理,而DELPHI可以使用Split()把数值放入TStrings里进行处理。  
 
5、获得QQ好友在线名单  
  获得QQ好友在线名单,跟获得好友名单差不多,唯一不同的是用的命令不同用的是Query_Stat,协议如下:  
      VER=1.1&CMD=Query_Stat&SEQ=&UIN=&TN=50&UN=0    
  服务器得到协议后如果成功则返回:  
  VER=1.1&CMD=QUERY_STAT&SEQ=-1&UIN=29501213&RES=0&FC=141,270,270,&FN=1&SN=3&ST=10,10,10,&UN=12327207,24259132,29501213,&NK=   □,微程,鶹鸑,&    
  FC为QQ头像的的ID,如的头像ID为270,那么其头使用的图片为91.bmp,其算法为ID/3+1。ST为QQ用户的状态,10为上线,20为离线,30为忙碌。UN为在线用户的QQ号,NK为在线用户的QQ昵称。ST,UN,NK,每个逗号隔开的数据相互对应。在得到消息后如果用的是DELPHI语言,那么要用Utf8ToAnsi()进行转换,不然会出现乱码。  
6、得到QQ用户的信息。  
  如果要看到QQ用户的真实名称,MAIL,年龄,个人说明等信息,那么我们必需要向服务器发送得到好友信息的信息:  
      VER=1.1&CMD=GetInfo&SEQ=&UIN=&LV=2&UN=  
  UN为要查看用户信息的QQ号。  
  服务器得到协议后如果成功则返回:  
  VER=1.1&CMD=GETINFO&SEQ=12707&UIN=415103947&RES=0&AD=云南昆明&AG=0&EM=Microprogramer@hotmail.com&FC=270&HP=msger.org(建设中...)&JB=程序员&LV=2&PC=650000&PH=0871-6466529&PR=网络为媒%252c关系为本%252c信息为财%252c客户为主.%0d%0a&PV=云南省&RN=刘X&SC=社会大学&SX=0&UN=24259132&NK=微程  
  AD用户的联系地址,AG为用户年龄,EM为用户MAIL,FC为用户头像,HP为用户网站,JB为用户职业,PC为用户邮编,PH为用户联系电话,PR为用户简介,PV为用户所以的省,RN为用户真实名称,SC为用户毕业院校,SX为用户性别,UN为用户QQ号,NK为用户QQ昵称。在得到消息后如果用的是DELPHI语言,那么要用Utf8ToAnsi()进行转换,不然会出现乱码。  
 
7、增加QQ好友。  
  想要新增好友,就要发送AddToList命令给服务器,具体命令如下:  
      VER=1.1&CMD=AddToList&SEQ=&UIN=&UN=  
  UN为我们要增加用户的QQ号。  
  服务器得到协议后如果成功则返回:  
  VER=1.1&CMD=AddToList&SEQ=13666&UIN=415103947&RES=0&CD=0&UN=24259132  
  CD为被加QQ的身份验证状态,CD为0表示“允许任何人把我列为好友”,CD为1表示“需要身份证认才能把我列为好友”,CD为3表示“不允许任何人把我列为好友”。如果CD为0那么信息回馈后,用户就直接加为好友了,如果CD为1,那么还要发送一次回应加为好友的响应。  
 
8、回应加为好友的响应。  
  回应加为好友响应是双方的:1、如果你发送了请求加对方为好友,如果对方需要验证,那么必需发送回应加为好友的响应。2、如果对方发送加为好友请求给你,那么你可以加应加为好友的响应,一是加为好友,一是通过验证,一是拒决加为好友。我们要向服务器发送命令:  
  VER=1.1&CMD=Ack_AddToList&SEQ=&UIN=&UN=&CD=&RS=  
  CD为响应状态,CD为0表示“通过验证”。CD为1表示“拒决加为对方为好友”。CD为2表示“为请求对方加为好友”。RS为你要请求的理由,如果您用的是DELPHI那么RS在发送之间要用AnsiToUtf8()进行转换,不然发送过后,请求理由会变成“?”。  
  服务器得到协议后如果成功则返回:  
  VER=1.1&CMD=Ack_AddToList&SEQ=1130&UIN=415103947&RES=0&  
 
9、删除好友。  
  删除好友其实很容易,向服务器发送DelFromList命令则可以删除用户:  
  VER=1.1&CMD=DelFromList&SEQ=&UIN=&UN=    
  UN为要删除用户的QQ号。  
  服务器得到协议后如果成功则返回:  
  VER=1.1&CMD=DelFromList&SEQ=24514&UIN=415103947&RES=0&  
 
10、改变用户当前状态。  
  可以把QQ设置为在线,隐身等状态,我们可以发送Change_Stat给服务器以改变当前状态,具体命令如下:  
  VER=1.1&CMD=Change_Stat&SEQ=&UIN=&ST=    
  ST为要改变的状态,10为上线,20为离线,30为忙碌。  
  服务器得到协议后如果成功则返回:  
  VER=1.1&CMD=Change_Stat&SEQ=17512&UIN=415103947&RES=0&  
 
11、退出登录  
  要退出登录,要向服务器发送命令Logout,具体命令如下:  
  VER=1.1&CMD=Logout&SEQ=&UIN=  
  服务器得到协议后如果成功则返回:  
  VER=1.1&CMD=LOGOUT&SEQ=15803&UIN=415103947&RES=0  
 
12、获得好友QQ的消息  
  如果要接收好友的消息,要向服务器发送命令GetMsgEx,具体命令如下:  
  VER=1.1&CMD=GetMsgEx&SEQ=&UIN=    
  服务器得到协议后如果成功则返回:  
  VER=1.1&CMD=GETMSGEX&SEQ=56661&UIN=29501213&RES=0&MN=3&MT=99,9,9,&UN=24259132,24259132,24259132,&MG=30   ,asdfasdfasdfasdf   ,asdfasdfasdf   ,&  
  MT表示消息类型,99表示系统消息,9表示用户消息。UN表示消息发送来源用户,MG表示发送的消息,MG消息可以表示某些特定的系统含意,譬如:当MT为99,MG为30,UN为24259132则表示用户4259132现在处于忙碌状态,可根据此消息进行好友列表的刷新,提高效率。在得到消息后如果用的是DELPHI语言,那么要用Utf8ToAnsi()进行转换,不然会出现乱码。  
 
13、向好友QQ发送消息  
  要发送消息给好友,要向服务器发送命令CLTMSG命令,具体命令如下:  
  VER=1.1&CMD=CLTMSG&SEQ=&UIN=&UN=&MG=    
  UN为消息发送给的用户QQ号码,MG为发送给该用户的消息。如果您用的是DELPHI那么MG在发送之间要用AnsiToUtf8()进行转换,不然发送过后,消息会变成“?”。  
  服务器得到协议后如果成功则返回:  
    VER=1.1&CMD=CLTMSG&SEQ=15803&UIN=415103947&RES=0  
  好了,以上就是QQ基于HTTP的一个不完全的协议分析,在无源码前提下,在下能力有限,只能够分析这么多了。利用以上协议您就可以实现很多东西,如:QQ机器人,QQ广告系统,即时通讯的整合工具等等。

- 阅读全文 -

DDR公布迅雷修改版源代码和技术细节[转]

转自:http://www.cnbeta.com/articles/40006.htm

ugmbbc发布于 2007-09-27 16:29:23|7260 次阅读 字体: 打印预览

迅雷

感谢凯迪辣客的投递
新闻来源:DDR
迅雷5.7.2.371 DDR1.5版去广告版源代码说明
Thunder5.7.2.371 DDR Ver1.5 SourceProject ReadMe
我今天公布我写的源代码,目的是起到交流学习的作用,因为在未来的一段时间里面,我将要参加一场很重要的考试,虽然考试的结果对于我来讲并不十分重要,但是我一定要去努力。所以我不会有时间来维护这些东西,与其让它在硬盘里躺着,不如拿出来,这样我就可以心思坦坦的去复习所有的功课了,要不然的话总放不下心。

好了,有关软件的东西,是包括文档与代码,对于我自己,我是有详细的调试记录与大量的文档记载的,不过可惜的都是写在稿纸上,所以我无法上传,但是我可以把所有的代码都上传上来,虽然对于理解起来可以会稍有困难,但是我在下面稍加解释,以便有个全局的概念。
本地下载:
http://bbs.happyhome.name/upload/DDR_371Project_Source.rar
微软网络硬盘下载:
http://cid-778609f9f4685429.skydrive.live.com/self.aspx/Public/DDR_371Project_Source.rar
源代码目录与文件的概括解释:
.........这个是主目录
371Project         .........这个是迅雷5.7.2.371版的目录
LinkSimulate         .........这个是模拟链接的ATL框架支持的ActiveX源代码
s_parselink          .........模拟链接解密静态库源代码(即base64解码编码库)
setup371             .........这个是5.7.2.371安装脚本和迅雷安装文件
ThunderSetting       .........这个就是大家熟悉的"DDR迅雷设置中心"的源代码了
tpatch371            .........细心的人一定知道DDR迅雷program目录里面有个tpatch.dll文件, 这个就是那个文件的源代码
iTargetAD_Re            .........这个是我改写的iTarget.dll文件的ASM源代码,为什么用asm写,你打开看就知道了。 
编译环境:
Visual Studio 2005
masm32(这个是win32 ASM编译器,只有iTargeAD_Re目录里面的一个文件编译需要它)
Inno Setup5 (脚本编译程序,setup371目录打包需要它)
  如果你想实践一下,编译运行的话,就需要上面的三个软件。我可以保证都是完全可以通过编译的,如果你对其中某些部分不理解或者某些编译环境不够熟悉,也不用太担心,你可以先看看源代码,在理解的基础上然后用自己熟悉的环境去改写。
  当然我承认其中有些代码写的似乎不是很优雅,但这不是我的真实水平,我只是让代码可以运行起来,而没有想办法让代码变得更加漂亮,因为家里人都不支持写程序,所以我只能在空隙之间穿插着写点东西,虽然这种手法相当糟糕,但也是一时权宜之计,不过我仍然加了许多注释,你们在文件中所看到的注释都是我当时加的,这些注释将是分析代码的路灯,它们没有任何改动和删节(同样你们一定也会发现注释中有不少错别字^_^)。
  欢迎大家研究改写,也可以提出问题和看法,但是我可能不能做解答,因为上网时间要有控制,所以不要对我抱有太大期望。但我还是会在偶尔有时间的时候回来看看的:-)
  然后要讲的就是,前一段时间有很多网友来访问我的空间,我很高兴,我经常告诉我的朋友,我的访问统计是呼呼呼的向上涨,几乎接近tan(x) 从(0到PI/2)那段曲线,不过未来的100多天里,可能不能再继续出我的版本了,因为我又有了新的奋斗目标。现在是07.9.27 8:55,我不知道新版本的迅雷什么时候会出,其实我很想给大家一个全新的380版(暂且这样称呼吧)修改后的源代码,但是我等不及了,这也不能不称得上是件遗憾的事情,但我希望在我回来的时候能看到更多更有趣更酷的版本......
  当然光给源代码是不够的,有些东西我希望你们用OllyDbg或者其他调试软件调试,其实这个难度并不大,充其量只是一个简单的CrackMe而已,但是要有一定的耐心,还要多记录结果综合分析。
  tpach371目录下的文件是屏蔽广告的关键所在,可以用LordPE或类似工具软件插入到迅雷程序里面,因为用的是改写内存的方式,希望可以结合 OllyDbg,观察改写前后内存中代码的变化。否则的话,你直接看这部分代码,可能会觉得云里雾里,因为有些地方要用asm才能解释清楚。再给一点提示,关于如何调试,我建议你在调试器里面下WriteProcessMemory函数断点,这样你将会获得所有改动过的信息,并且我也发现逆向MFC框架搭建的软件是学习MFC的一个有效途径(汗......)。
  ThunderSetting目录下的文件是"DDR迅雷设置中心",其实是一个改写ini文件的GUI Shell,没什么实质性的内容,不过却方便了设置。LinkSimulate是模拟链接的关键,虽然是关键之笔但是却异常的简洁明了,看我的IDL文件描述,一个COM替换而已,我把得到的所有的参数都扔到迅雷的COM里让它去干活,而我呢则呼呼大睡去了。
  s_parselink是静态库,LinkSimulate和tpatch371都会调用它,里面有两个base64解码和加密函数,和一些专用链接的转换函数,不要被专链吓怕了,我这里有全部的转换方法。
  iTargetAD_Re最为简单,我还加了makefile文件,这样你编译的时候就不会太累了,呵呵....
  然后是setup371目录,有编译脚本的代码,和去除社区互动的OCrack_XLCommunity.dll.bak文件,你可以把它与正版的XLCommunity.dll用文件对照工具对比一下,就一处更改哦,当然光看到一些16位数字串的不同是没有任何意义的,你要到OllyDBG 下面去实践一下到底改成了什么,为什么这么改,这样才会有收获....
  其实我应该把所有项目都放到一个工程项目里面,但是我当时就没有这么做,导致现在目录比较乱,但我已经尽最大的力量把所有的都解释了一遍。
  对于高手来讲看这些东西都十分的轻而易举,也会发现我讲的也十分明白。但是对于部分新手可能会有些困难而又迫不及待的想弄清楚所有的一切,我希望你们可以先了解一些调试工具和开发环境的使用,然后再慢慢深入理解,同时把我上面讲的话语当中的关键字提取出来然后用Baidu或Google去搜集一些对你有用的信息。当然你也不需要去刻意弄懂一切,其实这些东西全然是一些雕虫小技,并不值得去消磨那么多时间,你应该把精力放到更有意义的地方,比如数学、英语啊,计算机组成、体系啊、数据结构、软件工程的学习,虽然短期内不会有突出成效,但这些是真正的屠龙刀,而我以前就是好大喜功,杀鸡取卵,等不及了,先学了一大堆所谓的API和其他各种标榜着"提高生产力"的语言,而对真正理论的东西学的不深不透,现在自食其果,后悔不及,不过亡羊补牢,犹未为晚,同样我也不希望后来者重蹈覆辙。不管怎么讲,到时候功到自然成,其他的都是衍生出来的附加产物。
  好了,我已经把所以的关键点都挑明了,剩下的就靠你自己了,你愿意怎么添啊改啊删啊都可以,最好的方式是消化掉所有的一切,然后Ctrl+Delete,再重新创造自己的。
  最后我想引用新东方老师的一句话做结尾:从绝望中寻找希望,人生终将辉煌........................
Date: Birthday
by DDrMsdos

- 阅读全文 -

delphi 用windows消息传递字符串

可以用PostThreadMessage,例如:  
 

  //发送线程  

  Procedure   TThread1.Execute;   
  var   
      sMes:String;   
      pMes:^String;   
      iTemp:Integer;   
  begin   
      sMes:='Test';   
      New(pMes);   
      pMes^:=sMes;   
      PostThreadMessage(thread2.ThreadID,WM_StartRecording,Integer(pMes),0);   
      iTemp:=111;   
      PostThreadMessage(thread2.ThreadID,WM_OriginalData,iTemp,0);   
  end;  


  //接受线程  
  procedure   TThread2.Execute;  
  var  
      msg:TMsg;  
      sMes:String;  
      pMes:^String;  
      iTemp:Integer;  
  begin  
      //消息循环  
      while   GetMessage(msg,0,0,0)   do  
      begin  
          Case   msg.message   of  
              WM_StartRecording:  
              begin  
                  //传过来的是String;  
                  pMes:=msg.wParam;  
                  sMes:=pMes^;  
                  Dispose(pMes);  
              WM_OriginalData:  
              begin  
                  //传过来的是整数  
                  iTemp:=msg.WParam;  
              end;  
              else   begin  
                  TranslateMessage(msg);  
                  DispatchMessage(msg);  
              end;  
          end;  
      end;  
  end;  

- 阅读全文 -

东进d160a 内线挂机信号检测不到解决办法

2个步骤:

1.录制信号分析信号

利用东进信号分析工具录制从拨打到挂机,整段的语音,然后选择挂机后产生的几个有规律信号,点击“分析”,如图所示

image

选择“修改INI文件选项”—>Dial Busy1——>“修改INI文件”,保存到ini文件

2.手动修改NewSig.ini文件

根据用户手册

配置

[SYSTEM]

BusyNum=2

挂机忙音种类数,该值最大为2,如为2,则Sig_CheckBusy函数将同时检测2种挂机忙音。

-------------

默认值是1,因为之前没有注意到这个参数,导致步骤1很早就完成,还是一直没有办法检测到内线挂机信号……

修改后,终于可以检测到内线的挂机信号……

- 阅读全文 -

live writer beta3 12.0.1277.0816 发布

终于等到了新版出现,更新如下:

摘自官方spaces

We have received a lot of great feedback since our last release and have done our best to respond in this with this update.  This is the last beta before our final release so please give Beta 3 a run and keep the feedback coming in!

Download
  Version 12.0.1277.0816

Some highlights of this release:

  • Insert videos using our new 'Insert Video' dialog

  • Upload images to Picasaweb when publishing to your Blogger blog

  • Publish XHTML-style markup

  • Use Writer in 28 additional languages

  • Print your posts

  • Justify-align post text

  • Better image handling (fewer blurry images)

  • Resolved installation issues from last release

  • Many other bug fixes and enhancements

------------------------------------------------------------------------------------

其中,最让我高兴的是,yo2终于可以直接新建类别了,以前总是要在后台建一个类别,麻烦死了

 

image

高兴……

另外,可以插入video,jpg

image

- 阅读全文 -

10个突破屏蔽的方法

转自:solidot

由于某些原因,我们会被禁止访问某些特定的网站,WebStuffScan列出了10个突破屏蔽的方法。很多你可能都知道,比如直接使用IP地址,匿名代理服务器,但还有一些比较特别的:

1.使用IP地址,将域名转换称IP地址,网络上有许多这样的工具如hcidata
2.Google cache
3.匿名代理服务器,如ProxifyAnonymouse
4.使用在线翻译工具
5.使用Google移动搜索
6.使用公开的代理服务器,这里有一个列表
7.通过电子邮件获取网页内容,web2mail就提供这种服务。邮件服务器列表(许多已不可用)。
8.使用Tor
9.建立自己的代理服务(比较复杂)
10.使用可交换服务提供商,比如用一个少为人知的电子邮件收取Gmail中的邮件。

- 阅读全文 -

TSYS 资源

asp的cms系统

 

非常遗憾 2.0刚刚出测试版,作者就好像人间蒸发一样消失了,官方网站也在不久后处于管理状态,不过对于一个免费开源,没有版权的CMS来说我们也没有什么可要求的!在TSYS的各个版本中均没有出现过重大的安全漏洞而且对于目前1.1来说已经是很完善成熟的了,TSYS和一般的Asp 的CMS不大一样,他的功能并非由本身而定,而是根据使用者的能力而定。使用者越厉害 TSYS本身也可以变的更厉害。强大的诸如碎片等的信息管理,可以将信息在显示的时候重新整合,说白了就是只有对TSYS非常熟悉的人才可以将TSYS的优势发挥出来,因此,光就这点也就注定了TSYS流行不起来,除非具有人性话操作的修改版本出来。

http://www.tsyschina.com

官方网站已经无法访问

但是,网络上资源还是比较丰富的……


几个TSYS的版本下载

相关的一些文章

 

TSYS2.0建站源码,有演示

- 阅读全文 -

线程和进程

[前言:]当前流行的Windows操作系统,它能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力。用进程和线程的观点来研究软件是当今普遍采用的方法,进程和线程的概念的出现,对提高软件的并行性有着重要的意义。现在的应用软件无一不是多线程多任务处理,单线城的软件是不可想象的。因此掌握多线程多任务设计方法对每个程序员都是必需要掌握的。本文针对多线程技术在应用中经常遇到的问题,如线程间的通信、同步等,对它们分别进行探讨。
一、 理解线程
要讲解线程,不得不说一下进程,进程是应用程序的执行实例,每个进程是由私有的虚拟地址空间、代码、数据和其它系统资源组成。进程在运行时创建的资源随着进程的终止而死亡。线程的基本思想很简单,它是一个独立的执行流,是进程内部的一个独立的执行单元,相当于一个子程序,它对应Visual C++中的CwinThread类的对象。单独一个执行程序运行时,缺省的运行包含的一个主线程,主线程以函数地址的形式,如main或WinMain函数,提供程序的启动点,当主线程终止时,进程也随之终止,但根据需要,应用程序又可以分解成许多独立执行的线程,每个线程并行的运行在同一进程中。
一个进程中的所有线程都在该进程的虚拟地址空间中,使用该进程的全局变量和系统资源。操作系统给每个线程分配不同的CPU时间片,在某一个时刻,CPU只执行一个时间片内的线程,多个时间片中的相应线程在CPU内轮流执行,由于每个时间片时间很短,所以对用户来说,仿佛各个线程在计算机中是并行处理的。操作系统是根据线程的优先级来安排CPU的时间,优先级高的线程优先运行,优先级低的线程则继续等待。
线程被分为两种:用户界面线程和工作线程(又称为后台线程)。用户界面线程通常用来处理用户的输入并响应各种事件和消息,其实,应用程序的主执行线程CWinAPP对象就是一个用户界面线程,当应用程序启动时自动创建和启动,同样它的终止也意味着该程序的结束,进城终止。工作者线程用来执行程序的后台处理任务,比如计算、调度、对串口的读写操作等,它和用户界面线程的区别是它不用从CwinThread类派生来创建,对它来说最重要的是如何实现工作线程任务的运行控制函数。工作线程和用户界面线程启动时要调用同一个函数的不同版本;最后需要读者明白的是,一个进程中的所有线程共享它们父进程的变量,但同时每个线程可以拥有自己的变量。
二、 线程的管理和操作
1. 线程的启动
创建一个用户界面线程,首先要从类CwinThread产生一个派生类,同时必须使用DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE来声明和实现这个CwinThread派生类。
第二步是根据需要重载该派生类的一些成员函数如:ExitInstance();InitInstance();OnIdle();PreTranslateMessage()等函数,最后启动该用户界面线程,调用AfxBeginThread()函数的一个版本:CWinThread* AfxBeginThread( CRuntimeClass* pThreadClass, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );其中第一个参数为指向定义的用户界面线程类指针变量,第二个参数为线程的优先级,第三个参数为线程所对应的堆栈大小,第四个参数为线程创建时的附加标志,缺省为正常状态,如为CREATE_SUSPENDED则线程启动后为挂起状态。
对于工作线程来说,启动一个线程,首先需要编写一个希望与应用程序的其余部分并行运行的函数如Fun1(),接着定义一个指向CwinThread对象的指针变量*pThread,调用AfxBeginThread(Fun1,param,priority)函数,返回值付给pThread变量的同时一并启动该线程来执行上面的Fun1()函数,其中Fun1是线程要运行的函数的名字,也既是上面所说的控制函数的名字,param是准备传送给线程函数Fun1的任意32位值,priority则是定义该线程的优先级别,它是预定义的常数,读者可参考MSDN。
2.线程的优先级
以下的CwinThread类的成员函数用于线程优先级的操作:
int GetThreadPriority();
BOOL SetThradPriority()(int nPriority);
上述的二个函数分别用来获取和设置线程的优先级,这里的优先级,是相对于该线程所处的优先权层次而言的,处于同一优先权层次的线程,优先级高的线程先运行;处于不同优先权层次上的线程,谁的优先权层次高,谁先运行。至于优先级设置所需的常数,自己参考MSDN就可以了,要注意的是要想设置线程的优先级,这个线程在创建时必须具有THREAD_SET_INFORMATION访问权限。对于线程的优先权层次的设置,CwinThread类没有提供相应的函数,但是可以通过Win32 SDK函数GetPriorityClass()和SetPriorityClass()来实现。
3.线程的悬挂、恢复
CwinThread类中包含了应用程序悬挂和恢复它所创建的线程的函数,其中SuspendThread()用来悬挂线程,暂停线程的执行;ResumeThread()用来恢复线程的执行。如果你对一个线程连续若干次执行SuspendThread(),则需要连续执行相应次的ResumeThread()来恢复线程的运行。
4.结束线程
终止线程有三种途径,线程可以在自身内部调用AfxEndThread()来终止自身的运行;可以在线程的外部调用BOOL TerminateThread( HANDLE hThread, DWORD dwExitCode )来强行终止一个线程的运行,然后调用CloseHandle()函数释放线程所占用的堆栈;第三种方法是改变全局变量,使线程的执行函数返回,则该线程终止。下面以第三种方法为例,给出部分代码:
////////////////////////////////////////////////////////////////
//////CtestView message handlers
/////Set to True to end thread
Bool bend=FALSE;//定义的全局变量,用于控制线程的运行
//The Thread Function
UINT ThreadFunction(LPVOID pParam)//线程函数
{
while(!bend)
{Beep(100,100);
Sleep(1000);
}
return 0;
}
CwinThread *pThread;
HWND hWnd;
/////////////////////////////////////////////////////////////
Void CtestView::OninitialUpdate()
{
hWnd=GetSafeHwnd();
pThread=AfxBeginThread(ThradFunction,hWnd);//启动线程
pThread->m_bAutoDelete=FALSE;//线程为手动删除
Cview::OnInitialUpdate();
}
////////////////////////////////////////////////////////////////
Void CtestView::OnDestroy()
{ bend=TRUE;//改变变量,线程结束
WaitForSingleObject(pThread->m_hThread,INFINITE);//等待线程结束
delete pThread;//删除线程
Cview::OnDestroy();
}
三、 线程之间的通信
通常情况下,一个次级线程要为主线程完成某种特定类型的任务,这就隐含着表示在主线程和次级线程之间需要建立一个通信的通道。一般情况下,有下面的几种方法实现这种通信任务:使用全局变量(上一节的例子其实使用的就是这种方法)、使用事件对象、使用消息。这里我们主要介绍后两种方法。
1. 利用用户定义的消息通信
在Windows程序设计中,应用程序的每一个线程都拥有自己的消息队列,甚至工作线程也不例外,这样一来,就使得线程之间利用消息来传递信息就变的非常简单。首先用户要定义一个用户消息,如下所示:#define WM_USERMSG WMUSER+100;在需要的时候,在一个线程中调用
::PostMessage((HWND)param,WM_USERMSG,0,0)

CwinThread::PostThreadMessage()
来向另外一个线程发送这个消息,上述函数的四个参数分别是消息将要发送到的目的窗口的句柄、要发送的消息标志符、消息的参数WPARAM和LPARAM。下面的代码是对上节代码的修改,修改后的结果是在线程结束时显示一个对话框,提示线程结束:
UINT ThreadFunction(LPVOID pParam)
{
while(!bend)
{
Beep(100,100);
Sleep(1000);
}
::PostMessage(hWnd,WM_USERMSG,0,0);
return 0;
}
////////WM_USERMSG消息的响应函数为OnThreadended(WPARAM wParam,LPARAM lParam)
LONG CTestView::OnThreadended(WPARAM wParam,LPARAM lParam)
{
AfxMessageBox("Thread ended.");
Retrun 0;
}
上面的例子是工作者线程向用户界面线程发送消息,对于工作者线程,如果它的设计模式也是消息驱动的,那么调用者可以向它发送初始化、退出、执行某种特定的处理等消息,让它在后台完成。在控制函数中可以直接使用::GetMessage()这个SDK函数进行消息分检和处理,自己实现一个消息循环。GetMessage()函数在判断该线程的消息队列为空时,线程将系统分配给它的时间片让给其它线程,不无效的占用CPU的时间,如果消息队列不为空,就获取这个消息,判断这个消息的内容并进行相应的处理。
2.用事件对象实现通信
在线程之间传递信号进行通信比较复杂的方法是使用事件对象,用MFC的Cevent类的对象来表示。事件对象处于两种状态之一:有信号和无信号,线程可以监视处于有信号状态的事件,以便在适当的时候执行对事件的操作。上述例子代码修改如下:
////////////////////////////////////////////////////////////////////
Cevent threadStart,threadEnd;
////////////////////////////////////////////////////////////////////
UINT ThreadFunction(LPVOID pParam)
{
::WaitForSingleObject(threadStart.m_hObject,INFINITE);
AfxMessageBox("Thread start.");
while(!bend)
{
Beep(100,100);
Sleep(1000);
Int result=::WaitforSingleObject(threadEnd.m_hObject,0);
//等待threadEnd事件有信号,无信号时线程在这里悬停
If(result==Wait_OBJECT_0)
Bend=TRUE;
}
::PostMessage(hWnd,WM_USERMSG,0,0);
return 0;
}
/////////////////////////////////////////////////////////////
Void CtestView::OninitialUpdate()
{
hWnd=GetSafeHwnd();
threadStart.SetEvent();//threadStart事件有信号
pThread=AfxBeginThread(ThreadFunction,hWnd);//启动线程
pThread->m_bAutoDelete=FALSE;
Cview::OnInitialUpdate();
}
////////////////////////////////////////////////////////////////
Void CtestView::OnDestroy()
{ threadEnd.SetEvent();
WaitForSingleObject(pThread->m_hThread,INFINITE);
delete pThread;
Cview::OnDestroy();
}
运行这个程序,当关闭程序时,才显示提示框,显示"Thread ended"
四、 线程之间的同步
前面我们讲过,各个线程可以访问进程中的公共变量,所以使用多线程的过程中需要注意的问题是如何防止两个或两个以上的线程同时访问同一个数据,以免破坏数据的完整性。保证各个线程可以在一起适当的协调工作称为线程之间的同步。前面一节介绍的事件对象实际上就是一种同步形式。Visual C++中使用同步类来解决操作系统的并行性而引起的数据不安全的问题,MFC支持的七个多线程的同步类可以分成两大类:同步对象(CsyncObject、Csemaphore、Cmutex、CcriticalSection和Cevent)和同步访问对象(CmultiLock和CsingleLock)。本节主要介绍临界区(critical section)、互斥(mutexe)、信号量(semaphore),这些同步对象使各个线程协调工作,程序运行起来更安全。
1. 临界区
临界区是保证在某一个时间只有一个线程可以访问数据的方法。使用它的过程中,需要给各个线程提供一个共享的临界区对象,无论哪个线程占有临界区对象,都可以访问受到保护的数据,这时候其它的线程需要等待,直到该线程释放临界区对象为止,临界区被释放后,另外的线程可以强占这个临界区,以便访问共享的数据。临界区对应着一个CcriticalSection对象,当线程需要访问保护数据时,调用临界区对象的Lock()成员函数;当对保护数据的操作完成之后,调用临界区对象的Unlock()成员函数释放对临界区对象的拥有权,以使另一个线程可以夺取临界区对象并访问受保护的数据。同时启动两个线程,它们对应的函数分别为WriteThread()和ReadThread(),用以对公共数组组array[]操作,下面的代码说明了如何使用临界区对象:
#include "afxmt.h"
int array[10],destarray[10];
CCriticalSection Section;
////////////////////////////////////////////////////////////////////////
UINT WriteThread(LPVOID param)
{Section.Lock();
for(int x=0;x<10;x++)
array[x]=x;
Section.Unlock();
}
UINT ReadThread(LPVOID param)
{
Section.Lock();
For(int x=0;x<10;x++)
Destarray[x]=array[x];
Section.Unlock();
}
上述代码运行的结果应该是Destarray数组中的元素分别为1-9,而不是杂乱无章的数,如果不使用同步,则不是这个结果,有兴趣的读者可以实验一下。
2. 互斥
互斥与临界区很相似,但是使用时相对复杂一些,它不仅可以在同一应用程序的线程间实现同步,还可以在不同的进程间实现同步,从而实现资源的安全共享。互斥与Cmutex类的对象相对应,使用互斥对象时,必须创建一个CSingleLock或CMultiLock对象,用于实际的访问控制,因为这里的例子只处理单个互斥,所以我们可以使用CSingleLock对象,该对象的Lock()函数用于占有互斥,Unlock()用于释放互斥。实现代码如下:
#include "afxmt.h"
int array[10],destarray[10];
CMutex Section;
/////////////////////////////////////////////////////////////
UINT WriteThread(LPVOID param)
{ CsingleLock singlelock;
singlelock (&Section);
singlelock.Lock();
for(int x=0;x<10;x++)
array[x]=x;
singlelock.Unlock();
}
UINT ReadThread(LPVOID param)
{ CsingleLock singlelock;
singlelock (&Section);
singlelock.Lock();
For(int x=0;x<10;x++)
Destarray[x]=array[x];
singlelock.Unlock();
}
3. 信号量
信号量的用法和互斥的用法很相似,不同的是它可以同一时刻允许多个线程访问同一个资源,创建一个信号量需要用Csemaphore类声明一个对象,一旦创建了一个信号量对象,就可以用它来对资源的访问技术。要实现计数处理,先创建一个CsingleLock或CmltiLock对象,然后用该对象的Lock()函数减少这个信号量的计数值,Unlock()反之。下面的代码分别启动三个线程,执行时同时显示二个消息框,然后10秒后第三个消息框才得以显示。
/////////////////////////////////////////////////////////////////
Csemaphore *semaphore;
Semaphore=new Csemaphore(2,2);
HWND hWnd=GetSafeHwnd();
AfxBeginThread(threadProc1,hWnd);
AfxBeginThread(threadProc2,hWnd);
AfxBeginThread(threadProc3,hWnd);
//////////////////////////////////////////////////////////////////////
UINT ThreadProc1(LPVOID param)
{CsingleLock singelLock(semaphore);
singleLock.Lock();
Sleep(10000);
::MessageBox((HWND)param,"Thread1 had access","Thread1",MB_OK);
return 0;
}
UINT ThreadProc2(LPVOID param)
{CSingleLock singelLock(semaphore);
singleLock.Lock();
Sleep(10000);
::MessageBox((HWND)param,"Thread2 had access","Thread2",MB_OK);
return 0;
}
UINT ThreadProc3(LPVOID param)
{CsingleLock singelLock(semaphore);
singleLock.Lock();
Sleep(10000);
::MessageBox((HWND)param,"Thread3 had access","Thread3",MB_OK);
return 0;
}

- 阅读全文 -

热门文章

最新文章

最近回复

  • wfzlxvvgte: 你的文章让我感受到了不一样的风景,谢谢分享。 http://ww...
  • sfiutfecff: 你的文章内容非常用心,让人感动。 http://www.55ba...
  • dyqoaaqpdc: 你的文章内容非常卖力,让人点赞。 http://www.55ba...
  • vrfedcneqp: 你的文章内容非常卖力,让人点赞。 http://www.55ba...
  • wmhoubuazg: 你的文章内容非常用心,让人感动。 http://www.55ba...
  • khhhttrppu: 你的文章内容非常卖力,让人点赞。 http://www.55ba...
  • atjzyxiutr: 你的文章内容非常用心,让人感动。 http://www.55ba...
  • dlamzmkwwi: 你的文章内容非常卖力,让人点赞。 http://www.55ba...
  • predcxvhsz: 《蛋黄人》国产剧高清在线免费观看:https://www.jgz...
  • qmffcradmz: 《逃狱者》剧情片高清在线免费观看:https://www.jgz...

分类

标签

其它