本站首页    管理页面    写新日志    退出


«September 2020»
12345
6789101112
13141516171819
20212223242526
27282930


公告
暂无公告...

我的分类(专题)

日志更新

最新评论

留言板

链接

我的博客

Blog信息
blog名称:fermos_blog
日志总数:73
评论数量:261
留言数量:30
访问次数:385890
建立时间:2005年3月27日




专家承认长江中下游崩岸与三峡蓄水有关
新闻动态

fermos的博客 发表于 2006/5/4 18:33:45

专家承认长江中下游崩岸与三峡蓄水有关(图)   “天字一号”段崩岸产生的裂缝。 三峡工程总是吸引着世界的目光,在三峡工程开发总公司新闻宣传中心副主任徐斐的案头放着十几家海外媒体驻京办的采访申请,吸引他们前来的直接原因是三峡大坝即将全面完工。预计5月25日,右岸大坝建成,历时八年建设的三峡大坝整体完工。 但本报记者的目的不仅于此,自2003年三峡蓄水以来,三峡工程的生态和环境影响一直是牵动世界的敏感神经,传言、怀疑和揣测纷纷涌来,长江下游城市天气的异常、九江的地震等等都与之扯上了关系。最近的一次联系则是长江湖南段干堤的强烈崩岸,岳阳市长江修防处的人员把三峡工程蓄水后,清水下泄放在了崩岸原因之首。在长江流域汛期将至的5月,这一问题备受关注。 1986年和1987年先后来到宜昌,进行工程建设筹备的三峡总公司科技管理部陈永柏处长和枢纽管理部胡兴娥处长,在总公司内被称为环保专家,4月25日下午,他们接受了本报记者的独家专访,详细回答了三峡工程带来的长江泥沙变化、三峡库区水质、地震监测等一系列备受关注的问题。胡兴娥处长坦承:崩岸的产生确实与三峡蓄水后下游江水含沙量减少有关系。 疑虑一:岳阳江段崩岸 辩护词:长江本身含沙大幅减少 记者:前不久,长江干堤岳阳段部分段发生严重崩岸,有报道称原因是三峡工程初期蓄水后,下泄江水泥沙含量下降导致挟沙能力增强,下荆江河床冲刷严重。这个说法是事实吗? 胡兴娥:三峡工程建成后确实减少了大坝下游江水的含沙量,使冲刷加剧,从而造成一些崩岸。但江水含沙量的减少不仅仅是由于三峡工程的建设,主要原因是长江本身水流含沙量的大幅下降。我这里有一组数字可以说明:在上世纪50年代至90年代,宜昌站监测年平均输沙量达到5.1亿至5.2亿吨,上世纪90年代后减少了25%至29%;1991年至2002年年均输沙量为3.91亿吨,而2003年至2005年这一数量减少了50%。按照三峡库区40%的排沙比计算(也就是60%的沙子沉积在库区,40%的沙子排到下游),大坝下游的含沙量只有以前的两成。 记者:难道长江变清了反而不好? 胡兴娥:这就像溶解度一样,可以打个比方,沙子是溶解在江水中的,江水中的沙子要达到一定的饱和度,现在水清了,饱和度不够,就需要溶解更多的沙子,于是挟带河床、河岸的泥沙,造成冲刷,有些地方就会把护岸的下部基础冲深冲掉,造成崩岸。这个矛盾很有意思,一方面我们保持水土,使河流去浊还清,减少泥沙,但暂时又出现崩岸问题。 记者:江水是怎么变清的? 胡兴娥:一是上游的水土保持有效,一些25度以上坡度退耕还林等措施确实使植被恢复了很多;二是长江上游如嘉陵江的一些梯级开发,使泥沙下泄减少;三是长江干流和支流上的采砂现象比较严重。宜昌至沙市河段年均采砂量约在2000至3800万吨。 记者:从监测显示看,此次大坝下游的冲刷主要集中在宜昌至城陵矶河段,且比预计来得早,偏严重,这是什么原因呢? 胡兴娥:这与荆江河段本身的条件有关系。1998年、1999年大洪水之后,受洪水冲刷和江湖关系调整等因素,荆江局部河段河势变化就较为剧烈。冲刷显得比预计来得早且严重是因为原先我们计算采用的是六七十年代的沙量,得出总体的冲刷量在0.80亿吨左右,现在的数据接近1亿吨。但这个说明不了大问题,实质上没有量级上的差别。 疑虑二:泥沙淤积 辩护词:泥沙淤积比预计减少 记者:三峡工程建完后长江下泄的泥沙减少了,是不是意味着淤积在库区内的多了呢? 胡兴娥:你上午去了现场可以看到,目前不论是库区内的水还是下游的水都是绿的。 从监测看,2003年6月至12月入库沙量是2.08亿吨,2004年6月至12月入库沙量是1.66亿吨,2005年是2.52亿吨。前面说过三峡工程蓄水三年排沙比平均是40%,就是六成的沙沉在库区里,四成的沙排到下游。这个情况比我们设计阶段的预计值还要好,水库泥沙淤积情况比预计有所减少。我们初步设计的结论是头十年排沙比最大不到34%,也就是至少要有66%的沙在库里,现实运作证明有了很大的提高。 三峡工程采用“蓄清排浑”方式,汛期6月至9月(来水量占61%,来沙量占84%)将水库水位降低,泥沙通过23个泄洪深孔排至下游,非汛期的10月至次年5月,水库蓄水。 记者:这对下游的洞庭湖,包括长江口会带来什么样的影响? 胡兴娥:泥沙量减少对于洞庭湖和鄱阳湖等是有好处的,它们的淤积会减缓。1998年洪水流量不大却淹了很多地方,重要原因就是洞庭湖等湖泊泥沙淤积,库容减少。 疑虑三:九江地震 辩护词:它们根本不是同一地质板块 记者:去年九江地震时,网上立即就流传,这一地区本没有地震史,是三峡工程建设后引起的,听说监测到很多小的震动。 胡兴娥:其实九江和三峡根本就不是处于一个地质板块的。我们的台网精度相当高,零级左右的地震都可以监测到,从坝前至巴东是重点监测区,从巴东往上游至奉节是一般监测区。 从2003年6月份至今,三峡地震监测台网监测到2200多次小震,这听起来好像很多。但事实上这2200多次小震包括很多类型:一种是以前一些煤矿采空区进水后触发的坍塌带来的矿震,特别是湘西河沿岸留下了一些煤矿,很多都挖到了地下100米深,蓄水后就易塌,在1997年蓄水前,我们曾录得一千多次这种矿震呢;第二种是岩溶洞中发生的岩溶暴,这是地质上的一些小灾害。当地居民称岩溶洞为天坑,这些天坑在雨季容易发生坍塌,带来微震。附近的居民在春天都会经常听到闷响。 此外,三峡水库属于河谷性水库,它对地壳的结构不会有很大改变,不同于湖泊式的水库,湖泊式水库对地壳的应力比较大,容易产生结构性的地震。 疑虑四:下游升温水质变化 辩护词:气候是一种长期的变化 记者:去年以来有一种说法,重庆、宜昌的雾天增多,长江下游一些城市高温,这与三峡工程的建设有关,这种说法成立吗? 陈永柏:气候是一种长期变化,一年的数据不能说明什么,重庆本来就是出了名的雾都。作为峡谷河道型的水库,对局部气候的影响范围和程度是非常有限的。 记者:关于水库的水质也有很多传言,有的说是五类,有的说是Ⅱ类至Ⅲ类,水库存的水质究竟有什么变化呢? 陈永柏:外界报道的水质之所以出现不同的类别,主要是评价参数不一致。从1996年至现在的监测显示,水库水质总体上没有发生变化,在Ⅱ类至Ⅲ类间,有些指标如有机物含量有所改善。 我们最关心的问题之一是三峡水库的水质,但水库本身是没有污染的。按照法律,地方政府对区域环境质量负责,我们没有监督的权利。目前国家规划投资392亿元用于库区和上游水污染治理,规划修订工作正在开展,费用有可能增加。 记者:有没有出乎你们预计的情况发生? 陈永柏:目前还没有,都在此前的预测评价之中。三峡库区目前还在围堰蓄水运行期中,今年下半年将进入初期运行,蓄水水位也将上升到156米。 记者:此前有媒体报道过库区垃圾漂浮物的问题。 胡兴娥:去年有媒体报道重庆50万立方米的垃圾留在库区,这个报道并不正确,照片也用的是2003年的,这种做法是相当不负责任的。 探访“天字一号”崩岸现场 2月22日事发的那天早晨,当张国胜在例行的巡岸中发现华容县洪山头镇桩号25+430至27+280段的长江外洲发生崩岸的时候,他并不觉得惊讶也没有当成大事,因为崩岸对于素有“九曲回肠”的长江荆江河段来说实在是太平常了。 他似乎也不能理解,当“天字一号”河段和三峡工程这个充满了新闻关注度的字眼联系起来后,一切都会随之改变。 位于洪山头镇的“天字一号段”是长江干堤湖南段的起始之处。长江湖南段全长163公里,沿江有一线长江干堤142公里,都在岳阳境内。 记者来到现场时,张国胜正指挥抢险。虽然一直下着雨,但他并没有停下来的意思。他告诉记者,“冲得最深的地方大约有-28米。估计总共要抛7万多立方米的石头下去。” 水下抛石固脚是治理江河崩岸的一种有效措施。人们事先通过水下回声仪测量出水下地形,然后通过计算,用石块把崩岸地段从深泓到岸滩均匀抛成一定厚度的块石层,以增加其抗冲刷能力。岳阳长江修防处的总工程师胡世忠告诉记者:“天字一号段目前抢险工程已经完成了70%左右,预计5月中旬将全部完工。” 荆江段成崩岸重灾区 崩岸顾名思义是河岸的坍塌,与珠江广州段堤岸与江水直接相拍不同,长江大堤下并不是直接的江水,而是一片沙洲,专业人士称为“外滩”。崩岸发生的地点就是“外滩”与江水相连的部位,简单理解为江岸。从现场看,坍塌的江岸大约有600多米长,最宽的地方有10多米,目前仍留有明显裂缝,几棵种在外围的意杨树也随着坍塌的岸斜向江边。这些沙洲一头连着江水一头又连着长江大堤,如果险情不控制的话,崩岸就会加剧,从而威胁到长江大堤。 胡世忠告诉记者,在1998年国家大规模治理长江大堤后,岳阳段干堤一直状况良好,但这几年特别是2002年后长江岳阳段的崩岸现象趋于严重,今年的情况是比较严重的,目前统计到总共有6处发生崩岸险情,集中在华容县天字一号河段、新沙洲河段、洪水港河段、荆江门河段等河段。 胡世忠分析强烈崩岸是多种因素造成的,特别是三峡工程初期蓄水后,清水下泄,下泄江水泥沙含量下降导致挟沙能力增强,对下荆江河床冲刷严重,此外,河道加宽工程,在消除表层黏土后,也使河岸抗冲能力减弱,崩岸加剧。 而现场的水利工作人员似乎都已经对崩岸见怪不怪了,他们告诉记者在荆江河段每年都会发生崩岸。一位老水利人员让记者踩一踩沙洲,记者发现踩在沙洲上松松软软的,鞋子上立即沾上了很多细沙。他告诉记者:“长江中荆江河段最容易发生崩岸,因为荆江河段分布着广而厚的疏松沉积物,现在的河道就是发育在这些沉积物上的。沉积物疏松易冲,最年轻的沙洲形成不过几十年,在这种情况下清水冲刷加剧,河势恶化,就会接连发生崩岸险情。而长江其他河段一般都是土岸,不容易产生冲刷。”文/图记者邱敏


阅读全文(3193) | 回复(0) | 编辑 | 精华 | 删除
 


100以内常用端口含义
软件技术

fermos的博客 发表于 2005/9/18 11:38:22

100以内常用端口含义 1 tcpmux TCP Port Service Multiplexer  传输控制协议端口服务多路开关选择器 2 compressnet Management Utility     compressnet 管理实用程序 3 compressnet Compression Process    压缩进程 5 rje Remote Job Entry          远程作业登录 7 echo Echo               回显 9 discard Discard            丢弃 11 systat Active Users          在线用户 13 daytime Daytime            时间 17 qotd Quote of the Day         每日引用 18 msp Message Send Protocol       消息发送协议 19 chargen Character Generator      字符发生器 20 ftp-data File Transfer [Default Data] 文件传输协议(默认数据口)  21 ftp File Transfer [Control]      文件传输协议(控制) 22 ssh SSH Remote Login Protocol     SSH远程登录协议 23 telnet Telnet             终端仿真协议 24 ? any private mail system       预留给个人用邮件系统 25 smtp Simple Mail Transfer       简单邮件发送协议 27 nsw-fe NSW User System FE       NSW 用户系统现场工程师 29 msg-icp MSG ICP            MSG ICP 31 msg-auth MSG Authentication      MSG验证 33 dsp Display Support Protocol     显示支持协议 35 ? any private printer server     预留给个人打印机服务 37 time Time               时间 38 rap Route Access Protocol       路由访问协议 39 rlp Resource Location Protocol    资源定位协议 41 graphics Graphics           图形 42 nameserver WINS Host Name Server   WINS 主机名服务 43 nicname Who Is            "绰号" who is服务 44 mpm-flags MPM FLAGS Protocol     MPM(消息处理模块)标志协议 45 mpm Message Processing Module [recv] 消息处理模块  46 mpm-snd MPM [default send]      消息处理模块(默认发送口) 47 ni-ftp NI FTP             NI FTP 48 auditd Digital Audit Daemon      数码音频后台服务  49 tacacs Login Host Protocol (TACACS)  TACACS登录主机协议 50 re-mail-ck Remote Mail Checking Protocol 远程邮件检查协议 51 la-maint IMP Logical Address Maintenance IMP(接口信息处理机)逻辑地址维护 52 xns-time XNS Time Protocol      施乐网络服务系统时间协议   53 domain Domain Name Server       域名服务器 54 xns-ch XNS Clearinghouse       施乐网络服务系统票据交换 55 isi-gl ISI Graphics Language     ISI图形语言 56 xns-auth XNS Authentication      施乐网络服务系统验证 57 ? any private terminal access     预留个人用终端访问 58 xns-mail XNS Mail           施乐网络服务系统邮件 59 ? any private file service      预留个人文件服务 60 ? Unassigned             未定义 61 ni-mail NI MAIL            NI邮件? 62 acas ACA Services           异步通讯适配器服务 63 whois+ whois+              WHOIS+ 64 covia Communications Integrator (CI) 通讯接口  65 tacacs-ds TACACS-Database Service   TACACS数据库服务 66 sql*net Oracle SQL*NET        Oracle SQL*NET 67 bootps Bootstrap Protocol Server   引导程序协议服务端 68 bootpc Bootstrap Protocol Client   引导程序协议客户端 69 tftp Trivial File Transfer      小型文件传输协议 70 gopher Gopher             信息检索协议 71 netrjs-1 Remote Job Service      远程作业服务 72 netrjs-2 Remote Job Service      远程作业服务 73 netrjs-3 Remote Job Service      远程作业服务 74 netrjs-4 Remote Job Service      远程作业服务 75 ? any private dial out service    预留给个人拨出服务 76 deos Distributed External Object Store 分布式外部对象存储  77 ? any private RJE service      预留给个人远程作业输入服务 78 vettcp vettcp             修正TCP? 79 finger Finger            FINGER(查询远程主机在线用户等信息) 80 http World Wide Web HTTP       全球信息网超文本传输协议 81 hosts2-ns HOSTS2 Name Server     HOST2名称服务 82 xfer XFER Utility           传输实用程序 83 mit-ml-dev MIT ML Device       模块化智能终端ML设备 84 ctf Common Trace Facility       公用追踪设备 85 mit-ml-dev MIT ML Device       模块化智能终端ML设备 86 mfcobol Micro Focus Cobol       Micro Focus Cobol编程语言 87 ? any private terminal link      预留给个人终端连接 88 kerberos Kerberos           Kerberros安全认证系统 89 su-mit-tg SU/MIT Telnet Gateway    SU/MIT终端仿真网关 90 dnsix DNSIX Securit Attribute Token Map DNSIX 安全属性标记图  91 mit-dov MIT Dover Spooler       MIT Dover假脱机 92 npp Network Printing Protocol     网络打印协议 93 dcp Device Control Protocol      设备控制协议 94 objcall Tivoli Object Dispatcher   Tivoli对象调度 95 supdup SUPDUP             96 dixie DIXIE Protocol Specification  DIXIE协议规范 97 swift-rvf Swift Remote Virtural File Protocol 快速远程虚拟文件协议  98 tacnews TAC News           TAC(东京大学自动计算机?)新闻协议 99 metagram Metagram Relay        100 newacct [unauthorized use]


阅读全文(5665) | 回复(0) | 编辑 | 精华 | 删除
 


今年9.18,你要中秋还是“九·一八”纪念?
新闻动态

fermos的博客 发表于 2005/9/18 11:32:34

[胡说狐言]今年9.18,你要中秋还是“九·一八”纪念?
随笔,  生活百科 同事闲聊,说起今年的中秋是9.18,也是“九·一八”事变74年纪念日,那么应该是过中秋呢?还是纪念9.18? 对个人来说,我认为二者不矛盾,中秋要过,9.18也不要忘记。最好能够在团圆的时刻能够念起和平来之不易,不要忘记东夷倭寇的窥吞之野心,记得告慰先烈众灵...... 对于社会来说,我更倾向于重在9.18,中秋之事不用宣传,人人自知思乡年家,而社会更应该于此时宣昔日之耻,“忘记历史就是背叛”,背叛昨天也许意味着明天的失去...... 中秋夜,我们一起纪念9.18,举杯慰先灵,撒酒誓忠诚。
中秋夜,我们一起纪念9.18,记得“打倒日本侵略和殖民主义”......

阅读全文(9363) | 回复(4) | 编辑 | 精华 | 删除
 


世界最经典的10句话
休闲娱乐

fermos的博客 发表于 2005/9/18 11:30:33

   世界最经典的10句话
发表:2005-1-13 20:18:43  出处:你的博客网(yourblog.org) 1,1 ,记住该记住的,忘记该忘记的。改变能改变的,接受不能改变的
screen.width-468)this.width=screen.width-468" border=0 dypop="点击查看原图片">
     2 , 记住该记住的,忘记该忘记的。改变能改变的,接受不能改变的
screen.width-468)this.width=screen.width-468" border=0>
2, 能冲刷一切的除了眼泪,就是时间,以时间来推移感情,时间越长,冲突越淡,仿佛不断稀释的茶
screen.width-468)this.width=screen.width-468" border=0>
3, 怨言是上天得至人类最大的供物,也是人类祷告中最真诚的部分
screen.width-468)this.width=screen.width-468" border=0>
4, 智慧的代价是矛盾。这是人生对人生观开的玩笑
screen.width-468)this.width=screen.width-468" border=0>
5, 世上的姑娘总以为自己是骄傲的公主(除了少数极丑和少数极聪明的姑娘例外)
screen.width-468)this.width=screen.width-468" border=0>
6, 如果敌人让你生气,那说明你还没有胜他的把握
screen.width-468)this.width=screen.width-468" border=0>
7, 如果朋友让你生气,那说明你仍然在意他的友情
screen.width-468)this.width=screen.width-468" border=0>
8, 令狐冲说“有些事情本身我们无法控制,只好控制自己。
screen.width-468)this.width=screen.width-468" border=0>
9, 我不知道我现在做的哪些是对的,那些是错的,而当我终于老死的时候我才知道这些。所以我现在所能做的就是尽力做好每一件事,然后等待着老死。
screen.width-468)this.width=screen.width-468" border=0>
10,也许有些人很可恶,有些人很卑鄙。而当我设身为他想象的时候,我才知道:他比我还可怜。所以请原谅所有你见过的人,好人或者坏人
screen.width-468)this.width=screen.width-468" border=0 dypop="点击查看原图片">

阅读全文(4040) | 回复(0) | 编辑 | 精华 | 删除
 


溧水秦源网论坛 → 网络资源共享版块 → 精品软件交流下载区
软件技术

fermos的博客 发表于 2005/9/14 9:13:08

  ├精品软件交流下载区
  ├FTP资源共享区
  ├网络PC游戏讨论区
收藏本页
联系我们
论坛帮助   var tmenu='恢复默认设置' 登录 注册 搜索 风格 论坛状态 论坛展区 回到首页 我能做什么
>> 来源网络中最新、最好、最经典的软件,你发现好的软件了么?告诉大家吧。 溧水秦源网论坛 → 网络资源共享版块 → 精品软件交流下载区 → 帖子列表
当前没有公告() 总在线3人,其中精品软件交流下载区上共有 0 位会员与 2 位客人。今日贴子 28 [显示详细列表]
var ShowTools = new Array(); ShowTools[1]='转让器';ShowTools[2]='后悔药';ShowTools[3]='一级特赦令';ShowTools[4]='二级特赦令';ShowTools[5]='三级特赦令';ShowTools[6]='吖噗鸡';ShowTools[7]='醒目灯';ShowTools[8]='水晶球';ShowTools[9]='追踪器';ShowTools[10]='一星龙珠';ShowTools[11]='二星龙珠';ShowTools[12]='狗仔队';ShowTools[13]='救生圈';ShowTools[14]='大救生圈';ShowTools[15]='时空转移机';ShowTools[16]='照妖镜';ShowTools[17]='晶体探测器';ShowTools[18]='精灵弓';ShowTools[19]='水之母';ShowTools[20]='转生之炎';ShowTools[21]='群发器';ShowTools[22]='偷窥器';ShowTools[23]='查税卡';ShowTools[24]='均富卡';ShowTools[25]='均贫卡';ShowTools[26]='抢夺卡';ShowTools[27]='复仇卡';             XML   RSS 2.0   WAP  精华 | 在线 | 事件 | 权限 | 管理  版主: 状态 主 题 (点 即可展开贴子列表) 作 者 回复 人气 最后更新  秦源信息发布规则 站长 0 3  2005-9-9 20:47:24 | 站长  溧水秦源论坛说明(新手必读) 站长 0 6  2005-9-9 20:37:10 | 站长   21款绿色软件下载★超好用个个★★★★★ 站长 0 3  2005-9-14 8:22:46 | 站长   [9.14]免费破解软件发布 站长 1 6  2005-9-14 8:21:42 | 站长   【09-14】【9-14】【分享】精品软件下载更新 站长 3 4  2005-9-14 8:07:22 | 站长   【下载】【中科精品】9月14日更新23款破软件,非款款精品 站长 1 3  2005-9-14 8:04:29 | 站长   让你使用电脑后不留任何痕迹,不留任何证据的软件!网络公安绝对拿你没办法。 站长 0 0  2005-9-14 9:05:05 | 站长  【09-14】[9月14日]金山快译2006 绿色精简免激活版 5.0.0.0(大小1.5M) 站长 0 0  2005-9-14 9:03:29 | 站长   【09-14】[9月14日]BitComet Acceleratorv3.0(加速器)绿色汉化版 站长 0 0  2005-9-14 9:02:25 | 站长   ACDSee 8.0 Build 39 烈火汉化注册版 站长 0 0  2005-9-14 9:01:35 | 站长  Windows化大师升级为6.82 Build 5.913-原注册机可用,不要轻信谣言 站长 0 0  2005-9-14 9:00:43 | 站长  木马杀客5.1注册版,决不次于木马克星! 站长 0 0  2005-9-14 8:59:45 | 站长  【9月14日】 注册、破解精品软件更新[国外软件] 站长 1 3  2005-9-14 8:37:20 | 站长  火狐Flash播放器 v3.11 注册码 站长 0 1  2005-9-14 8:35:51 | 站长  正版阿达连连看2005 V5.05注册码 站长 0 1  2005-9-14 8:34:59 | 站长  XP变脸王 6.X通用注册码 站长 0 1  2005-9-14 8:34:34 | 站长   FlashFXP 3.3.1 build 1089 Beta 简体中文版 ,含注册码 站长 0 1  2005-9-14 8:33:48 | 站长   ACDSee V8.0 注册机 站长 0 1  2005-9-14 8:32:58 | 站长  最新版本金山毒霸免序列号升级+破解补丁 站长 0 1  2005-9-14 8:32:14 | 站长  火狐Flash播放器 V3.18 原版及破解补丁(最新版) 站长 0 1  2005-9-14 8:31:25 | 站长   XP变脸王 6.83 的破解版,太爽了!斑竹支持啊 站长 0 0  2005-9-14 8:30:02 | 站长  [分享]一个下载小说电子书的好地方 (N多精品下载) 站长 0 1  2005-9-14 8:29:12 | 站长  一款软件帮助你把浏览器的速度提升到原来的300%,强!!! 站长 0 1  2005-9-14 8:28:27 | 站长   E阳网络电视VIP版 8.11 完美破解版,经典!!! 站长 0 1  2005-9-14 8:27:28 | 站长     
 

阅读全文(5581) | 回复(0) | 编辑 | 精华 | 删除
 


编程联盟
电脑与网络

fermos的博客 发表于 2005/9/14 9:04:54

本站首页 技术文章 精品控件 电子书库 源码示例 编程论坛     收藏本站 用户联系 精 品 控 件   系统控件 控 件 包 数 据 库 时间控件 媒体控件 界面控件 网络控件 图表控件 图象控件 压缩控件 文件控件 其它控件     时间控件 下一页   控件名称:Advanced Clock Control
控件授权:共享软件
适用工具:
控件开发:HomePage
控件简介:高级的时钟OCX控件。
控件名称:AMCLOCK
控件授权:免费软件
适用工具:
控件开发:HomePage
控件简介:TAMClock是指针类型的时钟控件,可自定时针的色彩并能载入BMP、WMF等图档为钟面。
控件名称:AVDATEFR
控件授权:免费软件
适用工具:
控件开发:HomePage
控件简介:专门输入日期的改良版的TEdit构件,能够出现月历供使用者挑选日期,并可变化月历外观。
控件名称:BCCALEN
控件授权:免费软件
适用工具:
控件开发:HomePage
控件简介:改良版的月历控件,可以将星期日等假日以不同色彩或字体标示。
控件名称:BSCAL
控件授权:免费软件
适用工具:
控件开发:HomePage
控件简介:一个加强版的月历构件,能够更方便的选取日期。
控件名称:BSTYEARCAL
控件授权:免费软件
适用工具:
控件开发:HomePage
控件简介:一次显示一年十二个月的年历控件。
控件名称:Calendar Control
控件授权:共享软件
适用工具:
控件开发:HomePage
控件简介:高级的日历OCX控件。
控件名称:Cncalc
控件授权:免费软件
适用工具:
控件开发:HomePage
控件简介:一个农历日期的VCL控件。
控件名称:DATEPICK
控件授权:免费软件
适用工具:
控件开发:HomePage
控件简介:是TDateTimePicker样式的月历控件。
控件名称:DCCALEND
控件授权:免费软件
适用工具:
控件开发:HomePage
控件简介:改良版的TCalendar控件,能够选取一的时间区段,并能够与TEdit控件搭配使用。
下一页       编程联盟 版权所有 © 2000  All rights reserved.
建站日期  2000.2.1

阅读全文(4571) | 回复(0) | 编辑 | 精华 | 删除
 


名副其实的爆笑贴图
休闲娱乐

fermos的博客 发表于 2005/9/9 10:21:39

    [首页] [上页] [下页] [尾页] 共 24 帖 1/1 每页 50 帖转到第 页 楼主 主题:名副其实的爆笑贴图--- [回复] [树状] 绿幽灵的夏 document.write(ShowAvatar("","0|0|0|0|1|1|1|1|0|1|0|0|1|0|0|0|1|0|0|0|0|0|0|0|0|0")); 账户充值|更换服饰 作者:绿幽灵的夏 --> 发表时间: 2005-09-06 13:48:22 看我的嘴,就知道我练的是美声唱法! render() 1楼 主题:哈哈,这哥们干吗呢! [回复] [树状] 绿幽灵的夏 document.write(ShowAvatar("","0|0|0|0|1|1|1|1|0|1|0|0|1|0|0|0|1|0|0|0|0|0|0|0|0|0")); 账户充值|更换服饰 作者:绿幽灵的夏 --> 发表时间: 2005-09-06 13:52:56 哈哈,这哥们干吗呢! render() 2楼 主题:换了一口气 [回复] [树状] 绿幽灵的夏 document.write(ShowAvatar("","0|0|0|0|1|1|1|1|0|1|0|0|1|0|0|0|1|0|0|0|0|0|0|0|0|0")); 账户充值|更换服饰 作者:绿幽灵的夏 --> 发表时间: 2005-09-06 13:53:15 换了一口气 render() 3楼 主题:原来打网球可以不穿内裤 [回复] [树状] 绿幽灵的夏 document.write(ShowAvatar("","0|0|0|0|1|1|1|1|0|1|0|0|1|0|0|0|1|0|0|0|0|0|0|0|0|0"));
阅读全文(5909) | 回复(0) | 编辑 | 精华 | 删除
 


爆笑
休闲娱乐

fermos的博客 发表于 2005/9/9 9:31:22

sina.com.cn 首页 | 新闻 | 体育 | 娱乐 | 游戏 | 邮箱 | 短信 | 聊天 | 天气 | 答疑 | 导航 function checkiask() { if (document._searchiask.k.value=="请输入关键词" || document._searchiask.k.value=="" ) { window.open("http://iask.com"); return false; } return true; } 爱问(iAsk.com) 笑话论坛 文化艺术 新浪首页 > 论坛首页 > 文化艺术 > 笑话论坛 新浪论坛-你的地盘 论坛热贴排行榜 精彩贴图大汇总 【斑竹招募】

新浪热帖: □父亲的挣扎:为了孩子不成为废品    ■儿童不宜的两性笑话
      ■警察枪口对着谁 受灾新奥尔良混乱不堪 □全世界最健康的菜单
      □感人至深:18年以来父亲的秘密象座山  ■十八禁动画排行榜
      ■泰坦尼克号揭秘:运送神秘木乃伊遭厄运 □超强的性暗示广告(组图)
      □烫手的补助:贫困生有用手机的权利吗  ■中国足球技术球员TOP25 | 精品文章 | 48小时热门贴 版主:绿幽灵的夏 w1987513 雪山上的松 按主题按作者按内容按发贴日期   树 状 发 贴 刷 新 主帖:4177 可见:1144  [首页]  [上页]  [下页]  [尾页]  1/12转到第 页   主题 作者 发贴时间 回复/点击 最后回复人 autowidth() [顶][图] 爆笑图库,近期网上最搞笑的图库集---- <158字节>[精] 草原真牛 08-24 14:59 51/100197 草原真牛 render() [顶][图] 爆笑图片接龙:偷情的最好地点 <0字节>[精] 小猪无邪 08-23 18:03 23/608336 wenchen1013 render() [顶] 史上最强的一帖---世界上最NB的人(惊人啊!!… <2932字节>[精] 我是镭29 08-23 16:22 66/29100 太极错 render() [顶] 女士请进--处男和非处男的区别(不看后悔!!) <256字节>[精] 我是镭29 08-23 13:50 56/482148 cclc_samon render() [顶] 点击率第一的最新成人暴笑贴 <275字节> 绿幽灵的夏 08-22 14:21 31/293467 mrdsp render() [顶] 变态鹦鹉笑话全集 <1118字节>[精] 绿幽灵的夏 08-21 13:38 31/108195 zylqjs render() [顶] 医学院学生之色色的事情!汗啊!! <541字节>[精] 绿幽灵的夏 08-19 11:04 22/457778 54snake render() [顶] 幽默荤笑话一网打尽:都是安全套惹的祸 <604字节>[精] ppa123 08-18 11:22 26/329714 hongch9 render() [顶] 给国语不标准的总经理---爆笑留言条大杂烩 <102字节>[精] 小笑99 08-12 10:01 29/81021 zccyz77 render() [顶] 本坛招募斑竹!机会多多不要错过! <321字节> 小呆 08-05 18:51 24/4337 家在三江源 render() [图] 脱光光 带出场--最新叫鸡行情(爆笑喷饭图) <0字节> 我是镭29 09-09 08:28 9/42 我是镭29 render() 办什么哭 <118字节> wangfang51888 09-09 09:03 0/0   render() [图] 名副其实的爆笑贴图--- <32字节> 绿幽灵的夏 09-06 13:48 37/310582 zsfazyzl render() 坚决不能让老婆知道的事 <1712字节> 家在三江源 09-08 23:29 0/82   render() 小偷都不敢要的手机 <1783字节> 家在三江源 09-08 23:28 0/79   render() 2005年高考中的广告词(超级爆笑) <1952字节> 家在三江源 09-08 18:34 7/260 家在三江源 render() 各色皇帝的N多个笑话 <450字节> 龙宝宝29 09-08 16:31 12/368 龙宝宝29 render() [图] 成人世界几何题 <20字节> 小笑99 09-06 12:17 29/273498 鹿丽丽丽丽 render() BT网名大全集 2005版超贱--女澡堂的男搓背工 <1582字节> 绿幽灵的夏 09-05 16:40 18/208590 lgs0777 render() 女生宿舍八卦卧谈会-- <162字节> 绿幽灵的夏 09-08 09:26 15/25583 cl3564841 render() 非常爆笑--杀蚂蚁的54种方法 <871字节> 卓玛的草原 09-07 16:03 5/3122 深水行 render() 网上美眉八大撒娇术 -------(网友们快看) <2494字节> 天涯海角5488801 09-08 18:36 0/217   render() “爽”字的来历 <182字节> 家在三江源 09-08 18:15 0/153   render() 李白的妻子和女儿已经被考证姓名 <185字节> 家在三江源 09-08 18:12 0/143   render() 女士千万不要穿低胸上衣上公车 <2519字节> 家在三江源 09-08 18:08 0/408   render() 军阀的四姨太吃一汤四菜 <997字节> 家在三江源 09-08 17:32 7/339 家在三江源 render() 强奸女人的整套工具 <449字节> 家在三江源 09-08 17:30 0/474   render() 最cool的短信集锦 <124字节> 卓玛的草原 09-07 14:13 20/93478 wyr_yc render() 对着喝 <410字节> 怪难 08-27 17:17 1/401 怪难 render() 周星驰八级统一试卷(绝密) <10378字节> 海星山顶 09-08 16:09 0/283   render() 搞笑鬼故事 <582字节> 绿幽灵的夏 09-02 08:51 27/61853 luizeying110 render() 把人活活气死的小侄女 <1389字节> 海星山顶 09-08 16:06 0/270   render() 克林顿……三陪小姐! <1272字节> 海星山顶 09-08 16:04 0/261   render() 如何表扬别人长得丑! <1250字节> 海星山顶 09-08 16:02 0/226   render() 一个女孩的月经论!(男孩必看) <2088字节> 海星山顶 09-08 16:01 0/364   render() 食堂里的超强MM <717字节> 海星山顶 09-08 15:59 0/250   render() 小女人老婆的“私房日记”! <1061字节> 海星山顶

阅读全文(5125) | 回复(0) | 编辑 | 精华 | 删除
 


windows网络编程经典入门
电脑与网络

fermos的博客 发表于 2005/9/8 8:21:19

新手必学:windows网络编程经典入门 http://www.pcdog.com 2004-12-4 太平洋电脑网 下一页 1 2 3 
  对于一个windows网络编程初学者,下面方法是经典入门。
  初学者建议不要用MFC提供的类,而用windows API做一个简单服务器和客户端,这样有助于对socket编程机制的理解。
  
  为了简单起见,应用程序是基于MFC的标准对话框。
  
  Winsock用WINDOWS API实现:
  
  (1)服务器端有两个线程:
  主线程 — 你需要编写以下函数来实现
  
  #define NETWORK_EVENT USER_MESSAGE+100 file://定义网络事件
  sockaddr_in clientaddr; file://暂时存放客户端IP地址
  
  file://自己定义消息映射函数,将上面定义的网络事件映射到处理函数
  file://OnNetEvent为网络事件处理函数,它在下面定义
  ON_MESSAGE(NETWORK_EVENT, OnNetEvent);
  
  在你对话框中的初始化函数中调用下面的初始化网络的子函数
  BOOL InitNetwork() file://初始化网络
  {
  file://初始化TCP协议
  BOOL ret = WSAStartup(MAKEWORD(2,2), &wsaData);
  if(ret != 0)
  {
  MessageBox("初始化套接字失败!");
  return FALSE;
  }
  
  file://创建服务器端套接字
  SOCKET serverSocket
  = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if(serverSocket == INVALID_SOCKET)
  {
  MessageBox("创建套接字失败!");
  closesocket(m_Socket);
  WSACleanup();
  return FALSE;
  }
  
  file://绑定到本地一个端口上
  sockaddr_in localaddr;
  localaddr.sin_family = AF_INET;
  localaddr.sin_port = htons(1688);
  localaddr.sin_addr.s_addr = 0;
  if(bind(serverSocket ,(const struct sockaddr*)&localaddr,
  sizeof(sockaddr)) == SOCKET_ERROR)
  {
  MessageBox("绑定地址失败!");
  closesocket(m_Socket);
  WSACleanup();
  return FALSE;
  }
  
  file://注册网络异步事件,m_hWnd为应用程序的主对话框或主窗口的句柄
  WSAAsyncSelect(serverSocket, m_hWnd, NETWORK_EVENT,
  FD_ACCEPT | FD_CLOSE | FD_READ | FD_WRITE);
  
  listen(serverSocket, 5); file://设置侦听模式
  
  return TRUE;
  }

  file://定义网络事件的响应函数
  void OnNetEvent(WPARAM wParam, LPARAM lParam)
  {
  file://调用API函数,得到网络事件类型
  int iEvent = WSAGETSELECTEVENT(lParam);
  
  file://得到发出此事件的客户端套接字
  SOCKET pSock = (SOCKET)wParam;
  switch(iEvent)
  {
  case FD_ACCEPT: file://客户端连接请求
  {
  OnAccept();
  
  break;
  }
  case FD_CLOSE: file://客户端断开事件:
  {
   OnClose(pSock);
  break;
  }
  case FD_READ: file://网络数据包到达事件
  {
  OnReceive(pSock);
  break;
  }
  case FD_WRITE: file://发送网络数据事件
  {
  OnSend(pSock);
  break;
  }
  default: break;
  }
  }
  
  void OnAccept(SOCET pSock) file://响应客户端连接请求函数
  {
  int len = sizeof(sockaddr);
  
  file://调用API函数,接受连接,并返回一个新套接字
  file://还可以获得客户端的IP地址
  SOCKET clientSocket = accept(serverSocket,
  (struct sockaddr*)&clientaddr, &len);
  
  file://为新的socket注册异步事件,注意没有Accept事件
  if(WSAAsyncSelect(clientSocket ,m_hWnd, IP_EVENT,
  FD_CLOSE | FD_READ | FD_WRITE) == SOCKET_ERROR)
  {
  MessageBox("注册异步事件失败!");
  return;
    }
  
  file://自编函数,将此客户端的相关信息保存下来:套接字、
  // IP地址、登陆时间
  saveClientSocket(clientSocket,clientAddr,currentTimer);
  }
  
  void OnClose(SOCET pSock)
  {
  file://自编函数,结束与相应的客户端的通信,释放相应资源并做相应处理
  endClientSocket(pSock);
  }
  
  void OnSend(SOCET pSock)
  {
  file://自编函数,在给客户端发数据时做一些预处理
  handleOnSend(pSock);
  }
  
  void OnReceive(SOCET pSock)
  {
  recv(...); file://调用API函数,读出网络缓冲区中的数据包
  
  file://自编函数,将此数据包和发出此数据的客户端
  file://clientSocket封装成一条网络消息
  buildNetMsg(...);
  
  file://自编函数,将此网络消息放入一个消息队列中,由工作线程去处理
  saveNetMsg(...);
  SetEvent(...); file://用事件对象触发工作线程
 }
  
  客户端登陆后,随即把自己的计算机名发给服务器,服务器接到后,把它保存下来。这样服务器就可以显示所有在线客户端的信息了,包括:客户端计算机名、IP地址、登陆时间等。
  
  注意: 客户端没有OnAccept()函数,但有OnConnect()函数。
  
  工作线程 —
  在你的应用程序初 始化时,创建并启动一个工作线程
  
  AfxBeginThread(WorkThread,this,THREAD_PRIORITY_NORMAL);
  file://this可能为应用程序的主对话框或主窗口的句柄
  
  UINT WorkThread(LPVOID pParam)
  {
  while(1)
  {
  file://等待多重事件到来
  int ret = WaitForMultipleObject(...);
  
  switch(ret)
  {
  case OBJECT_0:
  {
  if(bNewNetMsg) file://查看网络消息队列是否有新的网络消息
  {
  readNetMsg(...); file://如有新的网络消息,则读出
  handleNetMsg(...); file://处理此网络消息
  }
  break;
  }
  case OBJECT_0 + 1:
  {
  file://做退出处理
  break;
  }
  default: break;
  }
  
  return 0;
  }
  
  客户端为单线程,登陆服务器时,用connect()函数给服务器发连接请求;
  客户端没有OnAccept()函数,但有OnConnect()函数。
  在OnConnect()函数里做发连接请求时的预处理;
  在OnReceive()函数里响应并处理网络数据;
  在OnClose()函数里响应服务器的关闭事件;
  在OnSend()函数里做发数据时的预处理;
  
  如果你还想实现各客户端之间的在线交流(即所谓的聊天室),你在客户端还可以基于UDP协议
  再做一套多点对多点的局域网组播模型模型,以后在和你聊,你先把上面的程序实现。
  
  以上的I/O异步模型基于Windows的消息机制,另外还可以用事件模型、重叠模型或完成端口模型,
  建议你参考Windows网络编程指南之类的书。
  
  如果你能对上面的机制很熟练,你肯定已经对Winsock编网络程序的机制有一定理解,接下来你可以进行更精彩的编程, 不仅可以在网上传输普通数据,而且还
  以传输语音、视频数据,你还可以自己做一个聊天室,和你的同学在实验室的局域网里可以共同分享你的成果。

阅读全文(4569) | 回复(0) | 编辑 | 精华 | 删除
 


经典编程:DLL地狱及其解决方案
软件技术

fermos的博客 发表于 2005/9/8 8:16:56

经典编程:DLL地狱及其解决方案 http://www.pcdog.com 2004-12-4 csdn 下一页 1 2 3 4 
  原作者:Ivan S Zapreev
  
  译者:陆其明
  
  概要
  
  本文将要介绍DLL的向后兼容性问题,也就是著名的“DLL Hell”问题。首先我会列出自己的研究结果,其中包括其它一些研究者的成果。在本文的最后,我还将给出“DLL Hell”问题的一个解决方案。
  
  介绍
  
  我曾经接受过一个任务,去解决一个DLL版本更新的问题————某个公司给用户提供了一套SDK,这个SDK是由一系列DLL组成的;DLL中导出了很多类,用户使用这些类(直接使用或派生新的子类)来继续他们的C++程序开发。用户在使用这些DLL时没有得到很详细的使用说明(比如使用这些DLL中导出的类有什么限制等)。当这些DLL更新为新的版本之后,他们发现他们开发的基于这些DLL的应用程序会经常崩溃(他们的应用程序从SDK的导出类派生了新的子类)。为了解决这个问题,用户必须重新编译他们的应用程序,重新连接新版本的SDK DLL。
  
  我将对这个问题给出我的研究结果,同时还有我从其它地方搜集过来的相关信息。最后,我将来解决这个“DLL Hell”问题。
  
  研究结果
  
就我个人的理解,这个问题是由SDK DLL中导出的基类改动之后引起的。我查看了一些文章后发现,DLL的向后兼容性问题其实早有人提出。但作为一个实在的研究者,我决定自己做一些试验。结果,我发现如下的问题:
  
  1. 在DLL的导出类中增加一个新的虚函数将导致如下问题:
   (1)如果这个类以前就有一个虚函数B,此时在它之前增加一个新的虚函数A。这样,我们改变了类的虚函数表。于是,表中的第一个函数指向了函数A(而不是原来的B)。此时,客户程序(假设没有在拿到新版本的DLL之后重新编译、连接)调用函数B就会产生异常。因为此时调用函数B实际上转向了调用函数A,而如果函数A和函数B的参数类型、返回值类型迥异的话问题就出来了!
   (2)如果这个类原本没有虚函数(它的父类也没有虚函数),那么给这个类增加一个新的虚函数(或者在它的父类增加一个虚函数)将导致新增加一个类成员,这个成员是一个指针类型的,指向虚函数表。于是,这个类的尺寸将会被改变(因为增加了一个成员变量)。这种情况下,客户程序如果创建了这个类的实例,并且需要直接或间接修改类成员的值的时候就会有问题了。因为虚函数表的指针是作为类的第一个成员加入的,也就是说,原本这个类定义的成员因为虚函数表指针的加入而都产生了地址的偏移。客户程序对原成员的操作自然就出现异常了。
   (3)如果这个类原本就有虚函数(或者只要它的父类有虚函数),而且这个类被导出了,被客户程序当作父类来用。那么,我们不要给这个类增加虚函数!不仅在类声明的开头不能加,即使在末尾处也不能加。因为加入虚函数会导致虚函数表内的函数映射产生偏移;即使你将虚函数加在类声明的末尾,这个类的派生类的虚函数表也会因此产生偏移。
  
  2. 在DLL的导出类中增加一个新的成员变量将导致如下问题:
   (1)给一个类增加一个成员变量将导致类尺寸的改变(给原本有虚函数表的类增加一个虚函数将不会改变类的尺寸)。假设这个成员增加在类声明的最后。如果客户程序为创建这个类的实例少分配了内存,那么可能在访问这个成员时导致内存越界。
   (2)如果在原有的类成员中间增加一个新的成员,情况会更糟糕。因为这样会导致原有类成员的地址产生偏移。客户程序操作的是一个错误的地址表,对于新成员后面的成员尤其是这样(它们都因为新成员的加入而导致了自己在类中的偏移的变化)。
  
  (注:上述的客户程序就是指使用SDK DLL的应用程序。)
  
  除了上面这些原因外,还有其它操作会导致DLL的向后兼容性问题。下面列出了解决(大部分)这些问题的方法。
  
  DLL编码约定简述
  
  下面是我搜集到的所有的解决方案,其中一些是从网上的文章中拿来的,一些是跟不同的开发者交流后得到的。
  
  下面的约定主要针对DLL开发,而且是为解决DLL的向后兼容性问题:
  
  1. 编码约定:
   (1)DLL的每个导出类(或者它的父类)至少包含一个虚函数。这样,这个类就会始终保存一个指向虚函数表的指针成员。这么做可以方便后来新的虚函数的加入。
   (2)如果你要给一个类增加一个虚函数,那么将它加在所有其它虚函数的后面。这样就不会改变虚函数表中原有函数的地址映射顺序。
   (3)如果你打算以后给一个类扩充类成员,那么现在预留一个指向一个数据结构的指针。这样的话,增加一个成员直接在这个数据结构中修改,而不是在类中修改。于是,新成员的加入不会导致类尺寸的改变。当然,为了访问新成员,需要给这个类定义几个操作函数。这种情况下,DLL必须是被客户程序隐式(implicitly)连接的。
   (4)为了解决前一点的问题,也可以给所有的导出类设计一个纯接口的类,但此时,客户程序将无法从这些导出类继续派生,DLL导出类的层次机构也将无法维持。
   (5)发布两个版本的DLL和LIB文件(Debug版本和Release版本)。因为如果只发布Release版本,开发者将无法调试他们的程序,因为Release版与Debug版使用了不同的堆(Heap)管理器,因而当Debug版本的客户程序释放Release版本DLL申请的内存时,会导致运行时错误(Runtime failure)。有一种办法可以解决这个问题,就是DLL同 时提供申请和释放内存的函数供客户程序调用;DLL中也保证不释放客户程序申请的内容。通常遵守这个约定不是那么简单!
   (6)在编译的时候,不要改变DLL导出类函数的默认参数,如果这些参数将被传递到客户程序的话。
   (7)注意内联(inline)函数的更改。
   (8)检查所有的枚举没有默认的元素值。因为当增加/删除一个新的枚举成员,你可能移动旧枚举成员的值。这就是为什么每一个成员应该拥有一个唯一标识值。如果枚举可以被扩展,也应该对其进行文档说明。这样,客户程序开发者就会引起注意。
   (9)不要改变DLL提供的头文件中定义的宏。
  
  2. 对DLL进行版本控制:如果主要的DLL发生了改变,最好同时将DLL文件的名字也改掉,就象微软的MFC DLL一样。例如,DLL文件可以按照如下格式命名:Dll_name_xx.dll,其中xx就是DLL的版本号。有时候DLL中做了很大的改动,使得向后兼容性问题无法解决。此时应该生成一个全新的DLL。将这个新DLL安装到系统时,旧的DLL仍然保留。于是,旧的客户程序仍然能够使用旧的DLL,而新的客户程序(使用新DLL编译、连接)可以使用新的DLL,两者互不干涉。
  
  3. DLL的向后兼容性测试:还有很多很多中可能会破坏DLL的向后兼容性,因此实施DLL的向后兼容性测试是非常必要的!
  
  接下去,我将来讨论一个虚函数的问题,以及对应的一个解决方案。
  
  虚函数与继承
  
  首先来看一下如下的虚函数和继承结构:
  
  /**********DLL导出的类 **********/
  class EXPORT_DLL_PREFIX VirtFunctClass{
  public:
   VirtFunctClass(){}
   ~VirtFunctClass(){}
   virtual void DoSmth(){
   //this->DoAnything();
   // Uncomment of this line after the corresponding method
   //will be added to the class declaration
   }
   //virtual void DoAnything(){}
   // Adding of this virtual method will make shift in
   // table of virtual methods
  };
  
  /**********客户程序,从DLL导出类派生一个新的子类**********/
  class VirtFunctClassChild : public VirtFunctClass {
  public:
   VirtFunctClassChild() : VirtFunctClass (){}
   ~VirtFunctClassChild(){};
   virtual void DoSomething(){}
  };
  
  假设上面的两个类,VirtFunctClass在my.dll中实现,而VirtFunctClassChild在客户程序中实现。接下去,我们做一些改变,将如下两个注释行放开:
  //virtual void DoAnything(){}
  和
  //this->DoAnything();
  
  也就是说,DLL导出的类作了改动!现在如果客户程序没有重新编译,那么客户程序中的VirtFunctClassChild将不知道DLL中VirtFunctClass类已经改变了:增加了一个虚函数void DoAnything()。因此,VirtFunctClassChild类的虚函数表仍然包含两个函数的映射:
  1. void DoSmth()
  2. void DoSomething()
  
  而事实上这已经不对了,正确的虚函数表应该是:
  1. void DoSmth()
  2. void DoAnything()
  3. void DoSomething()
  
  问题就在于,当实例化VirtFunctClassChild之后,如果调用它的void DoSmth()函数,DoSmth()函数转而要调用void DoAnything()函数,但此时基类VirtFunctClass只知道要调用虚函数表中的第二个函数,而VirtFunctClassChild类的虚函数表中的第二个函数仍然是void DoSomething(),于是问题就出来了!
  
  另外,禁止在DLL的导出类的派生类(上例中的VirtFunctClassChild)中增加虚函数也是于事无补的。因为,如果VirtFunctClassChild类中没有virtual void DoSomething()函数,基类中的void DoAnything()函数(虚函数表中的第二个函数)调用将会指向一个空的内存地址(因为VirtFunctClassChild类维持的虚函数表仅仅维持有一个函数地址)。   现在可以看出,在DLL的导出类中增加虚函数是一个多么严重的问题!不过,如果虚函数是用来处理回调事件的,我们有办法来解决这个问题(下文有介绍)。
  
  COM及其它
  
  现在可以看出,DLL的向后兼容性问题是一个很出名的问题。解决这些问题,不仅可以借助于一些约定,而且可以通过其它一些先进的技术,比如COM技术。因此,如果你想摆脱“ DLL Hell”问题,请使用COM技术或者其它一些合适的技术。
  
  让我们回到我接受的那个任务(我在本文开头的地方讲到的那个任务)————解决一个使用DLL的产品的向后兼容性问题。
  
  我对COM有些了解,因此我的第一个建议是使用COM技术来克服那个项目中的所有问题。但这个建议因为如下原因最终被否决了:
  1. 那个产品已经在某个内部层中有一个COM服务器。
  2. 将一大堆接口类重写到COM的形式,投入比较大。
  3. 因为那个产品是DLL库,而且已经有很多应用程序在使用它了。因此,他们不想强制他们的客户重写他们的应用程序。
  
  换句话说,我被要求完成的任务是,以最小的代价来解决这个DLL向后兼容性问题。当然,我应该指出,这个项目最主要的问题在于增加新的成员和接口类上的虚回调函数。第一个问题可以简单地通过在类声明中增加一个指向一个数据结构的指针来解决(这样可以任意增加新的成员)。这种方法我在上面已经提到过。但是第二个问题,虚回调函数的问题是新提出的。因此,我提出了下面的最小代价、最有效的解决方法。
  
  虚回调函数与继承
  
  然我们想象一下,我们有一个DLL,它导出了几个类;客户应用程序会从这些导出类派生新的类,以实现虚函数来处理回调事件。我们想在DLL中做一个很小的改动。这个改动允许我们将来可以给导出类“无痛地”增加新的虚回调函数。同时,我们也不想影响使用当前版本DLL的应用程序。我们期望的就是,这些应用程序只有在不得已的时候才协同新版本的DLL进行一次重新编译。因此,我给出了下面的解决方案:
  
  我们可以保留DLL导出类中的每个虚回调函数。我们只需记住,在任何一个类定义中增加一个新的虚函数,如果应用程序不协同新版本的DLL重新编译,将导致严重的问题。我们所做的,就是想要避免这个问题。这里我们可以一个“监听”机制。如果在DLL导出类中定义并导出的虚函数被用作处理回调,我们可以将这些虚函数转移到独立的接口中去。
  
  让我们来看下面的例子:
  
  // 如果想要测试改动过的DLL,请将下面的定义放开
  //#define DLL_EXAMPLE_MODIFIED
  
  #ifdef DLL_EXPORT
   #define DLL_PREFIX __declspec(dllexport)
  #else
   #define DLL_PREFIX __declspec(dllimport)
  #endif
  
  /********** DLL的导出类 **********/
  #define CLASS_UIID_DEF static short GetClassUIID(){return 0;}
  #define OBJECT_UIID_DEF virtual short
   GetObjectUIID(){return this->GetClassUIID();}
  
  // 所有回调处理的基本接口
  struct DLL_PREFIX ICallBack
  {
   CLASS_UIID_DEF
   OBJECT_UIID_DEF
  };
  
  #undef CLASS_UIID_DEF
  
  #define CLASS_UIID_DEF(X) public: static
   short GetClassUIID(){return X::GetClassUIID()+1;}
  
  // 仅当DLL_EXAMPLE_MODIFIED宏已经定义的时候,进行接口扩展
  #if defined(DLL_EXAMPLE_MODIFIED)
  // 新增加的接口扩展
  struct DLL_PREFIX ICallBack01 : public ICallBack
  {
   CLASS_UIID_DEF(ICallBack)
   OBJECT_UIID_DEF
   virtual void DoCallBack01(int event) = 0; // 新的回调函数
  };
  #endif // defined(DLL_EXAMPLE_MODIFIED)
  
  class DLL_PREFIX CExample{
  public:
   CExample(){mpHandler = 0;}
   virtual ~CExample(){}
   virtual void DoCallBack(int event) = 0;
   ICallBack * SetCallBackHandler(ICallBack *handler);
   void Run();
  private:
   ICallBack * mpHandler;
  };
  
  很显然,为了给扩展DLL的导出类(增加新的虚函数)提供方便,我们必须做如下工作:
  1. 增加ICallBack * SetCallBackHandler(ICallBack *handler);函数;
  2. 在每个导出类的定义中增加相应的指针;
  3. 定义3个宏;
  4. 定义一个通用的ICallBack接口。
  
  为了演示给CExample类增加新的虚回调函数,我在这里增加了一个ICallBack01接口的定义。很显然,新的虚回调函数应该加在新的接口中。每次DLL更新都新增一个接口(当然,每次DLL更新时,我们也可以给一个类同时增加多个虚回调函数)。
  
  注意,每个新接口必须从上一个版本的接口继承。在我的例子中,我只定义了一个扩展接口ICallBack01。如果DLL再下个版本还要增加新的虚回调函数,我们可以在定义一个ICallBack02接口,注意ICallBack02接口要从ICallBack01接口派生,就跟当初ICallBack01接口是从ICallBack接口派生的一样。
  
  上面代码中还定义了几个宏,用于定义需要检查接口版本的函数。例如我们要为新接口ICallBack01增加新函数DoCallBack01,如果我们要调用ICallBack * mpHandler; 成员的话,就应该在CExample类进行一下检查。这个检查应该如下实现:
  
  if(mpHandler != NULL && mpHandler->GetObjectUIID()>=ICallBack01::GetClassUIID()){
   ((ICallBack01 *) mpHandler)->DoCallBack01(2);
  }
  
  我们看到,新回调接口增加之后,在CExample类的实现中只需简单地插入新的回调调用。
  
  现在你可以看出,我们上述对DLL的改动并不会影响客户应用程序。唯一需要做的,只是在采用这种新设计后的第一个DLL版本(为DLL导出类增加了宏定义、回调基本接口ICallBack、设置回调处理的SetCallBackHandler函数,以及ICallBack接口的指针)发布后,应用程序进行一次重编译。(以后扩展新的回调接口,应用程序的重新编译不是必需的!)
  
  以后如果有人想要增加新的回调处理,他就可以通过增加新接口的方式来实现(向上例中我们增加ICallBack01一样)。显然,这种改动不会引起任何问题,因为虚函数的顺序并没有改变。因此应用程序仍然以以前的方式运行。唯一你要注意的是,除非你在应用程序中实现了新的接口,否则你就接收不到新增加的回调调用。
  
  我们应该注意到,DLL的用户仍然能够很容易与它协同工作。下面是客户程序中的某个类的实现例子:
  
  // 如果DLL_EXAMPLE_MODIFIED没有定义,使用以前版本的DLL
  #if !defined(DLL_EXAMPLE_MODIFIED)
  // 此时没有使用扩展接口ICallBack01
  class CClient : public CExample{
  public:
   CClient();
   void DoCallBack(int event);
  };
  
  #else // !defined(DLL_EXAMPLE_MODIFIED)
  // 当DLL增加了新接口ICallBack01后,客户程序可以修改自己的类
  // (但不是必须的,如果他不想处理新的回调事件的话)
  class CClient : public CExample, public ICallBack01{
  public:
   CClient();
   void DoCallBack(int event);
  
   // 声明DoCallBack01函数(客户程序要实现它,以处理新的回调事件)
   // (DoCallBack01是ICallBack01接口新增加的虚函数)
   void DoCallBack01(int event);
  };
  #endif // defined(DLL_EXAMPLE_MODIFIED)
  
  例程 ---> 代码下载(6.26K)
  
  与本文的内容配套,我提供了演示程序Dll_Hell_Solution。
  
  1. Dll_example: DLL的实现项目;
  2. Dll_Client_example: DLL的客户应用程序项目。
  
  注意:目前Dll_Hell_Solution/Dll_example/dll_example.h文件中的DLL_EXAMPLE_MODIFIED定义被注释掉了。如果放开这个注释,可以生成更新后的DLL版本;然后可以再次测试客户应用程序。
  
  为了保证读者能够正常演示,请遵循如下步骤:
  1. 不要改动任何代码(此时DLL_EXAMPLE_MODIFIED没有定义)编译Dll_example和Dll_Client_example两个项目。运行客户程序,体验最初的情况。
  2. 放开DLL_EXAMPLE_MODIFIED的注释,然后重新编译Dll_example。重新运行客户程序(此时使用了新版本的DLL),应该仍然运行正常。
  3. 重新编译Dll_Client_example,生成新的客户程序。我们看到新增加的回调函数被调用了!

阅读全文(3158) | 回复(0) | 编辑 | 精华 | 删除
 


« 1 2 3 4 5 6 7 8 »



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.059 second(s), page refreshed 144475358 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号