2005年09月14日

我和童生活了三年,分手N次。曾预想过一百种分手的情景,就是从来没想到能和平分手,所以当她笑着用缓缓的语调说,“好啊,大家都是成年人了,好来好散”时,我一点也不轻松,把拳头捏的紧紧,随时做好了应战的准备。她就是这样,每次答应分手,说的豪爽,可没有一次可以干脆的做到。要死要活,哭闹争吵,没有一次肯真正分手。说完,童起身离去。没有哭闹,没有纠缠。我足等了半个小时,才走出餐厅的大门,左顾右看提防她从哪个角落冲出来,可她也没有等在门口给我突然袭击。整个下午,在办公室都把手机调成无声,等待她狂轰乱炸、歇斯底里的发作,可是,居然一次也没有响,以至我怀疑办公室是不是屏蔽。一个星期过去了,她仍然那么平静,QQ,MSN,电话,邮箱,一点异动的情况都没有。一个月过去了,这是她以前所能承受分手痛苦、我能享受单身的底限时间,依然平静。这时我才掐了一下自己,做梦一般,和她真的结束了吗?




我终于可以晚上想玩到几点就几点,终于可以肆无忌惮的泡妞,终于可以专注的工作,终于不用整点电话报到了。
我终于可以在办公室逗留到11点,在网上和众多MM耍贫嘴,还把黄色图片存在硬盘上。
我终于可以和她禁止我交往的,爱搞一夜情的哥们去泡吧蹦的。

可我还是随时做好了她杀回来的准备,不知道什么时候就会结束,要即时行乐。我疯狂的玩了一个星期,天天到4点,接下来又整整的睡了2天。

周一上班,就要出差,去海南。海南的水果硕大新鲜,我捧起个木瓜,这是她最喜欢吃的水果,带2个给她吃吧,才记起,咱们已经分手了。
再也不用惦记着给她带好东西了。我终于解放了。
海船上海风徐徐,想起上一次在海船上给她发消息“我在海上想宝贝”,好象已经隔了很久,是有一个多月了。转身看见一个裙角飘飘的女孩,便霍霍磨刀,把好久没用倍感生疏的泡妞技法拿出–等我找好了新女朋友,她想回头都回不了–果然宝刀不老,这个叫静的女孩于是成了我的新女朋友。

新女友静和前女友童一样是当老师,可比她贤惠比她懂事,静的工作和童一样清闲,可静绝不会像童一样没事就逛街,把我的卡刷爆,还口口声声说“钱全花在刀刃上”。静也绝不会像童一样没事就打电话给我,一天可以打10个:“我看中了一件衣服,你喜欢什么颜色的?”“我刚看见人家都是一对对的,我就好想你啊”“咱们什么时候去桂林啊?”“哦,你在开会啊,好,我不知道,我知道就不打了,你认真开啊,我想你……”诸如此类,没有任何实际意义、完全可以回家再说的话。静白天没课基本也不会给我打电话,每天都固定在晚上9点才打,像闹钟一样准时。
静是过日子的人。
我和静虽然好象少了些恋爱的激情,可我知道,是因为童的爱恋太浓烈的缘故,就像闻了CD的绿毒香水,再闻淡雅的KENZO觉得没味道一样。

五分钟,挂了静的电话一看,才9点过5分。童平常绝不会在晚上9点就放过我的,“那10点你再打过来吧。”有时候故意忘记,下场更惨–她一定会在凌晨1点打过来说:“我一直在等你打,你怎么没有打呢?”她就是这样让人讨厌。可此时5分钟便结束了和静一天的通话,我却心里空虚。
上论坛潜水。
以前分手后,童总是喜欢在我经常上的网站留一些只有我能懂的爱的表白。3个月了,什么也没有。

其实最后一次,她什么也没有做错,只是性格的差异,以前的众多次分合吵闹,使我们已如老夫老妻一样审美疲劳。她刚开口,我就莫名的烦躁,受不了了,一秒钟也受不了了,我一定要和她分手。当时就是这样想,便这样做了。
以前每次吵完隔几天冷静下来,她再一哭,我就心软,又重新找回爱她的感觉,分不了了。
这次童没有。

在童之前我曾很认真的爱过一个大学同学,那是初恋。
在童之前我有过几年荒诞的夜生活。
认识童以后,我曾很爱很爱她,也曾很恨很恨她。

我爱她甩手的样子;爱她把鼻头皱起好多褶子的样子;爱她腆着肚子走路;爱她走夜路或到陌生的环境,很怕的抓紧我的手;爱她把头埋在我的肚子里,问:“你爱我吗?”;爱她睡觉时不准我翻身,说才朝她这边不够五分钟;爱她舍不的喝2块钱的汽水,为了见我却花30元打车……

我更恨她经常打电话给我;恨她不准我和这个来往那个来往;恨她和我吵架嘴上绝不认输;恨她只要我上网就必须和她QQ聊天;恨她对我的意见总是阴奉阳违,连分手也是,从来都甩不掉她……

我真的甩了粘人讨厌的童,遇到了合适的静。

我不知道这样做是否有点不人道。因为,童的第一次,是给我的;童第一次流产,是在我们N次分手中的一次,没有通知我,便悄悄在私人诊所买药流了,莽撞的行为,使的她后来和我一起的2年,再也没有怀上。

童喜欢喝点小酒,喝醉了就爱吵着我要我赔孩子,她喝醉后把脸埋在我怀里说:“我想要你的孩子都想疯了……”
“你能怪我吗?你都没有告诉我。”
“可当时我们分手了,你不理我啊!”
“难道你告诉我,我会不要?”
“真的?”童扬起脸,迷惘的看着我。
“没关系,以后每个月那几天我都拼命交粮给你。”我笑着说。

那时,还不知道事情有这么严重。我从不做保险措施,可是以后,不管每个月再怎么养精蓄锐的爆发,童始终都没怀上。甚至后来每次她例假前后,就昏昏沉沉的发低烧。
我说找个两人都空闲的时间,好好陪她住院看看妇科,可一直耽搁到分手。

童曾说过,她和我分手,再也不会找别人了。因为她怀不上,也只能找离婚或丧偶有孩子的,不然会害别人没有孩子,但她又不想做后妈。
想到这里,我忍不住心揪了一下。
可是当时真的烦她烦到不行,忘了这些。

我第二天打给一个哥们威,问下童的近况。威经常和童联系,本来是我的哥们,可后来和她还来往的更密切些。童自己几乎没有什么女朋友,全是和我的哥们玩。
这也是我讨厌她的一点。

威已经有几个月没有和我联系了,接到我的电话吞吞吐吐。
“童,已经结婚了。上个星期办的喜酒。她没告诉你?”
我差点背过气去:“你说什么?!”
“童上个星期结婚了。”

(2)
我好久才平静下来,她真是受了打击,是为了报复我吗?这么委屈自己?问:“她嫁了个什么人?离过婚的还是死了老婆的?”
我一直记得童说过的话。
“不是,没有结过婚的,是个归国留学博士,摆了40桌。好象感情还挺好的。”
“臭娘们!”我咬牙切齿的说:“刚分手3个月就结婚了。还说什么一辈子不嫁人!”
“你们分手3个月?童不是说你们早就分了吗?今天婚礼主持还说他们去年秋天就认识了……”
我已经听不下去,把电话砸在桌子上。怪不的这次这么痛快就分手,原来早有此心找好备用轮胎了。还说什么一辈子不嫁,三个月就结婚。哼,可笑,我还在为她担心,她早就扑到别人的怀里去了。我以为她爱我情浓放不下,原来傻的是我。早知童是这种人,2年前就应该狠心甩了她的。
“去年秋天就认识了”,原来去年秋天她睡在我手上的时候心早就飞走了。

我很少喝酒,除非陪客户,那天晚上我喝的吐了几十次。
这也是种背叛。
在你以为对方如何如何爱你胜过你爱她,分手后也念念不忘放不下你的时候,却发现放不下的是自己,人家早已经放下了。
其实是自己被耍了。
我把她没有工资还在读书时给我买的500多的手表,送给了公司的保安;把她用一个暑假天天去郊区代课的钱给我买的订婚戒指,送给表妹去打对耳环;她的照片、她的内衣、她看的书,我都扔了……
我赌气似的向静求婚,静有些意外,但还是答应了。
我们分手的第四个月,我和静结婚了。

世界上的事尽是意外。

看上去比童娴静传统的静,不是处女。就像我当年没料到作风OPEN的童居然是处女一样意外。
我安慰自己不要在意。我是因为连童那样的人也是处女所以理所当然认为静是处女。其实现在20岁以上的女人已经没几个是处女了。
处女都不懂事,任性没有好脾气。
偶尔一次不行还不懂安慰,破口而出“你怎么会阳痿呢?”
永远记得童瞪大眼睛说:“你才29岁,怎么就阳痿呢?”。
我气急,做了坏事一样结结巴巴的解释什么叫生理性阳痿,什么叫心理性障碍。告诉她这样只会让我更加障碍,告诉她应该主动帮我缓解心理压力。
“对不起,我以前没有经验,不知道这些。”瞧瞧处女的借口吧。
第二天情欲又上身,准备翻身上马时,传来她娇滴滴的声音:“你别紧张,就算阳痿也没什么大不了的。”
我一楞,软趴了,坐起来,对她吼:“你这人扫兴吗?告诉过你我这不叫阳痿!”
童泪眼婆娑:“你不是要我帮你缓解吗?我这样安慰你也不行?”她还委屈,我去哪叫屈?

童自己想想认为是我上黄色网站太多,改了密码,不准再上。
其实童不知道,是我有心理恐惧,怕满足不了她,我怕我这个开始走下坡路的男人满足不了日渐成熟的女人。
童是在经历我之后丰韵的。
我是在经历童以后衰老的。

童从处女到熟女,对性充满好奇,她不准我沾黄,自己却兴趣满满,今天告诉我学了个新体位,明天拼命的摸着我的背“没欲望吗?奇怪,网上说这样可以激起性〈!—->欲的,你翻过来,我再试试亲你的耳朵。”
最刹风景的一次是她拼命挑逗我,让我也激动起来,以为她需要我进入时,童却拿出根直尺:“他们都说中国男人的平均有15CM,我量量你的。”

我当时就想抽自己一耳光,恨自己不该破了童的处子身。

童脑子里满是乱七八糟,满是淑德女人不可能有的偏激想法。
童看了新闻说现在流行换妻,她怕我把她拿去和别人换,她不说要是换妻就和我分手,而是说,“要是你拿我和别人换,我就死给你看。”
童怕我出轨,她不说要是我出轨就和我分手,而是说:“要是你出轨,我也出轨,你不想我和别人睡觉的吧,那就别出轨。”
童怕和我分手,她不说不想和我分手,而是说:“要分手可以,你先还一个儿子给我。”
她就是这样偏激。

童不像静,我要和静吵架分手,静一定只会用低沉的声音幽幽的说:“分手了,我该怎么办?”
童是哭着大吼:“好啊,分手啊,我巴不得,可你还欠我个孩子呢!”
童泪流满面,却扑过来打我。

所以我不能找童作老婆。我和童三年,第一年就定了婚,后两年却从不再提结婚。我和静认识只有三个月,可我娶了静。

我在心里狠狠对童说,你嫁吧,谁娶你谁倒霉,任性粘人不懂事,还是个下不出的蛋的主。
我在静身下垫个枕头,“要孩子吧,这样容易怀上。”静张开嘴却不作声。
我要搂着妻儿从她面前走过,气死她!
我要在她面前大声叫“大毛”,然后看儿子屁颠屁颠的跑过来,叫“爸爸”。
“大毛”是我和她给我们打掉的孩子起的小名。

(3)
女人,绝不是男人以为了解的那样。我以为够了解童,却被证明,错了。
威在QQ上问我,想不想看童和她老公的照片。我想敲“懒得看”几个字,却最终打出个“发”字。威给我发来童的照片,她幸福的一手搭在那个矮胖的“海龟”身上,另一手搭在完全隆起的腹部。
童怀孕了!我们分手5个月的时候,她的腹部已经隆起像个球!她和我在一起两年都没怀,什么不孕,什么慢性宫腔炎,这不和别人怀的好好的吗?
她一定是骗我的。
除了戴套套,世界上还有叫女用口服避孕药的避孕方法。

她早就不想和我好了,所以怕再怀上我的孩子,并有预谋的悄悄口服避孕药,嫁祸于那次流产,增加我的负罪感。

童阴毒!这是我以前从不了解的。
我一定要彻底把这个毒妇忘了。

我一直在一家大型香精公司做销售经理,积攒了两年的年终提成–大概十几万,问静,咱们是买房子还是拿来开公司呢?
开公司吧。静说。
如果是童,她一定会逼我买房子。能比逛服装店更吸引她的就是看样板房。

她被学校聘用的时候,告诉我加上课时费一个月将有5000多。
“你可以买好多漂亮衣服穿了。”
“不,我要存钱,买房子。”
连我们一起打CS时也如此。我们作匪,她从来不买AK,不买AWP,只买MP5。几场下来,一瞥,发现她居然还有7000多元钱。
“你干什么,存这么多钱,给我买阻击枪吗?”
“不,我要存着买房。”然后露出她的招牌咪咪眼笑。
她笑起来,看不见眼珠,眯成一条线。

自己出来干,我成了香精代理商。
还找威等哥们借了钱。

我和威的关系很微妙。没和童分手的时候,几个月我才和威联系一次,本来是都是大男人,又不在一个城市,偶尔问候下就行。
一次无意间才听童说经常和威聊QQ。
当时觉得很意外。
每个太靠近童的男人都会让我紧张。
我以为几乎天天和我住在一起的童身边没有走的近的男人,除了我。
没想到她和我哥们经常聊天。
他们有什么可聊?我和威每次都是有事聊事–我们共同投资了两个彩票点–他和童哪有话题?
我很好奇,一个是哥们,一个是女朋友,却无法问,必须装出大度的样子。
从此在威面前便不太自然。
我不知道威和童的关系是朋友,好朋友,还是知己;和童分手后,威到底是站在童那边还是我这边。威从来不和我说童在他面前说过我什么,从来不评价我们以前的感情,从来不说谁对错,从来不提。只是威会冷不丁冒出一点童的消息。

“你要借多少?”
“你能借我多少,当然越多越好。”
“我刚买了房,手上没多少余钱,去筹筹看,应该一两万是不成问题的。”
“好啊,谢谢你。你尽量帮我多借点。到时第一批定单出去,就可以还。”
“没关系。童生了个儿子。7斤8两。”

威每次就是这样,说别的事情时突然带出童的消息,就在我几乎要忘了童的时候。
“那好啊,帮我恭喜她,静应该也快了。”
“静也怀了?”
我恹恹的说:“还没呢,最近不是忙吗。公司上正轨我们就准备要了。哼,不像有些人,急着先上车后补票。”

当晚没有一点兴致。可我粗暴的把静拖进房里,扒掉了她和自己的衣服。她看着我还是软趴趴的,眼神迷惑了。
“没事,等下就会硬了。为了造人,我们要努力啊。”
静不作声,低下头主动爱抚我。

和童在一起,性生活无比协调,除了几次“心理性障碍”外。我们有好多次都可以同时到达颠峰–这是性爱最完美的结局。
和童以前,和童以后,我其实都是喜欢后入式的,这样最省力,最刺激。可只有和童,我偏喜欢作传教士。
开始是因为童喜欢这个姿势。
“你不喜欢从后面吗?那样应该最深啊。”
“喜欢,可从后面就抱不到你,看不见你的表情了。”童怕我不愿意,马上又说“我答应9次前面搭配一次后面好吗?”
可后来我也喜欢上了从前面作教士。因为我发现每次从后面要20分钟,从前面,俯身抱住童,同时亲吻,用不了5分钟就一定爆发。
谁不喜欢迅速爆发呢?

每次事后感叹,还是有爱的性才叫性爱,才最舒服。因为童是我爱着的女人,那个姿势又和童最亲密,还可以亲到她,所以每次让经验老道的我忍不过5分钟。

30分钟了,我还是没有在静体内爆发。静什么也没有说。要是童,超过5分钟就会嚷着累。
“又不要你运动,你还累啊?”
“就是嘛。”
“那你要加强锻炼,以后多动啊。”我嘲笑着童。从此在心里给她定义:任性、粘人、懒惰。没听说过躺在下面悠闲的喊几声,5分钟就累的。

“算了吧,我们又不急着要孩子。”静终于说话了。
我抬起头,才发现面前的静,不是童。

有一次我和童分手一个月又和好,我们仿佛有说不完的话,要向彼此交代这一个月发生的事。童每次都要追问:“你想我了吗?都是什么时候什么情景如何想的?想了为什么又不打电话呢?”
我笑着回答,哦,有时候听到我们在一起听的歌时就会想你,可我是大男人啊,怎么能随便就给你打电话呢?
童,你这个女人到底现在在想什么,在做什么?你抱着海龟的儿子时,有想起我们的儿子大毛吗?

(4)
威真够哥们,居然借了我十万元。
因为资金足够,加上以前布下的客户网和那么多年销售的经验,很快生意做的风声水起。我忙起来。
在中山出差,陪客户喝醉了酒,走回宾馆,让冷风吹醒酒性。
去年,是在上海,还在别人的公司做的时候,也是陪客户喝醉了酒,我一个人走在外滩,看着周围热闹的人流,看着我的风衣被冷风萧瑟的吹动,忍不住打电话给她。
“我的责任很重,以后要照顾你,照顾爸妈,要赚钱,让你们过舒服的日子,还有我们的孩子。”那是少有几次我对她倾诉。我一直觉的大男人不要说这些肉麻西西的话。责任,一直有,只是对象换了。现在想来还像做梦一样,我没有想过我和童会真的分开,我身边的妻会另有他人。
虽然一直对童有诸多不满,可一直以为会偕老白头。
我不是这么传统的人,是童强加给我的信念。因为于她,选择了我好象永远就不肯再放手一样。于是我也被催眠了,老是嚷着要分手心里却没认为真能分开。
我不得不承认,童是个无比执着的女人,至少在我们感情上如此。
哼,执着个屁,最终她还是和别人结婚了。
我抹抹额头。给静拨了电话。静不在家。打手机,静说她回娘家了。
我赶凌晨的车回家。开门,静居然已经回来。
我紧紧的搂着静说,“我的责任很重,以后要好好照顾你和爸妈,还有我们将来的孩子。”
“我知道。赶快洗个澡休息一下吧。”静总是这样恬淡。静身上散发的温馨,是童不能比拟的。

这段日子是忽略了静,我整天陪客户吃吃喝喝,几乎没在家吃过一顿饭。要是童早就发飙了,带她就像带孩子,比带孩子还累,离不得人。空虚,寂寞,冷落,都可以成为她去酒吧买醉的借口。我说过,她喜欢喝酒。这也是让我不放心的地方。可是静却不会。
日子过的很快,生意有几次失败的时候,每每都是威出手相救。我没问过威为什么会有这么多钱,威是公安局的一个小头,是否有黑钱也不方便问。

饭间一个大公司的老总,说奇闻给我们听。
“现在的女人真是不得了,为了钱什么都干得出来。我认识一广告公司女总,为了在我这接个业务,磨了好多天。可我已经先答应了一熟人,所以她软硬兼施,使出什么给回扣、送礼这些见多了的招,我还是没答应。你们猜她最后来了一招什么绝的?”
“哈哈,那还有什么,主动投怀送抱,陪你上床呗。”
“哼,猜错了吧。自己陪我上床算什么啊,现在这种招还算招吗?她带了5个女的,个个1米七,面白唇红,眼带桃花,身材一流,凹凸有致,一起拥进我办公室,说:‘陈总,这些全是我们公司公关,你看中哪个或者哪两个,自己挑。当然,您要是体力惊人,三个也行。’然后这女总自己先脱光了,指着小腹上一道明显的疤说:‘我是已经生过孩子,破过相的人,你不介意的话,挑我也行。’然后另外几个小姐也跟着全脱光了。”
我们流着口水听呆了。
“你说要是她一个,我肯定能顶住。女的出来做生意的,但凡没有后台,基本上是都睡烂了,白送我,还要考虑考虑,可这加上5个美女一起在我办公室全脱光了,我是一凡人,顶不住啊。”
“那你还不是享尽人间春潮?说吧,挑了几个美女?”
“哈哈,当然是一皇二后啦。不过话说回来,那女总还真是厉害角色,酒店、房间、美女、伟哥、制服、SM,一条龙全准备好了,两个美女的妇科检查单也交给我检查,还在耳边悄悄说:‘陈总,事先给她们两都吃过避孕药了,每人三张嘴,您想怎么玩都行。”
我们啧啧称奇,道说社会不古,什么人都有了。
“当然了,她这样有胆色的操作下来,才能最终把那单我准备给表弟做的生意抢过去。你们知道那单多少钱吗?”陈总惊的我嘴没合拢:“1500万。”

睡前,我抱着静把这听来的奇闻做黄色笑话说给她听,静只是依偎着我,在黑暗中不笑不语。我连忙发誓表态,自己绝不是徐总那种人,一来小公司没有那样的大单给别人做,二来以后生意做大了也不和女总单独谈生意,除非有静在场。静轻声说:“女人和男人比起来,真是弱者,同样是都是做生意,自己做鸡还不够,还要做老鸨。”
我紧紧的抱住静:“别怕,反正你不用出去做生意,有我照顾,一辈子就等着做少奶奶享福吧。”
我和静算着公司现在每个月赢利多少,已经走上正轨,以后我们要赚多少万。
我和童刚住在一起的时候,有个夜晚,也是这样,关着灯,睡在床上,第一次说到了结婚的事。我抱着童,有点不好意思的告诉她,零零碎碎全加上,我只有8万元存款,不过再存一年钱应该就可以付买房首期款。童说:“没关系。等我毕业,一个月也有3千多,然后我再去外面兼点课上,就有四五千,加上你的工资也有一万零了,拿2千供房,一千伙食费,一千给我们父母,哈哈,还剩6000多呢,怎么花呢?”一边说还一边掰着我的指头算。
那时,我觉得童真是个好女孩,只想和我一起供楼还贷款。
童在真正做了我的女人后,是想嫁给我的。
我娶的妻,却是静。
童,成了别人的妻,别人孩子的妈。

我在黑夜中把瘦弱的静抱得紧紧的:“我以后会赚好多钱给你用的。我以后会好好对你的。我以后绝不会出轨的。”
我会彻底忘了童,只和静你一个人好好生活的。
“好。”静轻声说。
我以为静会扬起脸,迷惘的看着我说:“真的?”
在黑暗中,看不见静的表情,只依稀记得童是这样回答过,模样已经幻化。

日子继续着,我继续忙碌着,周围的人说我渐渐变了,变的塌实、肯干,更像顺德农民了。是啊,现在做生意竞争那么大,脱衣服没人要,只能凭实力,不努力,吃什么?
童以前经常说我学历低,又不愿意继续深造,我也想把公司做大,让已经嫁给海归博士的童知道,我没有高学历,也能成功。
不过,幸亏几次危难中有威借我钱。算下来,他前后已经借给我几十万了。可是做生意就是,都又囤积到货款里了。幸好,威每次都说不急,丝毫没有催还的意思。

陈总的公司很大,有一个全国闻名的饮料品牌。树大好乘凉,我几乎没有赚一分钱给了他一批香精,因此和他合作密切。
我去陈总公司结款,他神秘的叫住我,“今天有好事便宜你。等下来我办公室。”两眼放光。“还记得上次我和你们说过的那个广告公司女老总吗?她今天也来收钱,所以又带了几个靓女,我留1个给你。”我连忙拒绝。和童在一起我总不能抵抗外来的诱惑,和静生活,不能再重蹈覆辙。
“嘿,你这么革命?看看你就会心动的。我领你见识见识美女吧。”
“那行,我就瞧瞧。”
其实,我想见的不是美女,而是想见识下那厉害的“老鸨”。到底是什么女人,可以这样豁出去。

(5)
走进陈总关的严严实实的办公室,看见4、5个模特一样的女子转过来。各个清瘦高挑,一脸浓妆。最后转过身的是中间最矮的,素颜,童颜!是童!
我以为她的容颜已经模糊,可是原来就算她的身材已经改变,我都能立刻辨认出来。
比起和我在一起白净丰满的身材,现在的童至少瘦了20斤。从没想到过一身BABY肥,软软的肉肉的童竟可以瘦成这样,颧骨、肩胛骨、手肘、腰骨,处处露骨,处处刻骨。一件剪裁贴身的黑色西服在她身上还灌风。
童就是陈总叙述中的广告公司女总,可以脱光衣服站在男人面前自暴其丑的老鸨,可以为了生意提供全套周到性服务的女人。
从我们分手那一刻我就有预感会再和童见面,只是没想到是以这种场合,这种身份。
就像我对我们分手失算一样,对我们的再见同样失算。

童同样惊讶于我们的重逢,不过瞬间就恢复自然,扯起嘴角笑着打招呼,装成不认识我。

童笑起来,颠覆了我的回忆,回忆里她是无邪的笑的可爱,不是这样扯起颧骨旁深深的一道沟,笑着冰你。
我曾和童说过我喜欢女孩子瘦一点,童却怪我喜欢给她扛成批的雪糕买成箱的薯片,害她瘦不下来。就连分手后,家里的冰箱还留有半打她没吃完的雪糕,慢慢融化。
童胖的时候是我见犹怜,瘦下来却阴冷。

我不记的当时的情景,现在想起已经是一片空白。只记得始终无法把眼光从童身上移开。陈总看出来了,问我最近有没有要做广告的的产品,要童和我合作。
一定是当时我的眼神太直勾勾的望着童,让他以为我对童有意思,想撮合童陪我。
“是,我有广告要做。陈总你不是说找个靓女陪我吗,就让她陪我吧。”
陈总左手一个,右手一个,我和童,一起进了宾馆的2间套房。
走进去,我把房间的门反锁上,一把把童扑到床上,舌头侵略她的舌头,手撕开她的衣服。
“讨厌,你怎么这么猴急啊,你就不能等我把衣服挂好把东西收拾好再……”童娇俏的笑着嘴上拒绝我,却是欲拒还迎半推半就的帮我解开自己的扣子。

这是2年前,童过生日,我刚好去上海出差,顺便带上她去玩当是庆祝时的情景。宾馆套房里雪白的床单,局促私密的空间让我克制不住就想要童,她还笑我说的好听是带她来玩,其实是为了满足自己。

现在,童靠在桌子前,不发一语,不笑,不动,只是瞄着我。
我坐在床上,同样没有表情的看着童。
从见面起我们就这样沉默的互相看着,除了打招呼外没有多说一句话。
有太多话想问童。
可童以老鸨的身份出现,以生意床伴的身份站在我面前,我关心的问题只有一个。
“你陪多少客户上过床?”
童没有任何表情的看着我,不出声。
“你到底在干什么?不是在学校教书吗?怎么出来开公司了?不是好好的嫁给了海归博士吗?还缺钱需要拿肉体换生意吗?”
童还是不说话。
我终于爆发,站起来,抓住童的肩膀拼命摇晃。
“你说话啊!”
可我不敢继续摇下去,抓着她的肩膀,似乎骨头也能刺到我的手,她轻得没有重力一样,我怕把她摇散架。
童抬起头看着我,“这是我的私事。你不会是要在五百八一晚的套间和我聊天吧。你要不是来上床的,我就回去了。”
她拿起皮包,转身就走出房间,头也不回。
以前一直是我冲出去,童跟在后面拽我不要我耍脾气。
现在是我跟着冲出去,把她从楼梯间拽回来,甩手关上门,扔到床上。
我忘了她是如此的瘦,轻轻一甩,惯性把她的头重重砸在床头上。
我把她的包也扔在床上,里面的东西洒满一地。

童背对着我,跪在地毯上,弯腰捡着东西。
她肉肉的时候,我就说要保护她就想要保护她。
她瘦弱的背,如今只有我一半宽,骨头隔着外衣都隐弱可见。我却永远不能再去保护她。

我把童拎起来。
“你这样乱搞,你不想想自己,也要为你老公你孩子想想吧?你老公愿意自己老婆天天陪人上床?不管你?你对的起你丈夫你孩子吗?”
我可能说到童的疼处了吧。她抬起头,含着泪,咬着嘴唇,用眼瞪着我。
两年了,我还是可以一如以前,轻易刺到童的最疼处,并把这种手段当成致胜的砝码。

童在我之前,谈过一次恋爱,那也是她的初恋。
“你想想看,现在有谈恋爱只拉拉手亲亲嘴不上床的吗?他都跟你谈了快两年,现在和我,才破了处,他是有多讨厌你才会连到嘴的免费午餐都宁可不吃!”
这是我每次生气时,力举童惹人讨厌的一条证据,每说到这,善于反驳我的童就会不说一句,含着泪,咬着嘴唇,用眼瞪着我。和现在一样。
我胜利了,吵赢她了,用最刺疼她的方式。

我承认我自私。我爱童,可以爱她入骨,但不会把心窝掏给她。我讨厌童,就可以用渣滓洞的残酷,伤害她。

童的牙齿放松,嘴角慢慢提起,她居然笑了。
“我已经离婚了。”

我知道,当最后一次分手,童那么轻松的走出门时,我就知道有这一天。她不是轻易就会放过我的女人。
她来找我了。
我已经放下童的手,又把她拎起来。
“我就知道你不会轻易放过我的,不闹个鱼死网破,你是不会愿意和我分手的。所以你宁可采用这么偏激的报复方法。哈,我都差点忘了,你就是这么极端偏激的女人!先是和博士结婚,以为能刺激到我,没有,又和他离婚,然后人尽可夫来报复我,是吧?”我咬牙切齿的冲她喊到。
这个女人。她是天生带破坏性的。她怎么会眼看着我和静幸福的过上平静日子呢。是我麻痹大意。
“你到底要怎么样?!啊?!今天的见面也是你安排好的吧?!我告诉你,别以为你真能毁了我的生活!你还想和我上床?哼!你是处女时我就是勉强接受你帮你解决激渴,何况现在被这么多男人睡过,世界上的女人死光,我也根本不会再碰你一根指头的!!我和你,是永远不可能的!你离婚了,可我现在婚姻幸福着呢,老婆比你贤惠一百倍,漂亮一千倍!我不会让你再搅和进来的!”我瞪着眼睛的嘶喊着。
我知道,当时的表情一定可怕极了,就像要杀人。
我知道,蛇打七寸,擒贼擒王,只有彻底击到这个女人的最脆弱底线,我才能赢,才能有摆脱她的可能。
童还是轻轻一笑,是轻谬的冷笑,说:“明白了,你不是来上床的。我早就说要走的啊。”她丝毫没有被我打败,两年前的童真可爱全没了,只剩成熟冷艳。走到门口,童又回过头,拉低外套的肩膀,说:“但是,真的没有一点诱惑吗?”
反而是她,说到了我的心里。

(6)
童,也许有万般缺点,可我必须承认,她是具有很强女性魅力的,这是她天生的优点。她的身材丰满,曲线突出,皮肤白皙,头发长卷,性别特征明显。
如果我不是童的第一个男人,我也许不会对她具有如此强烈的独占欲。就因为童只有我我一个男人,童一直认为我是最强的,所以我怕,怕没有经验又天性好奇的童哪天好奇心发作和别的男人上床,发现其实她的男人不是最强的。
还怕如此娇美的童被别人分享。
所以我从来不表扬童的这些优点,而且尽可能把和童上床表现的像解救困难户一样,希望她认为自己对男人不具备吸引力,哪怕每次行为出卖了谎言,至少我在口头上一直如此强调。
我怕只有我的童,哪天发现了,要利用自己的这些优势去招惹别的男人。这种与日俱增的怕让我抓狂,直到我想出了办法一劳永逸:和童分手。
和童分手之后就再不用担心,担心晚上联系不到她,瞎琢磨,偏偏还得装成满不在乎的样子;担心吵架后,她会采用身体出轨的方式报复我;担心我出轨被她发现,她会采用乱搞的方式报复我……

男人总会有性的冲动和喜欢性的新鲜刺激,一如我,一如你的老公,或是她们的男朋友。
一次和童分手,无比空虚,急切需要温热的女人气息代替右手。
我要证明,我的空虚,不是与童分手后感情的空虚,而是没有女人身体的空虚。
于是便上QQ,花了几天时间培养,锁定一个目标:“不停旋转”,已婚妇女,27,言语极开放。
我也把和童一起拍的大头贴发给不停旋转。
用我和童的合影发给要泡的网友,是过分,这也我的手段。大头贴上我和童拍的就像一对璧人,和我偷别人的老婆一样,她勾引靓女的男朋友肯定也同样具有征服感。
这叫一招致胜。
果然,照片起到了作用,她的兴趣马上提高。
我开始在网上更大胆的勾引、挑逗她,她十分受用,急着要听。

无:我一把把你拖进房,扯掉衣服,露出一对雪白而丰满的乳房……
不停旋转:你怎么知道我是白而丰满的?
无(我有点尴尬):那你白不白,丰不丰满?
不停旋转:当然啦。继续说嘛。
无:……(省略)。
不停旋转:……(省略)。
无:……(省略)。
不停旋转:……(省略)。
无:……(省略)。
不停旋转:……(省略)。
无:我把你的长发拨开,看你动情的样子。
不停旋转:可我是短头发啊。
无:是想象啦,我怎么知道你现在是长头发还是短头发。
不停旋转:你女朋友是长头发吧?

不停旋转一针见血的揭示我不愿面对的事实–我描绘的和她亲热的场景其实只是回忆和童无数次亲热的一次。
我难道真的只是在怀念童的身体吗?
不是,不是,我是可以把性和爱分开的男人。
我就证明给你看。
我在网上又勾引了不停旋转几次,软硬兼施。终于,她答应第二天上午来我家,可是提出有一个要求。

无:说吧,宝贝,是不是要我准备好TT?
不停旋转:不是。
无:喜欢SM?
不停旋转:去你的。
无:是什么要求,你就直说吧。我们都这关系了,别说一个,就是十个我都答应你。
不停旋转:其实,我们的聊天记录,我老公都看过了。看了照片后,他很喜欢你女朋友,说要是你答应让你女朋友和他上床,他就答应我和你上床。
无:我不换妻!

花了一周的时间,每天下班就在电脑上打这些字,可最后的结果是他们看中了童!
我那时彻底崩溃。对异性,童远比我更具有性诱惑。我花了时间、费了脑力、用尽技法,都不及她不谙世事的躲在大头贴上一笑。

没想到不停旋转的老公是移动的什么内部人员,轻而易举的从我告诉不停旋转我的手机号码里查到了通话最多的那个号–童的,开始直接对童进行骚扰。
当然,不止我,还有不停旋转也嫉妒童,当她发现丈夫真的是对照片中的女人一见钟情后。这些是她告诉我的。
我闭上眼都能看见那个男人以掌握我出轨的证据来诱惑童的情形。
我要发狂。
分手了,还是放不下童。也许不知道还好,知道了,不能、不可以想象童被别的男人拥入怀。
我和童复合了。

离题,我从两年前的回忆中苏醒,望着童骨瘦如柴的身体,缩水的胸部,减退的魅力,自己却没有对她减少欲望。
童已经走出门。
童不再执着于要留下来陪我。

我恨童。
她的霪乱,撕毁一切与她重新在一起的可能。
我是说如果我也单身的话。

我打电话给威。
“童离婚了?你为什么没告诉我?”
威很吃惊。“你怎么知道她离婚了?你从哪打听的?”
“哼。我还需要打听吗?她在我们这已经以性贿赂出名了!”
威沉默着不语。
“看样子你都知道!那你怎么不告诉我?她结婚、生孩子你都说,离婚了你却不说呢?”
“她是离婚了,那又怎样?你又没离婚。”

(7)
威提醒我,才记起,有静这个妻。我无权再过问童的一切。
“你要真还关心她,就离她远点,别再伤她。”
“那她为什么离婚?什么时候离的?”
“刚生完孩子的时候。”
“为什么?童不是生了个儿子吗,怎么会搞的要离婚?那孩子判给了谁?”
“孩子没满月就死了。先天不足。你别再问了。”

“我可能这一辈子都怀不上孩子了。怎么办,我好想给你生个属于我们的孩子。”
“别乱想,我们好好治,现在科学这么发达,非治不好,我们还可以人工受孕啊。”
“真的?那好啊,听说人工受孕往往容易生双胞胎。”
“那双胞胎是两儿子还好,一个跟我姓,一个跟你姓,要是两女孩我可亏死了。”
“为什么?女孩多好啊。体贴父母……”
“好什么好?像你这样,父母把养这么大,白白嫩嫩,保护得这么好,最后不还是白送给我了吗?”
“你怎么这么说,好坏啊……”

那么想要孩子的童一胎流了,一胎死了,还和丈夫离婚,受的打击可想而知。
但这都不是她放纵的借口。
她放纵光我什么事?我不要和她再纠缠。
但是,童如果低姿态的撒娇叫我,像过去那样扑到我怀里,我还能拒绝吗?

我领着静上街购物,钻戒,手表,时装,只要她试什么我就刷卡买什么。静抢过卡,不准我再刷。
“你疯了?我没说要买,只是看看而已。”
“没关系,看看也可以买嘛,有更合适的,再买。”
我要补偿静。
可我欠了静什么?不知道。婚后从没有出轨过,杂心都没有。昨天和童,也没有。欠了爱?我对谁还有爱?只要和静有感情,对静好就够了。
那我到底是欠了静什么要这样补偿?
我以前欠了童,想在静身上补偿。

我呆住了,为自己的自话自说。

“我看,我们还是不逛了,回去吧。我累了,再说也买了这么多东西,够了。”
“不行,不够。你再去挑点衣服,冬天快来了,挑点新上季的衣服,啊,还有鞋。”我不由分说拉着静就走。
“你不要这样好不好!你看现在才几月份,这里需要穿冬装吗?到底是你要买,还是我要买?”静甩开我的手站在商场中央提高音调说。
第一次听静说话超过八度。我们僵持着站着。静叹口气,过来扯我的手:“我们回去吧,回去包饺子给你吃,下次再来逛嘛。”静像母亲似的,扯着我的手,带着任性的孩子回家。为什么静当我是孩子,我却当童是孩子?
我的情绪起伏。静随我闹,她不和我闹,由着我闹。

童有两种方法能很轻易的打听到我的电话号码:威和陈总。我以为她会再打给我,一如以前吵架。
可是童没有。似乎从最后一次分手开始,童就彻底把我排除出她的生活。也对,她现在是广告公司的老总,每天要计划着招呼手下的女公关去哪接客,还有,她也有钱了,一单生意就1500万,赚的不少吧。她哪里还会记得我。

我白天照常上班,可下班后,特别到晚上9、10钟就开始难受。我想象着这个时间,童开始坐在这个老总的大腿,那个老板的怀里。12点了,童一定正光溜溜的躺在哪间宾馆的床上。
“我出去走走。”
没等静回答,就拿着手机和钱包出门。
135……,这是童的号码,拨通,“小狗狗”三个字跳了出来,我的电话,一直存着她的号码,不过,名字是昵称。
“对不起,您拨的号码是空号,请查对后再拨……”
我又打威的电话:“童的号码改了?现在是多少?”
“我只和童在网上联系,我不知道她的电话。”
“怎么可能,那你每次能那么及时就知道她的消息?”
“真的。她有我的号码,我没有她的。有事,都是她打给我的。而且,不应该再去找她了,你不怕你老婆知道?”
人被血气上头,劝的住吗?当初是童每次血气上头,哭着喊着不许我走,现在,是我血气上头,到处找她的号码。

威不像撒谎。只有最后一个办法了,问陈总。正花天酒地的陈总微醉着回答说:“你开始还说没兴趣,装得君子一样,怎么,现在爽了一次还想要?我没她电话,平常都是她打给我,她求我办事啊。名片倒是有,放办公室,现在也没带身上。这样,你过我这来吧,这有几个美女,身材长相都比她强,让你一个。”
“我就是要找她,是公事,谈广告业务。”
“少来了,这个时候谈业务?我说那娘们是不是有什么特殊功夫,这么勾你的魂?改天我也尝尝是什么味道……”
把电话摔的粉碎。以前和她一起,她总能让我这样莫名的烦躁火大,没想到和别人结婚了也一样。
急也揪心,躁也揪心。

以前总是我关了机,四处找我。
现在是童换了号,我四处找她。

童有做侦探的天分,我每个哥们的手机号码从没告诉过她,可她全有,不知道怎么搞到的。有次我们三个男的去泡吧,童打我手机,太吵没听见,她就接着打另外两个的,其中一个哥们接了,听是她,惊呼,你怎么知道我这个号?你老公他都不知道!

我关机,是嫌童烦,电话太多,经常拿着漫游和长途费演韩剧。可是她居然可以在我重新开机的第一时间打过来,含着哭腔说:“你怎么可以真的关机?你怎么可以这么不负责任?万一我这个时候突然出车祸、被抢劫要打给你怎么办?你知道我一直打你的手机打了多久吗?”
“你说,你还烦不烦,你再烦,我又关机了。”
“别关机……”童急的马上哭起来,“我不烦你了。好吗?”
我得意的笑:“恩,这还差不多。我挂了。”
“啊,等一下,你今天还没说一句甜蜜的话,光骂我了。你说一句,我就能睡的香些,就一句。”
我有办法关机整她烦,她也有办法整我说出肉麻的表白。
“乖,宝宝乖,要听话我才会喜欢你啊。”
“好,我会听话,你今天有想我吗?”
“当然有了。”
“想,怎么不打给我呢?”
“我今天好忙,到现在才回家,澡还没洗。”
“真的啊,那你今天忙些什么?”
“忙的是……诶,又说了多少句了?你不是说不烦我了吗?我挂了啊。”
“好,不说了,再说一遍你爱我我就挂电话。”

我强硬,童拿我没有办法。童撒娇扮可怜,我拿她没有办法。
我们是天生的冤家。
所以才会分手了还能再碰见,这是缘分。
只是不知道,是不是孽缘。

一晚上,翻来覆去睡不好。起身,上网。静压住我。
“你最近到底怎么了?平常五分钟就开始打鼾的,失眠吗?”

说个笑话,有一个人,非常能睡,一般上床如果你一分钟内没和他说话,就能听见鼾声。如果十分钟还没睡着,就抓狂,以为失眠了。他不知道别人一般入睡就要20分钟。
这是童说的。
我就是这样没心没肺的活着。
当时却不知道,这就是幸福。一分钟就能睡着的幸福。

第二天,一早自己就去陈总公司拿童的电话。捧着号码,我居然像第一次和童见面后给她打电话一样,清了清喉咙,想好了要说的词。
童会不会不接我的电话?我的号码没换过。
童会不会冷淡的挂断我的电话?

可是童的两年秘密生活,童的现状,童心里到底还有没有我,童的想法,都像迷一样抓住我的心。一个曾经那么爱我的女人,短短两年的蜕变,诱惑着我,鬼迷心窍的拨通了童的号码。

是男人的声音!
我不出声,我没有想到这种可能。
对方还在喂,我挂断了电话。

三秒后,童的号码又拨过来。
“你刚才打了这个号码,请问你和机主是什么关系?”
“你又是她什么人?我要找童。你叫她接电话吧。”
“你要找她?来XX公安分局。”

(8)
隔着公安局的玻璃窗,看见童。她显然一夜没睡,眼睛发青,化过妆的眼线酝开在眼睛周围,头发散乱,瘦弱的身躯蜷缩在椅上,鞋也脱了,用手指掰着脚指玩。
童喜欢这样把脚缩到椅子上。
我嘲笑过她,她吃饭时也这样,像叫花子。
“我就要这样,我妈也这样,我爸也这样,我们家吃饭,全这样,脚不着的地的,这是童家习俗。哼,你是嫉妒吧,嫉妒自己脚缩不上来。”童“哼”的时候,嘴向前弩,鼻子皱皱的,特别可爱。

童沉迷的掰着脚趾,我错觉她还像认识我的时候一样天真,那年,她21岁。

童是因为“性贿赂”罪被扣留。
我因为给她打电话,又自己开有香精公司,也被怀疑是涉案人员。
公安问:“你打电话给她干什么?你们是什么关系?怎么认识的?”
“她是我的女友,已经分手了的。”

查明我没有和她有业务往来后,公安说可以走了。

我站起来,还是和童隔着窗户。
童抬起头,看见我,眼神中闪过一丝惊喜,转瞬,又恢复平静。
她知道,我救不了她。
我就隔着玻璃窗户望着她,想救她,却使不上劲。
童发青的眼睛一直随着我走出公安局,像重遇的晚上,瞪着我,没有表情,却目不转
睛。

出门,急着想怎么把童救出来。请律师。这个不成问题,关键是要找公安局里面的熟人,打听准确情况,别让童受冤枉苦。
我记起威,威经常来我们市办案,和这的公安也很熟。
连忙给威的小灵通打电话,不通;打办公室,威的下属说,他正在往我们市的路上。
“特别急,好象说这边有个案子,可一个人就走了。”
打手机,威接了。
“你现在在路上?是开车来我们这吗?”
“你怎么知道?”
“还有几小时到啊,我去接你。”
“大概还有3个小时,凌晨4点出发的。”
“太好了,你来的真是及时,你得把手下的案子先放下,我们碰下头,给你说说童的情况。”
“你知道童出事了?”
“你也知道了?”
“我过来就是专门处理她的事的。”威急急的把车停在路边,和我说:“我叫你别和她联系,你怎么非不听。告诉你,童的事,放心,我肯定会尽所有能力救她,你呢,就别再搅进来了。这案子,听说有人准备上报,作为你们市性贿赂典型案件,到时就更麻烦了,谁沾谁一身腥,你还有老婆,别把自己也搭进去了,而且,你搭进去还白搭。”
“那你打通关节、请律师,都要钱吧?你去走关系,我去准备钱。”
“行。记住,有什么事和我联系,别和童,也别再和与童有关系的人接触了。”
“威,要真是童有罪,会判多少年?”
“得看涉案金额。”
“1000万以上呢?”我记得光陈总给童的单,就有1500万。
“你还记得以前我们那中建三局有个女的,接建筑工程,也是涉嫌性贿赂,好象有7000多万涉案金额吧,是判的死刑。”

我眼前一片黑,腿脚发软,眼角渗出了咸咸的液体。
我是男人,从不哭,只流泪。
长这么大,只流过6次。
一次是6岁,父母离婚,我骂我爸,他反手抽了我一耳光。
一次是28岁,抚养我长大的外婆去世。
一次是29岁,童第一次和我吵架,收拾行李要搬回去。我扯着她的衣角,对她说想什么时候回来就什么时候回来。
一次是30岁,我第一次下决心和童分手。
一次是31岁,和童在上海过生日,外滩、新天地,都可以让她兴奋不已,才记起,三年没带她出去旅游过一次,心酸,童和我一起吃苦了。
再就是这次。

“童会判死刑?”我颤抖着问威。
“不会,我是举个例子,人家7000多万才判死刑的,童怎么会有啊,1000万大概判10年左右,如果成立的话。当然这是最坏打算。不过,你怎么知道有1000万?童告诉你的?确切吗?”
“没有,我也是随便举个例子。”

准备走,局里跑出个公安:“正好你还没走,她要见你。”

我,桌子,公安,童。
这样非常规的方式,开始平心静气的交谈。
“我,在这里没有亲人,就麻烦你帮我处理一些事吧。这是我家的钥匙,地址是……,你帮我去拿些衣服,还有,帮我给家里打个电话报平安,说我出国了。”
童真是世故了,声音镇定,情绪平静。
她知道事情的严重性吗?

我怎么一直忘了,童在这里没有一个亲人。
她就这样过了2年!中间还经历了丧子、离婚,到现在的羁押在案。
伸手接过钥匙,触到了童的手,骨头咯得我疼,心疼。

童的家的位置,不敢想象,居然就是我们曾同居3年的地方。
我退租后,是童租下了!

(9)
记得我退租是在分手4个月后,准备和静结婚的时候。当时,房东说早就有租客和他说,我一退租人家就租,最好是连家具一起。
原来租客就是童。
童接着1500万的单时,仍然是住在这没有电梯的两房一厅里!
现在,一桌一椅,原封不动,都是和童一起生活时的样子。
客厅,还放着我健身用的跑步机,我搂着童“看我们多配啊”照的镜子,铺着童从“娘家”带来的桌布的餐桌。
卧室,衣柜、电视桌、床头柜,从上海宜家背回来的折叠桌,一点都没变。
打开衣柜,一层,放的全是我给她买的衣服,看来分手后就没再穿过,一直折着收着,折痕都很深了。
床边的墙壁,摸到一块熟悉的地方,是一次我们吵架后,童伤心时,用发夹刻的歪歪斜斜的三个字:我恨你。另一面墙上,挂着放大的照片,是我们感情最好的时候,我和童、我妈一起爬山拍的照片,我们都没心没肺的傻笑着。
我们的合影全是童细心收着,我说以后买了新房再放大摆出来。
“你怎么这么俗。现在谁家还摆大照片啊,要摆也摆幅名画啊。”童当时还说的我不好意思。
整个家看不出一丝她前夫的影子,童仿佛还是我爱着的,没有结过婚、没有霪乱过的单纯姑娘。

我终于忍不住,捂住疼的裂开的心蹲下来。
童,原来一直都爱我。
不管她结没结过婚,和多少男人睡过,每天都这样生活在我们的房间里。

静打来电话:“你今天没去公司?”
“回来再说,我去办件事就回家。”

我买了童最喜欢吃的薯片、梅条、菠萝啤和她的衣服,一起递给了她。

童检查完衣服笑着说,你怎么还是这么粗心?这条裙子明明是黄色的,你怎么拿件紫色的上衣呢?多难看啊。
我拍桌子站起来吼道:“你还笑!你还笑的出来!你知道现在什么状况吗?威说一千万就判10年,8000万就枪毙,你还笑得出来!”
童被我吓到了,急忙过来搂着我的腰说:“真的?你可不能不救我!我好怕,我不敢了,哥……”童总是恶作剧一样学着韩剧,叫我哥。
“你现在知道怕了?”
童乖乖的点点头。
“真的?那你甩甩手,我就救你。”童甩起手来可可爱了,独家动作,全身都跟着扭着。
“甩手跟枪毙有什么关系?我甩手你可以保证他们就真的不枪毙我了?”
“当然了。”

现实的童没有表情,看也没看就拿起一件衣披在身上,说,“你早点回去吧,别让家里人着急。我没事,你也不用再来了。”
“你等着我,我去给你请律师。”
童轻轻的摇摇头,别,别再为我浪费一分钱。
“没关系,我虽然没有很多钱,可是无论多少,只要对你案子有利,我都会花。”
“你的钱,不是你一个人,还有你老婆的。你的心意我领了,别说了,回去吧,不要来了。”童一字一顿说。

“我知道你怪我喜欢买衣服,而且有的还买的挺露的,我现在又不挣钱,你嫌我浪费钱了。可是告诉你,我喜欢你才用你的钱,我要是有二心了,就一分钱都不用你的。”
这是典型的童式强盗逻辑,当时我听着格外不舒服。
现在才明白。

(10)
回到家,开门,静从沙发上一弹,就走到门口,满脸焦急。
“你最近到底怎么了?昨天那么晚要出去散步,还失眠,我担心你打到公司,才知道你没去上班也没有交代任何职员。”
“我有一个朋友关起来了。”
“什么朋友?我认识的吗?”
“不认识的。”
“那犯了什么法?”
静盯着我的脸,我无法对她撒谎,也无法说出“性贿赂”这三个字。静是宁静的生活着,不会理解童的堕落。
“乱搞呗。”
“乱搞?有这个罪?是P C吧。哪个朋友?”
“你不认识,生意场上认识的。别问了。折子呢?家里那定期存款的折子呢?”我装着找存折,不敢看静的眼睛。
我只能用翻箱倒柜掩饰我的慌张。
“是不是钱就能救的你朋友?”
“那当然,至少我可以保释他或者是帮他请律师。”
“是不是用钱摆平这件事后,你就不再心烦了?”

我呆了,静如神,洞悉一切秘密。
我才知道,女人,我从来都是一知半解,就算天天睡在一起。

如果童能平安出来,一点事都没有,我会怎样?和童复合?静怎么办?我能也认为童无罪吗?
如果童判个十年八年,我会怎样?给童送牢饭?然后等她出狱?
如果童判个……
不敢往下想了。

“当然。他出来了我还心烦什么。主要是朋友嘛,犯了这事又不像别的事,不能问他家要钱,只能靠我帮他想办法。”
我装成轻松的说。反正,打死不承认。这是我的生存本能。以前靠这招,骗了童很多次。
“你保证?”
“你今天怎么了?你拿不拿啊?你不拿就是让朋友觉得我太不义气了!”
只有我比她更理直气壮,静才会真的以为我理直气壮。
“这里是五万块定期。不过,我希望是第一次也是最后一次。”静直视我的眼睛,她原来也可以这么强势。
“好,我把他救出来,就让他立刻还钱,不还就告诉他老婆去,而且,和他绝交。老婆,别生气了。”我嬉皮笑脸着,“不过,五万可能不够,最近公司也需要钱发工资,你再拿五万吧。”
静望着我,不说话,不动。
“好老婆,再拿五万来嘛,这些都会还的。”
静突然抽了我一耳光。

我呆了。

童最凶的时候,只是扑过来打我,咬我,踢我,从不敢抽我耳光的。
倒是我,有次被童打后,觉得她太横蛮任性,反抽了她一耳光。
都不记得起因是什么事,只是当时气昏了。

童捂着脸,顿时跌坐在地上,嘴唇连着下巴抽搐:“你打我?”
然后开始号哭,哭到全身发抖。
我不忍,心碎,抱着童。
童不让,踢我。
我的心疼又转为烦躁,她就是这样,什么柔弱她什么不做,怎么强悍她就怎么做。
干脆不理她。
童一边哭一边开始收拾东西。
她两眼通红,把衣服、包等一股脑塞进旅行袋,把抱抱熊夹在腋下,还不时用手背抹一把泪水。

她还是个孩子。难带吵事的孩子。
心酸,拖住她。她不让,好倔。我拦不住,又不敢再用暴力,只得把童的衣服强行脱掉,并扔到开着窗的客厅。
看她光着身体怎么离家出走。
童又羞又气,尴尬的蹲在地上继续哭泣,企图遮住三点。

我再也抵抗不住视觉诱惑,欲望膨胀,即将爆发。
我把哭的泪人一样的童,压到床上。
终于随着我的动作,童的哭声越来越小,最后变成了喘息。
事后虽然两人都满足,可激情之前的这些事,在我们心上都划上了伤痕。

(11)
此刻换我捂着脸,对静吼:“你打我?”
却不敢动静一根指头。
因为心虚。

真是报应。

静直视着我,一点不怕我瞪的溜圆的眼神:“你嫖一个不够,还同时嫖几个?”
我楞了,原来静以为是我P C。

“你说什么啊?怎么是我嫖了?”
“不是吗?那你倒说说你那个朋友叫什么名字,是什么身份,住哪啊?”
我语绝,真是回答不上来。

“我已经够给你机会和帮你留面子了。你要五万,好,我给你,让你摆平就当什么也没发生过。可你要十万,嫖一个鸡,罚款加保释金加请客送礼怎么说也要不了十万吧?你肯定要不是同时嫖了几个,要不就是还做了些什么更龌龊的事。”

静冤枉了,错打了我,我却什么也反驳不出。垂下头去。
“我真的没有去嫖,你相信我,静。反正我就是需要十万块。别的你什么也别说、别问了。”

静不理我。转身准备出门。
存折都在静手上,童自己的帐户都被冻结了,急等着我的钱救命。
除了我,谁还能拯救她?

我扯住静,“扑通”一把跪在她面前。
“静,我对不起你。我是出去嫖了,都是作生意的那些朋友拉着我去的。至于为什么要十万,细节你就别问了,实在是因为我做的事太龌龊了,怕说出来恶心你。静,我求你,给我一次机会,原谅我吧。我保证,以后再也不会了。”
静还是没动。
“我错了,对不起,我错了,对不起,我错了,对不起……”我继续跪着喃喃的念,边扇自己的耳光。
我是错了,我从一开始错就大了。

在童面前,无论错多大,从不向她道歉的。顶多,说句,我们都有错,大家一起改吧。童听到这句已经很满意。
因为童爱我超过我爱她,无需道歉她也会原谅我。

静终于递给我另一个存折。说:“你记住,这是第一次,也是最后一次,你自己亲口保证的。”

我捧着两个存折,人生第七次,渗出了泪水。
只差没给静感激的磕个头了。
存折的钱,至少有3/4是我赚的,我却只能求着静给我。
谁叫她是我妻子呢?

静从头到尾,没哭,没闹,音贝都没提高一下。
我却乖乖的认错。
童总是哭,闹,嚎哭的隔壁都听见,我也没低姿态说过道歉。

我拿着钱,去联系市里最好的律师,去找威。
每天焦急的等待威的消息。
一边夹起尾巴做人。
按时上下班,推掉所有的应酬。
可下班成了痛苦。
因为静开始不和我说话。
她还像以前一样给我做饭,贤惠的操持家务,可就是不和我说话,偶尔说一句,还像恩惠。
对,她以博大的胸怀饶恕了我的罪,是开恩。

我们两从吃了晚饭,到关灯睡觉都没有说话。要不是心里装着童的事,我真可以被她憋死,静不说话,就是绝对的冷战。
每当我欺负童后,童生气,也是要作出不理我,和我冷战的样子。我索性睡觉,可她又会憋不住了,挠挠我的脚板,抓抓我的腰。等我起身,她又装着一本正经在干别的事。几个回合,冷战不攻自破。
所以童的冷战,最长也就是半个小时。

我想像处理和童的僵局一样,在床上,抱着静,一起运动,达到“床头吵架床尾和”的效果。可静睡前只淡淡的说了句,“也不知道你当时有没有有戴套。去医院吃一个疗程的药吧。”就直接到客房去了,和我分房睡。
童要显示她的主权,顶多是抱着枕头睡到床另外一头。碰到我烦她,睡到客房的情况,十五分钟内她一定忍不住,拉下所有的面子,来敲门,把我拽进我们的卧室。

原来冷漠真的很难熬。

幸亏,静第二天就和同事一起飞去鼓浪屿度假。她收拾行李的时候通知了我一声。是,静现在是位于我上,要做什么不需要和我商量。从此,我觉得静所有对我的好,都像是赐予。

也好,大家都免得尴尬。

(12)
在静回来前,童被无罪释放–证据不足。
最有利的反面证据就是,童公司的帐号上,除了周转的钱外,就没有一笔大数目。行贿是为了什么,获益吧,每单生意都是微利甚至是无利,行什么贿。而且童的帐目也一清二楚的说明如此,当然,那是假帐。而收贿的人,自然也是死不承认。
最后,不了了之,放了童。
这中间,最起作用的就是威。
我负责出钱,具体事宜都由威操作。可以这么圆满的救童出来,足见威的神通广大。

威大专毕业后就当了一名户籍民警。没有后台,没有财力,在短短几年混到公安的这个职务,是很不容易的。要知道,没有背景,在白道不好混的。
威唯一不顺的是感情,每次都是落花有意,流水无情。总算谈了个朋友,买了房子,准备结婚,女朋友却在毫无征兆的情况下,提出分手,原因是那句经典的“你太好了,我配不上你。”
威痛苦大半年。
后来慢慢得知,其实是女朋友另有所爱。

威喝醉了告诉我们,那男人论能力、性格、工作哪方面都不如自己,唯一,比他长的高。
忘记说,威身高只有一米六几,别说是他们局,可能全市公安民警中都算最矮的一个,当初招聘时,威是给体检的医生送了厚礼才过关的。
身高,一直是威的忌讳,也是自卑的心病。
从此后,威再也没有正式谈过一个女朋友。

威和我一起接童。
挨过这些日子,童二十几岁的人生,又增添了一页沧桑的阅历。
她的身形更加瘦削。好象又瘦了。
童无力的望着我们说:“我想回去洗澡、睡觉。”
威识趣的连忙说:“我开车回去了。你陪童回家,好好照顾童。”
这段时间威一直没回去,假也没请,晚上就住在童的家。
威确实够朋友。
所以我才敢和他一起投资彩票点,在威的城市。


而且威知道我有多想和童单独在一起。
我想童像以前那样,头枕着我的肚子,躺在床上说话。
说这两年发生的事情。

“今天晚了,开长途危险。你陪我回家,明天再回去吧。”童扯住威,不让他走。
“我听威说你帮我垫了一笔钱。到时我托威还给你。真的很谢谢你,分手了还能这么仗意帮忙。你回去吧,我们先走了。”童轻轻的对我说,然后拉着威就要走。
我杵着,不知道该怎么办。

童现在根本不想再单独和我呆一分钟!
也许,童不再爱我。她住在我们的家,只是习惯而已。
也许,两年的生活,连串的打击,她心里已经装不下对我的爱了。

“这样吧,今天就听童的安排,明天你们两和我一起回去。你呢,就顺便去彩票点对对帐,都两年没去看过了,童呢,就去逛逛,散散心。” 威建议说,化解了我的尴尬。
童不出声,算是默许。

第二天出发,童的气色好了许多,不再蜡黄着脸。我和威轮流开车,聊着二十出头时的愣头青事,中间有几次,童还加入,帮我们纠正夸大之处。这些事,早在我和童恋爱时就间断都告诉过她,她一直都记得,比我还清楚。
童还是爱着我的。
只要心照不宣,小心的屏蔽掉最近2年的回忆,就可以当什么事也没有发生过一样。
我和童甚至还互相取笑,融洽得仿佛没分手。
她依然是我的女朋友。

下午三点钟到达。
威急着要去单位报到,要我和童一起,自己安排活动。我们晚上再碰面,一起吃饭。
多好的安排。
童却抖抖嘴巴,好象犹豫了一会,说:“他要去彩票点,我去逛街,我们不一起,电话联系吧。”

我以为童是当着威的面不好意思,嘴硬,一如我以前。等威一开车,我就拉着童的手,把她搂入怀里。
如果不是在马路上,我一定会吻童。
以前每次久别重逢,我和童都会变得更亲密。

这次童却无声的推开我。
“你别这样。我自己打车走了。”
童真的飞快拦下一部出租车,剩我一个人。

威从单位回来,陪我对帐。可童的冷淡,让我心情颓丧,帐目也看不进。索性拉着威早早的离开,先去喝点咖啡。

还没坐定,彩票点的店员打电话给威,说附近起大火,让我们回去看看。
“你去吧,一般起火,最容易趁乱出事,出事局里肯定要找我。我回去待命。”

附近的店面烧了一大片,死了两人,十几个人重度烧伤。
不过彩头好,火烧到我们彩票点前就被扑了。
店员告诉我:“刚才老板娘童也来了,她可能以为我们铺起火了吧,哭着喊着往里冲,拉都拉不住,后来还是被消防武警拖出来的。”

我笑了。开心的笑了。
不错啊,童,你也学会了我的本事,轻易就把我的心情撩拨得一下失落一下振奋。
你在我面前装的淡漠,可你以为我出事的时候,却泄露了真正的心迹。

店员问我笑什么,我说,笑童那副哭着喊着、歇斯底里的样子,她倔起来,力气很大,确实是一般人拉不住。还笑她虚惊一场,扑错了。

就像我以为童会坐牢判刑,拼了命要救她一样,童怕我被火烧着也拼了命要冲进去救我。
有些爱,要到永绝才知道可贵。
已经知道爱可贵,但我不要和童永绝。
不管她两年生活有多霪乱,不管我已经结婚,要和童重新在一起。
只是,静没有错,我怎么可以提出和她离婚?
不离婚,难道金屋藏娇?童的性子,怎么会做二奶?
我没答案。不管那么多,但今晚,童一定是重新属于我。

我打电话给威,问他借车,告诉他晚上各自吃饭算了。威说也好,反正晚上要加班没时间陪我,车别人开回去停在他家楼下,我去取就是,钥匙在房门口的信箱里。
路上,我定了五星级酒店的套房,77朵红玫瑰–除了那次向童求婚,我再也没有送过花给她。还买了童最喜欢吃的烧烤、麻辣小龙虾和一对红酒。
童不能吃辣又爱吃辣,辣的时候总是一边伸着舌头,一边大力哈气,然后喝点小酒解辣。我要她坐在我腿上吃,对着我的脸哈气。

走到威门前拿钥匙,听见房里有电视声,开的很大,还能听出放的是韩国片。
威从来都是一个人住,也没听说他家来了亲戚或朋友,莫非,有贼?还是,他找了女朋友?
我用和车钥匙套在一起的房间钥匙开了门。

“你不是说你加班吗?”
是女人的声音。
只穿着内衣的童,走出来。

童没想到是我,惊慌失措。沙发上是威和童今天穿的衣服,显然脱的时候迫不及待,杂乱的摊着,地上,还有撕开的避孕套包装……
  
(13)
我蒙了。
“你和威上床了??!!”
童拣起件衣服,穿在身上。
讽刺,脱了衣服见我哥们,穿着衣服见我。

“你怎么来了?”
“我不来,还不知道你们的丑事!”我指着童的鼻子怒吼。
“我们有什么丑事?男未娶,女未嫁,都是单身男女。倒是你,别人的老公,有资格指责我吗?”童挑衅的把我的手拨开,把脸凑到我面前说。
“你是因为我现在有老婆,报复我?”
“报复什么?要报复早在分手的时候就报了,还等到现在?而且,你以为我还是过去的童吗?”
童一手拿起遥控器,一手捧着苹果啃,坐在沙发前看电视。
她在威的家里悠然自得,就像当初在我家一样。

“说,为什么是威?为什么偏偏是威?因为他把你从公安局救出来?”
“按你的逻辑,救我,你还出了钱,我也应该要和你上床了?”
“你怎么这么霪乱?!!”
“不是,”童停下戏谑的表情,严肃的对我说:“不是霪乱,是认真的爱。”

我疯狂,彻底失去理智。狂奔到楼下,我拿出车里的东西,摔到童的面前。
童还是在嘲笑我,一边捡起东西。
“你怎么一点都没有变,火气还这么大,像小孩子乱发脾气。不是说你找了个既漂亮又温柔的老婆吗,也没调教调教你?”
对,我不气,我不怕。我还有静。
“是啊,我买这些东西就是特意要送给你们的。花,给威,让他捧着向你求婚。吃的,你们下酒,还有红酒,你不是最喜欢喝点小酒了吗,喝完了继续再做〈!—->爱啊,多来劲。你这种饥渴离婚少妇碰到一样饥渴又找不到女朋友的威当然一拍即合。希望威穿我旧鞋穿的合脚,祝你们生活美满,早生贵子。哦,顺便问你一句,你还能生得出孩子吗?你要是生不出了,我和威关系这么好,到时我叫我老婆多生一个,认你做干妈……”

“啪!”童给了我一耳光。
她负在沙发上痛哭起来。
“为什么你还要伤害我?两年了,为什么见面你还要伤害我?”
童用双手遮住脸,抽泣着。

她和威发生关系伤害到我,为求自保和反戈一击,我也要伤害她!
我真的给了童狠狠一刀。两年了,并也没把握可以再伤到她的心,为起效果,我用了最毒的话。

童一边哭一边哽咽着重复一句话:“为什么你还要伤害我?”
我们吵架,童喜欢和我理辩,可当她是非对错、道理,都不讲了,只哭着说同一句话:“你为什么要这样伤害我?”的时候,我知道,她是极度伤悲了。
有一次,童哭着说:“你凭什么这样伤害我?你自己知道你是凭什么可以这样伤害我吗?你是凭着我深爱你,所以你才可以肆无忌惮的伤害我啊!”
那次,说的我灵魂一颤。

可是童,我真的还有本钱伤害你吗?
推开门,我拂袖而去。

直到第二天静回来,我的脑袋一直都发炸。
去机场接静,她看来情绪很好,对我笑着讲见闻,可我没有力气回答。
“你怎么了?”静在我额头摸了摸,“你发烧了!病了就不用来接我嘛。”
静似乎被我感动了,脸上流露出无限温柔。回家,照顾我躺下,她给我拿药、做饭。我昏昏沉沉的发着烧,做着胡梦。
我梦见童扯我的手说:“你快起来,你是装病,你以为自己是楚楚可怜的黛玉啊?我
才是野蛮黛玉。”
我一向身体很好,几乎没得过病。童倒是抵抗力差,动不动就感冒,这里不舒服那里不舒服,我笑她是“野蛮黛玉”。
“你像林黛玉一样娇弱,可又不温柔,比韩国那个野蛮女生更野蛮,所以这个野蛮黛玉的名字最适合你了。不过,电视里那种身体弱不禁风的女生,怎么没有一个长的你这么丰满的,全是骨感型的?”
“我这是虚胖。”童撅起嘴巴回答我。
梦里,童拉不动我,索性耍赖睡到我手上。
“你怎么还是这么吵事,我难得病一次也不放过我,你去打游戏也好,看韩剧也好,别来吵我休息嘛。”
“我睡在你旁边不吵总可以吧?你抱着我应该睡的香些啊。”

不要再梦到她了,也不要再想她了,再怎么心痛,再怎么有缘分,童终归和我不是一路人。这个,我应该在2年前就清楚。

我翻个身,接着迷迷糊糊的半睡半醒,还是想起了很多和童有关的事。

今天,彩票点的店员叫童作“老板娘”,这个店员,是在我和童分手后才到店里上班的,他怎么会知道童以前是我女朋友呢?其实我误会了。这个“老板娘”的“老板”,指的是威,而不是我。
威一定经常童去,所以和店员都熟悉。

这两年威借给我的钱,也是童的吧?我早就应该想到,威拿着公务员的工资,哪里有那么多钱借给我呢?而且,他也没有催我还过,再是哥们,不是因为他和童有这么密切的关系,又怎么会如此大方?

是了,不然威也不会那么心急火燎的班也不上,赶去救她。
威不是早就警告过我不要再去找童了吗?
前天晚上威想制造我和童单独在一起的机会,也只是想让童和我说清楚一切吧。

想到我做生意的钱可能是童陪别人上床换来的,我的头就更疼,心也疼碎了,碎成千疮百孔。
记得她曾说,如果有一天我们真分手了,她希望我能生活的很好。
“我希望我可以嫁给千万富翁,高矮胖瘦、多大年龄都无所谓,只要他给很多很多钱我。你不是一直说我不贤惠能干还老和你吵架吗?你呢,就去找个温柔体贴的女孩做老婆,我每个月都给你好多好多钱,让你们生活的舒舒服服的。”
“神经病!”我当时是这样回答童的,“我不成吃软饭的了吗?难道连老婆都养不起向你要钱?再说,你能嫁个百万富翁就烧高香了,又不是多美,还想嫁千万富翁?”
我只当童嫌我不会赚钱,从来没有细想过这句话背后的含义,童当时是已经爱我爱到宁可牺牲自己,也要成全我和别的女人的幸福。
我当她发神经的话,竟都一一实现。
我从威的手里,接过了童出卖自己信仰和身体的钱,做起香料代理的生意,自己和静过上中等收入水平的生活。

孽缘!
我不愿说这么老气的词,可再没有比这更恰当的词可以用来形容我和童的关系。
童爱上我是孽缘!在童任性、我没有学会包容的这个错误的时间,遇上了不该爱的、错误的人。
童离婚后带着满身伤痕投入威的怀抱,何尝不是件好事?至少,有人继续疼她,爱她,而不是伤害她。
我是给不了童幸福的男人。为什么?根基不好。一开始,就根基不好。童的粘人、任性给我留下了随时躁狂的因子,我回之的自私冷酷也给童留下了深深的伤害。
当然,我一直都爱童就像童一直都爱我一样。
只是,童任性,我便以冷酷自私对她,她虽然表面上用更多的退让、更低的姿态挽留感情,可内里受伤的心却不能平衡,不久便又流露出偏激任性的心态,而我,继续以更自私冷酷的方式来还之……

如此恶性循环。
直到不记得爱,只有憎恶。
一旦真正的分手,却又记起爱。

因为爱得痛苦,才愈加铭心刻骨。

这不是孽缘又是什么?


高烧退了,一切都会好的。
我对自己说。

我和静开始恢复以前相敬如宾的生活,好象什么也没有改变。
不再联系威,也不愿想起童。
只是听到放蓝心湄的《不怕付出》,会心里一颤,牵动全身。

不怕付出
le cinquieme jour de i’an 2000, je te quitte, je suis disparu
(2000年的第5天,我要离开你 消失!)
我发现我真的是再也无力
触动一颗已经没有我的心
所爱的人不留恋的表情
是最让人心凉的一场雨
总相信我们的爱能走下去
有笑有泪才会动人难忘记
可惜只有我一个人相信
改变不了两个人的分离
爱你怎么会是个错误
从甜蜜一路到痛苦
原来未必越拥抱越相处
就了解彼此越深入
爱你怎么会是个错误
从天真悲伤到清楚
感情不是够努力够付出
就一定留得住幸福
le fin du siecle nous a quitte, comme deja-vu.
on n’est plus affirmatif de la naivete, de i’eternite, ef du bonheur.
je trouve qu’-il n’y a rien que je peux fire, vraiment rien.
c’est toi, ma chere toi, qui n’arrete pas de rever.
mon innocence n’est plus la, depuis lentemps.
llne reviendra, ni mou affection, ni ma passion au-revoir.
(世纪末已离我们而去,成为似曾相识
我们对于天真 永恒及幸福都不再确定.
我发现我真的没办法,
是你,亲爱的你,不能停止作梦.
我的纯真早已逝去,如同我对你的爱与欲)

那是童最喜欢听的歌,睡前,躺在床上,她会把MP3的耳塞,一人耳朵里塞一只,强迫我听着,而且还是循环播放。
“昨晚你注意听里面的歌词了吗?”
“没,太催眠了,我一听就睡着了。”
我想忘却,可是记得。

童说,这首歌,是她的代表金曲。


静热衷旅游,我怕她搬出嫖妓的杀手裥,而坚决支持。还得感谢她没有告诉我母亲,以传统女性的美德,帮我留住脸面。
我照常工作,目标是把全省的总代理权拿下。
童被检举一次后,恐怕不会再像以前那样操作。现在,广告这行也不好做。不过,她就吃老底,应该也衣服无忧。还事,威能帮她摆平。
除此外,生活重复,时光流逝,一切朝前。
这大概就是人生的本质:恬静,平淡,真实。
简单也是种幸福。
我以为,这样到终老。
直到,静拿来报纸。
“你看,这不是你那个哥们威吗?他被捕,已经开庭了。”
我头也不抬。
“你只见过他一次,看错了吧。他在公安局,一向是他抓别人,怎么会别人抓他?”
“真的,你看看,标题就是‘执法部门干部以身试法,公安干警涉嫌洗黑钱’,正是XX市。”
我扯过报纸,没错,是威,垂着头,站在法庭的照片。


(14)
平心而论,没有童的话,我和威还是很好的哥们。威和我虽然性格不同:一个敏感好强、一个大而化之, 可我们相处的不错。我做销售,威对做生意、赚钱很感兴趣,谈话投机。威自尊心很强,对身高特别介意,恋爱失败后把全身心的投入工作上,甚至–非常钻营–这也没什么不好,现在这个社会,需要如此才能混出名堂。
知道童和威在一起后,我还想,威除了矮,其他都是配得上童的。他也没有我好玩、粗心,应该可以给童幸福。
可是,还没过多久,怎么就出事了呢?
这次和童被拘留不同,威已经上庭,看来,判刑是八九不离十,只是刑期长短的问题。
童怎么办?
第二次失去爱人,她会坦然接受还是放纵自己?

“威出了这么大的事,我居然不知道,我得去XX市,马上动身。”
“好啊,我帮你收拾收拾换洗衣服,你不用急着回,多帮帮他尽点力。”
静还是这么通情达理。

去之前,我先到了童的家。
不知道童是在XX市提心吊胆的等待审判结果,还是留在自己家。不过,先去一趟,童如果在,还可以和我一起,带我去见威。
童竟然在家。她正在收拾家里为数不多的几样威的东西。
童真的变了,从她脸上似乎看不出一点受打击的痕迹。
“威出大事,你怎么也不告诉我,有什么我帮的上忙的吗?”
“没有。”
“你是他女朋友,怎么也不看着威,让他闯出大祸。”
童抬起头,瞄我一眼,冷笑着“哼”了一声,继续做事。
“这些东西,是清着给威送去的吧,正好,我也想去探探他,我们一起出发,现在走,可以赶在晚上到。”
童拿个塑料袋把东西包好,然后丢到楼道的垃圾箱里。
“要去你自己去,我不去。”
“你怎么变成这样?和威吵架了?他现在是最需要你的时候,你还任性,他多伤心啊……”
“你是想说,我当年就是这么任性伤你的心的?”
“我们过去的事就不提。去吧,我们一起去看威。”
“我们没吵架,是分手。”

童冷血,无情。
“当初你被关的时候,威怎么救你的,你还记得吗?”
“你不提我被关的事情还好,你提,我更不会去看他。”
“怎么,威费了那么大劲你最后才能无罪释放,你还觉得他做的不够好?”
“是……”童望着我欲言又止,“算了,不提了。”
“就是,你摸着良心说,他还要怎么对你,不管他判多少年刑,你以后还跟不跟他,至少现在不能分手啊。你这女人怎么这样绝情、这样现实!我算认清楚你的为人了,幸亏当时没和你好,我就知道你是这样靠不住的人,真是大难临头各自飞。”
童皱起眉头,看着我:“你说什么?我是靠不住的人?”
“你难道靠的住?和我分手两个三个月不到就嫁人,威还没判刑就和他分手,你最靠的住了!”
我讥笑她。
“我们分手三个月我就嫁人?”
“不是吗?你还准备狡辩?”
“威告诉你的?”
“是了。”
童突然鼻头一酸,流下眼泪。
“他原来真是这种人。我问你,要是分手三个月的时候,威是告诉你我准备嫁人,你会怎么做?会来找我,要我别嫁吗?”
“怎么了?”
“你先回答我。”
当然会来找你了,不过,你如果真是爱,我会祝福你,童。
这样我也心安。

童激动,几乎站不住。她扶住我的手,“真的?你真的会来找我?”
我叹息。
“当然,自己曾经的宝宝要嫁给别人,肯定会来问清楚。”
童哽咽的更厉害。
“如果你来找我,我告诉你我不爱那人,只因为要激你出来,而且有了孩子,肚子大了瞒不住,想找个人结婚做替名的爸爸呢?”
“生活哪有这么多如果。”我怕,不想提,不想打开尘封的感情。

“如果这一切都不是如果呢?”童哭出声来。

(15)
每次我们分手,不会超过一个月我就会哭着来找你,可最后这次没有,不奇怪吗?因为,分手的那天,我已经知道自己又怀上我们的孩子了。
还记得吗?那天你说了很多重话,说看不起我,这么大人了依赖心还这么重,什么事都依赖你。我想,好啊,我就不告诉你我有孩子了,分手也一个人扛起来,到时你一定会觉得我很坚强,表扬我的。
这是唯一一次,我不怕你说要分手。
我傻笑着想:分手?你是逃不出我的五指山的,我有妇科病这么难怀上都让我又怀上了,就像上上一次分手时,不小心把你送的求婚戒指冲到下水道又捡回来一样难得,都证明我们注定是分不开的一对。
所以,当你是耍小孩子脾气,不理你就好了。
不是说,男人都是长不大的孩子吗?
你要分手,就让你闹一下,自由几天。我也要学着宽容,以后才能照顾你们两个小孩子。
有孩子,母性会让人成熟。

可是,就这样过了2个多月,你一直没来找我。
可能,你在等我先打电话?
可能,你真的不爱我了。
我不死心,又拉不下面子。我想的你要命,又不想被你瞧不起–女的,怎么好意思每次都主动去找男的呢?所以我找威,要他转告你,我要结婚了。

后来,我才知道,他那时已经喜欢上我。应该就是这个原因,他欺骗了你,也欺骗了我。
到了四个月的时候,威告诉我,你结婚了。
这个,是真的还是也是威撒的的谎,你真的是才分手四个月就结婚了?

我无颜,回答童。

当时,我觉得天塌了。
什么都没有了。再做什么努力都起不了作用了。
我幻想很多次的复合,彻底变成不可能。
你结婚,是真正的和我分手了。

童吸了一下鼻子,深呼吸,抓住我颤抖的手。

我很任性,你不是经常这样说我吗?如果那时,我不那样任性,去医院引产,我的人生可能也不会这么……这么……灰暗。
我很想要孩子,你知道的。不要,我怕这辈子可能都怀不上了。
而且,最重要的是,这辈子都没机会怀上你的孩子了。

我决定一定要把这个孩子生下来。
学校管的很严,未婚生子,肯定不行。为掩人耳目,我在网上到处发帖子,征求网友假结婚,当孩子的代名爸爸。结果,真让我找到。就是威给你看过照片的那个人。
当然,天下没有免费的午餐,他要五万元钱。
他可不是什么海归博士。
我不想让你看贬,编的。

我是够任性的吧?
就因为我任性,产检都不去检查,我怕妇科病影响孩子,怕医生说孩子不健康,怕别人劝我不要这个孩子了。
我连我爸妈都骗,我骗他们早就和这个“名义老公”好上了,孩子是他的。

孩子生出来,折腾我半死。
每次开始和你做〈!—->爱的时候,都嫌你的粗,弄的我疼,你记得你还吓唬过我,说我火腿肠进出都怕疼,那以后要生孩子,头有皮球那么大,岂不要疼死吗?
真的很疼,疼到以后割伤手,摔伤脚这种事都不觉得疼。
要撑住,一定要把孩子生出来,带给他看。
我在产床上,靠的就是这个信念坚持下来。

当医生把孩子抱到我面前,说:“是个儿子,七斤八两”时,我哭了。
你不是一直不愿意便宜将来的女婿而不想要女儿吗?
要是当时你在旁边,一定会很高兴。我好想亲口告诉你,真的,我给你生了个儿子。

我痛哭起来。
童拍拍我的肩膀,“这些都过去了,没事的,别哭,你一哭,我就没有主张。”
童竟然反过来安慰我。

我妈一直在医院陪我生产。可是当医生抱着儿子给妈看时,她呆了,然后,跑出医院,再也没和我说过一句话,直到现在也是这样。
后来爸告诉我说,因为妈看见孩子的那一刹那,就什么都明白了。
孩子跟你是一个模子刻出来的,单眼皮,肉鼻子,厚耳垂。
一看就知道,这个孩子绝对是你而不是我“丈夫”的。

爸对我说,童,你太任性太不听话了,你的悲剧,是自己造成的。
他说完,别过脸去,哭了。
我爸是什么性格,你也知道的,整天嘻嘻哈哈,年纪一大把还喜欢开玩笑。可是他,竟然当着我的面哭了。

我当时就像走火入魔,什么都听不进。除了我妈告诉爸的那句–“瞎子都能看出那是谁的孽种。”
我高兴,爸妈都能一眼看出来,那将来我带着孩子再碰到你,你肯定也能一眼认出自己的孩子来,对吗?
我不该看那么多言情片,傻痴痴的以为,就算你结婚了,以后只要有一天知道我生下你的孩子,还是会跑过来认我们。
电视里不都是这样演的吗?
但是那终究只是电视。
孩子出世不到一个星期,就发现心肺功能先天不足。都是因为我任性,怀孕的时候不做检查,妇科疾病带来的。我求医生一定要救活孩子,可是,没用,熬到17天的时候,宝宝死了。

宝宝死了,我也想死。
除了想死还是想死。
我不觉得生活还有任何希望。
我也不觉得上天对我有任何怜悯。
可能,这样任性的孩子,连老天也生气了,受不了,也和你一样,要抛弃我。
怀着宝宝的时候,每天去逛逛童装店,看看育儿书,做做胎教,没有你的生活也变的充实起来。和你分手,好象也没有那么疼。
是孩子让我振作。
是孩子给了我希望。
也是最后的希望。
现在,老天却把他带走。这一次,不知道还有什么能让我振作?

按约定,“丈夫”这时提出离婚,我却拿不出五万块钱。父母算和我脱离关系,是不可能向他们借的,自己也没有积蓄。
我提出分期付款,“丈夫”不同意,气急,把签的合同复印件寄到学校。
所以被开除。
不过无所谓,反正那时我也得了严重的抑郁症,上不了课,每天缩在房间里,不出门,不吃饭,不睡觉。
就是那时候,我瘦了二十几斤。

后来威出现了。
他每天守着我,陪我说话,喂我吃饭,劝我不要自暴自弃。

“我爱你。”
威说。
“从你开始告诉我你和他的事情,我就爱上了你。我恨为什么我就碰不到这么痴情的女孩。你越告诉我你如何爱他,我就越爱你。”
真的吗?那你爱听吗?
我问威。
“我想听,可是听的过程,真是种折磨。”
然后我开始又一遍一遍,祥林嫂似的,向他诉说。
威一把抱住我,“童,你别这样,你这样我看着心好痛。醒醒吧,他结婚了,回不来了。”
真的回不来了吗?
“是的。回不来了。你和我好吧,我不会让你受这么多伤,我会帮你疗伤。”
真的吗?
威开始脱我的衣服。我人格好象已经分裂,冷冷的看着他脱我的衣服,就像是脱别人的衣服一样。
威整整花了一个小时才进去。
原来,不是每个人都可以把性和爱分开。
面对一个我自己不喜欢的人,连原始欲望都没有。

(16)
也许是我做的不对,从一开始,我就对威有亲切感,不为别的,只因为他是你哥们。
和他一起,感觉就靠近你一点。
威是被我执著的爱吸引,可一旦真正和我生活,这也成了他最不能忍受不了的一点,因为,我不是执著的爱他,而是你。我说话、我哭、我笑,都是因为你,这让他觉得自己只是生活在你阴影下的人。
威好强,他怎么受的了天天被所爱的人无视,于是不平衡,慢慢积累到变态,由爱变恨。
其实我和威,是相似的:我爱着一个已经分手、结了婚的男人;而他,爱着一个从来不爱他的女人。
我为了这个男人痴狂,威因为我而变态。
威从开始温柔诱导到半强迫到最后彻底发泄,完成了对我由怜爱到仇恨的过程。
他爱我。
为了让我有工作,有新生活,威拿出六万元钱,给我开了个小广告公司。并利用关系揽到肯德基一个促销的业务,虽然不大,却可以稳定的每个月进帐1万多。
他也恨我。
我听威无意中说起你想做香精代理,可是缺钱,就把赚的3万多全提出来,让威转交给你。
威气的脸都白了。
“你以为现在赚钱很容易是吧?不是肯德基广告总监的儿子在我手下犯了案子,他会把这个业务给你做吗?为了让他儿子无罪释放,你知道我怎么做的吗?我半夜三更溜到办公室改了口供!你知道要是被发现有什么后果吗?不光是工作丢掉,我还要坐牢!你知道我给你开公司的本钱是怎么来的吗?是我辛辛苦苦存了几年、从公务员工资里每个月每个月挤出来的!你知道存这笔钱是干什么用的吗?是我准备讨老婆用的!”
威不肯。他绝不肯把三万元拿去给你。
这些威从没和我说过,要早知道,我就不会开这个公司了。
我不值得他付出。

威从此变得气量更小,疑心更大,老是怕我私自拿钱给你,开始监视我,查公司的帐,动不动就威胁说要要回公司。
我只好开始寻找其他的业务,希望可以不靠他揽的业务赚钱,这样就可以明正言顺的把钱给你。
那段时间,我每天抱着黄页打电话,发传真到凌晨,希望可以接到更多业务。我找到一家新开的日化公司,他们要拍条10秒的广告片。算了一下,可以净赚十万。
十万,就能解决你做代理的资金问题。

这个公司的老总,是个顺德农民,典型的爆发户。我把广告文案和费用拿给他看,他推开,说不感兴趣。
“要美女,身材好,全裸,用我的洗发水洗头。至于制作费,我不管你赚多少,可报价一定要是最低的,如果还有人比你报的低,就不用你们拍了。”
我说费用可以保证是最低,不过,模特全裸做不到,就算我拍了,电视台也会禁播。除非,只拍背。
我当时在心里打着小九九,只拍背,都不用找专业模特了,肯定能把费用降到最低。
“只拍背……那可以露到哪个位置?”
“可以露到腰这。”我边说边给他比划着。
“你示范看看。”
“已经比给你看了,还要怎么示范?”
我隐约觉得不妙,老总的眼神不对。
“你少装样,出来做广告的女的,哪个没有附加服务?我告诉你,我这是给脸你,上次有个女的,房都自己开好了,请我去,可我嫌她长的又黑又干,没去。你嘛,别给脸不要脸,不愿意就滚!”
怪不的威说现在钱不好赚,我还以为自己本事,这么快就找到客户了,原来没有这么好的事,都要付出代价的。
我木着考虑了一下。
我已经跟威上过床了,就算你以后离婚,也不会再接纳我了,那我睡一个和睡十个有什么区别呢?何况,还可以靠他赚钱。
以前,男人趁我喝醉摸我的背,你都大发雷霆;以前,我上泡泡和陌生男人聊天,你都要我做三天检讨,何况跟别人上床呢?反正我已经回不了头了。

“别说了,童,别说了,我求你别说了……”
我把脸埋在童的胸怀,泪水浸湿了她的前襟。
我知道,她要说到十万元是如何用肉体换来的。我不愿意再听下去了。

“我要说。不说,可能你一辈子都会说我霪乱。”
童,真的别说了,你多说一个字,就像在我身上就多割一片肉,我知道,都是我害的。我是最没有资格说童霪乱的人,可我偏偏指着她鼻子说了。

“现在你老是说我霪乱,是不是在想我接了多少单,就跟多少男人上过床了?我没有。如果真是我脱一件衣服就能换一个单,那就好了。顺德农民把我带到会议室,关上门窗,坐在主席台上,要我把衣服脱光。我就站在他面前,在他注视下,一件一件脱着。你记得吗,和你在一起三年,每次你要开灯我就不愿意做了,一直都不好意思在你面前一丝不挂,现在,我却要在一个几乎陌生的、矮胖的男人面前主动脱光衣服。”
童缩了下眼泪,冷笑着。

可是,你知道吗,我耻辱地光着身子站在他跟前,他竟然说:“操!你生过孩子的!我看你身材好还以为嫩,搞半天已经生过孩子,那我还不如回家抱老婆去。”
他看见我生我们儿子的疤和妊娍纹,对我没兴致了,把拉链拉上起身要走。我光着身子,跑过去抱住他说,老总,别走,我会很多姿势的,虽然生过孩子,可下面很紧的,你给个机会试试看吧。
童泣不成声。
我哭的喉咙都嘶哑了。

我是不是很贱?比做鸡的还贱?我贱到这样求他,可是那个老总还是把我推开,说:“去去去,看见你那道疤就没兴致。”可能,这让他想起自己家的老婆了吧。我木木的穿上衣,想着,还以为自己有资本,有吸引力,原来已经沦落到脱光衣,男人都没有兴趣的程度了。
之后一个星期,再也没找到其他的业务。我只能回头再去找顺德农民。去之前,特意到最红的夜总会带了个头牌小姐出台。这样,才终于搞定。
那条广告,模特也是自己做的,没有露脸,只拍了个背,这样我整整赚了十一万。
就是那条一年前天天在有线电视台滚动播出的“亚宝亚宝,洗去灰尘、油脂、头皮屑,只留爽滑在心间”的广告,你看过吗?那个3秒钟的背部特写,是我。

童脸上挂着泪痕,还做出广告里的动作,拼命想逗我笑。
我怎么会没看过,那是静天天追着看的《孝庄秘史》的片头广告。
只是,谁会想到,电视里那瘦削的背部,会是我最爱、被我抱了三年的女人的身体!

(17)
童更靠近我的身体,把脸挨着我,挤出一个笑。
这个笑已不像以前,那是正版的山花烂漫。

从此,我学乖了,我学会了男人有些什么癖好、喜欢玩什么花样,就去迎合;我学会了先脱衣服自暴其短–和那些身材曼妙的小姐比起来,这样反而可以保全自己。
威对我的事有耳闻,他不敢相信,质问我–那时他心理已经不平衡,开始粗暴的对待我了。
我也反感他,所以撒谎说,对,我是和每个客户都上过床了。
威扬起手要打我,可是,最终捏成拳头,狠狠的砸在玻璃窗上,流出血。

童叹口气。
威就是这样,越是心有芥蒂就越是压抑自己,如果不这么压抑,他心里就能平和些,也不至于后来爆发。

威,吐出几个字:“你真是有毒!你把我当什么?凯子?当初为什么要留下来和我在一起?”
只因为你是他哥们。
我回答威。

人刻骨的爱过一次,又伤心到绝望,会变,变的没灵肉,是吗?
我知道威是真心对我,我知道他除了矮没哪样不好,可我就是对他没爱,怎么办?
我知道这样回答,肯定更深的刺伤了威,可当时我觉得无所谓,麻木了。
除了你,对任何人都麻木了。
除了和你有关的事,对任何事都提不起兴趣了。

从此,广告公司赢利的每一分钱,都被威转到自己的帐号上。
他通过经济上的获得,来平衡感情上的失去。
他纵容我给别人性贿赂,然后自己得利。
有点像丈夫抓到妻子卖霪,没有责怪,反而同意了,只是M Y所得要上交自己一样,我和威就是这种病态的关系。
前前后后,到我被抓前,公司赢利的的360万,已经陆续被他拿走。
我对威说,他全拿走都可以,只是有一个要求,就是要拿一部分给你做生意。他这才给了你十几万,大概占五十分之一。

我抱住童,拂开她额前的头发,故作轻松的说:“威还误打误撞让你免了牢狱之灾。这也是因祸得福。”

童摇摇头。
你错了。
威已经变态到不是你认识的那个威了。他知道我们又见面,怕我们复合,于是写了检举信。
那封检举信是威写的。

我不敢相信听见的事实,皱着眉,摇着头。
这个动作让童以为我生气了,连忙摇着我的手。

你又要说我太任性了,是不是?我要是忍忍威,不那么任性的、报复性的伤害他,他也不至于做出这些事。
可是他每次压在我身上的一个小时,比死还难受,好难忍啊。
每次那一个小时,我不知要默念多少遍:你在哪?你在干什么?你怎么还不来救童,童好难受啊……
童再一次哭出来。

我紧紧的搂住童,紧到我的肉箍着她的骨头。
我真想把你刻进我的身体。
我怎么会再怪你呢。

威装模作样的来救我。
他问你拿了十万块吧,说是救我。

我点头。

威觉得反正在感情上是输了,不能在经济上再吃亏,最后连那十几万也不舍得放手,始终要变着法子要回来。
威很节约,没有什么花钱的嗜好,他就是喜欢把这些钱全存着,折子上写他的名字,看着心里就舒服、塌实。
后来发展到洗黑钱、贪污来敛集财富。
威拿我公司的钱,觉得是赢回了面子;他拿公安局的钱,觉得在个个比他高的同事前赢回了尊严。
你知道他被抓的时候,帐户上有多少钱吗?700万。

童深吸一口气,慢慢放松。
“这就是我两年来的经历,全说完了。我们两之间也没有瓜葛了……”我用嘴封住童的舌头,突如其来的袭击让她说不出话,睁大着眼睛。
童瞪大眼睛,还如两年前一样清澈。
只是,是被泪水清洁。

我脱去童的衣服,她乖乖的,像只小白兔一样随我摆布。在最后一件衣服脱去后,童抓住我的手,让我闭上眼睛。
她指引着我摸到光洁的皮肤,上面有蜈蚣一样凹凸起伏的粗糙的肌理。
“这就是我们儿子出来的地方。他可会折磨我了,非要破开肚子才肯出来。像你一样,折磨我最拿手。”
我睁开眼,吻上去。
“是不是很难看?”
不,一点也不。
“不过没关系,反正以后也不会再有机会在这留下疤痕了。”
我们还会有孩子的,叫三毛。呵呵,那不是和一个作家同名了吗?
童盯着我,“真的?”
当然,现在就让你怀。

其实我对自己并没有信心。
在听童说威每次压在她身上一个小时以后,在听她说面对其他男人脱光以后,我以为会不行。
以前曾设想要是知道童经历过别的男人,自己会是什么心情。
心如刀绞,难以面对。
可当这些真的发生,身体却兴奋的告诉自己,不,可以接受。
我彻底被自己震撼了。
原来,真爱一个人,可以什么都不介意。
真爱一个人,可以包容一切。
真爱一个人,可以忘记一切。
就算没有忘记,可以假装看不见。

童像个孩子,蜷缩在我怀里,搂着我的腰,沉沉睡去。
童说过自己一个人,只能睡着几小时。光线亮睡不着,声音吵睡不着,有点心事也睡不着。和我在一起,不管白天黑夜,能香香的睡多了。
“因为你给了我安全感,躺在你身边,好象什么事都不用去想。”童那时还做了一个我最喜欢的动作:皱起鼻子,撸着嘴巴。

此刻,我反而没有睡意。
和童激情后,搂着童,静却浮上心头。

(18)
和童经历这么多事情,谈恋爱的三年加上分手后的两年,五年时间我们却像相恋了五十年这么久。
不是童的执着,不知熬不熬的过五个月?
无论如何不再离开童了,除非她想和别人。

可静怎么办呢?向她提出离婚?静什么也没有做错,我说不出口。
不离婚?
别说静一定会察觉,就算能瞒住她,也对不起童。

直到童醒来,我也没有想出办法。
不如就这样继续。
做梦。
不如就这样继续,直到静发现,我不开口,静自然也会提出离婚。
静的性格我知道。
我甚至都可以想象出她如何冷静的签离婚协议书。
我爱童,超过静。
这个没有办法的办法,明显偏向童。静心思那么细密,不出三天就会发现。说不定,今天回去就要摊牌。

童醒过来,伸了个懒腰。“睡的好香。哇,天都黑了?你在不在这里吃饭,冰箱有净菜,我去炒炒就行了。”
“不。”我斩钉截铁的说。
童脸色惊变。但是她尽力克制住自己,勉强的笑着说:“那就算了。”
“不要你动手,我去做给你吃。”我又成功的开了她一次玩笑。
童张大眼睛,“真的,不骗我?”我点着头。
她高兴的笑了,扑过来,调皮的坐在我身上,用小屁股压我肚子。“你坏,你坏,……”
童突然不笑,哭出来。“你坏……你总是欺负我,让我心一下子提到嗓子眼,一下子又落下去……”
我用手勾住她的背,让她靠在我胸口。
“童,我保证以后不再欺负你了。我保证以后不会让你再痛苦了。”
“真的?”童从我胸口扬起头,眯着眼问。

站在曾经生活了三年的房间里,我拿着锅铲,万千感慨。
童从我腋下把头钻过来,双手搂着我的腰,傻笑着望着我不说话。
“别过来,乖,等下油溅到你脸上怎么办?那就毁容了,不美美了。”
童还是不说话,灿烂的笑。
夹起一片肉,“试试味道怎么样”,童抬高头,听话的张开嘴。
这么好的机会,怎么舍得便宜菜了,我把自己的舌头送进去。

我们是一对连体婴。
我们都是婴儿,2年停止生长的婴儿。

我和静说过要去见威,所以整整和童生活了两天。
我们牵着手去超市,我一包包拿零食,童又偷偷把零食一包包扔出来。
我们去电影院看电影,我在座位上趁机偷摸了童两下。
我们去泡吧,我命令童不准穿的太露。
我们睡午觉,醒来发现童没睡,定定的坐在旁边,用手抚摩着我的脸,眼睛红通通的。“睡不着,想多看看你,多摸摸你。”我把她一把扯下来:“好戚美啊。可惜我们还要在一起一辈子,这么戚美太浪费了……”
我们看电视,一人捧一碟自己炸的虾片。看到宋惠乔出来,童激动的一边含着虾片,一边口齿不清的扯着我说:“看,我就说我瘦下来像她吧,你还不信,现在像不像?”
我要回家了,童倔,非要送我。而且还赖皮,说好送我出门,结果跟着车一直送到我家门前。童不敢进去,坐在出租车里,眼巴巴的望着我一步一回头的走进去。
童,比静先,可现在却成了偷偷摸摸的第三者。
真难受。
这种离别真他妈难受。
我甚至有冲动马上和静摊牌。

静没有多问我去看威的情况。没有发现我的“外遇”。周一上班,除了要发给员工的工资,我把流动资金都取出来,交给静。
这样,除了公司,其他已经财产全部都在静手上。只等东窗事发,我什么也不要了,净身出户,算是补偿静。
中饭、晚饭,除了有应酬外,我一定和童一起吃。我和她缠绵到晚上11点,哄童睡了才回家。
当然童没睡着,她只是作出睡着的样子。
每次出了大门回头望,都可以看见童的房间又亮起灯。

(19)
我以为这样的生活,不出3天,静就会发现,岂料一过就是2个月。
静似乎很理解我“工作忙”,对早出晚归的丈夫见怪不怪。
周末我也去陪童,周六晚上还睡她那,甚至周日回家随便用个“打牌晚了,在XX那睡的”理由打发静,她也没有责难我。
难道,静早已经知道,却不愿说破,故意装聋作哑来维持婚姻?

我为静心酸。拿和童那种灼热的感情比,真不清楚和静冷静的生活是不是爱。但静是在我最失意的时候,解救了我。
我感激,也不想伤害她。
静是在我开公司之前嫁给我的,虽然后来生意做好了,在生活条件上从没有亏待过她,可静也算是我糟糠之妻。如果静真是装聋作哑,那她为我们婚姻所做的牺牲和所受的委屈,也是我一辈子补偿不了的。
静像母亲,包容我。
而童,像我孩子。

童从来不问我什么时候和静离婚,从来不问今天静发现什么了没有,她只是一次次默默送我出门。
再过一个月后如果还是这样,我也会主动向静提出离婚。
这种生活,不是享受齐人之福,是折磨。

周日,回家,晚上11点了,家里还没有亮灯。在我“加班”的时间,静想必给自己也安排了很多活动。
哎……
我叹息着,上楼,开门、开灯。
静吓了我一跳,她原来在家,正坐在客厅里,没开灯,不说话。
她发现了?看来我们婚姻真的到了要结束的时候。
我也不说话,把房门钥匙轻轻摆在茶几上,坐到她旁边。

静递给我一张纸。
不是离婚协议书。
抬头写着市妇幼医院。上面有我不懂的名称和符号。
“这是什么?”
“化验单,我得了XX,也就是性病中的一种。你老实说吧,是那时我叫你去看病你就没看还是现在还好这口?”

我错愕。
静得了性病!
静得了性病,那我肯定有,那童也肯定有。
我从25岁开始就不喜欢桑拿和找鸡,好久都没有搞过一夜情。
同时应付老婆和爱人,再要找别的女人,铁棒都要磨成针。

自己很清楚,三个人中,传染源肯定不是我。
不是我,那就是静或者童了。
是静?那她还会坦荡荡的拿化验单给我看?
是童?威已经关了几个月了,那童除我之外,还有别的男人?

我的头昏了。无论是哪种可能好象都不可能。可又只可能是这两种可能。
我真希望自己是晕了,也许哪天出去叫过鸡不记得了呢?
无论真相是哪样都会出乎我意料,颠覆我所了解的人性。
到底是静还是童?
到底是静还是童?
到底是静还是童?
我不敢相信静乱搞了还可以做出一副贤妻良母的样子,这么镇定的来推卸。
我不敢相信童乱搞了还可以做出一副痴情的样子,每天眼巴巴的盼我去,送我走。

在静面前,只能承认是我传染给她的。既然上次承认嫖妓,这次也只能承认传染性病。
也许,这倒是机会,离婚的机会。
可是,是不是童传染给我们的?如果是,离婚了,还和童好吗?

“上次我没有去看病,没想过这么容易中标。”
“你出去玩不要紧,还搞了病回来传染给我,是不是太没道德了?盗亦有道,拜托你以后出去乱搞记得带套!”
静字字有声,呛的我无话可说。
“我明天陪你去医院治疗。”我只得说。
“不是陪我去,你也要去,你是男人可能还没有症状,但是一定有感染,要一起治疗。”
“好好。”

我心情无比烦闷。一刻也坐不下来。
没想过这么乱的事情会发生在我身上。
我同时和两个女人上床,终于被报应,老婆和至爱,我竟然没办法肯定是谁传染性病给我。

如果是静得的,那我,真是看淡了她,她在我眼里一直是贤淑能干的好妻子。当初会和她结婚也是因为觉得静比童贤惠,现在她竟然让我绿帽子戴的没点感觉,厉害。
如果是静,结果那倒简单了,我反正是作好了和她离婚的打算。
如果是童得的,那童一直在骗我,所谓情深爱浓,只是她演出来的。童可以演的这么逼真吗?也许吧。她是很善于装小可怜的。
如果是童,我该再一次分手,回到静身边吗?我嫖妓染病的事,将一辈子成为婚姻的暗点。要是静以后也报复我出轨呢?
一个是老婆,一个是爱人,不管是谁,反正是我戴绿帽了。
这真是人性的考验。只要两个女人自己不清口承认,我也将永远不会知道事实,带着这样的疑惑与任何一个女人继续生活,都是种折磨。

我一个人在客厅反复走来走去。
这天,很闷。
我急,我燥,我烦。
我径直出门,去童那。
不管有没有结果,我要去问童。

在童楼下,她房间果然还亮着灯。我听见屋里还在轻轻放着电视。
“谁啊?”
“我!”
等了好一会,童才来开门,一副手忙脚乱的样子。
“你在干什么?怎么这么久才开门?”不祥的感觉浮上来,我越发气燥。
“没干什么。”
突然看见客厅地上有一个盆,里面有咖啡色的水。
“你这是干什么?洗脚?洗脸?洗……”童脚上还流着咖啡色的液体,已经浸湿了睡裙裙角。她显然刚正一边坐盆一边看电视,因为开门,没来得及擦。
“你在坐盆?!”
童不说话。
我拿起盆子旁边的药水一看,正是治疗性病的外用药水。
“什么病?把病历拿来给我看看。”
童低着头,还是不说话。
“我知道你病历本放哪了。是放这个抽屉里面的……”我一把打开抽屉,翻开童的妇科病历,XX重度感染,三级!
“你得性病了?你为什么不告诉我?”
“我不说是因为……”
“啪”,我一脚把盆子踢翻,水流得到处都是。“你不说是因为你不好意思说!你不说是因为你不好意思告诉我你现在一刻也忍不了没有男人!你知道我每天晚上都和老婆在一起,所以你不平衡你也要和男人睡觉!你得了性病,传染给我不要紧,可是我还传染给我老婆了!莫名其妙得了这种病,给她身心带来多大伤害你知道吗?哦,你是不是怪我没和她离婚,故意让我把性病传染给我老婆,她发现了,我们离婚,我就能永远陪着你一个人了,是不是?”
童哭了。“你怎么就知道是我传染给你的?是不是你出去……”
“我操!你还怀疑是我出去乱搞找小姐传染给你们?我是这样的人吗?”
“不一定是找小姐,可能是一夜情呢?以前我们没分手的时候你就去搞过一夜情!”童哭喊着说。
我是找过网友一夜情,三年里唯一一次得手,可是因为那次对方年老色衰,索然无味,自己几乎都淡忘了。
我没有告诉过童,童也从没有提过。
“好啊,你还把那件事翻出来说,这么多年了,原来你一直知道一直记着,真阴!我还没说怪你,你倒先怀疑我了。不相信我拉倒,我们分手!”
已经清楚了。如果不是童,她怎么会得了性病也不说,背着我自己悄悄治疗呢?

童哭着过来抱住我。“你别走……你不要怀疑我……”
“我最讨厌别人骗我,当我是傻子了。你放手,你说我要走凭你的力气拦的住吗?”
“好、好,我放手,那你是不是不走?”
不走?我脑子一片混乱,呆在这也解决不了任何问题,何况,刚才出门都没跟静说。
“你放手,我不走。”我骗童。她倔起来、闹起来,今天一个通宵又会没完。
童这才放手,我夺门而走。
童在我身后号啕大哭。“你骗我!你怎么走了?你走了是不是永远不会再来了?”她声声凄烈,现在还回旋在我脑中。
我烦透了!我烦透了周旋在两人之间!我烦透了猜猜骗骗!
我没有回头就直接下楼。五分钟后,童开始打我手机,频繁的我按结束的时间也没有,直接关机。

那天半夜,下了好大一场暴雨,闪电,雷鸣。
第二天,放晴,好大的太阳,照得人心底空荡荡的。
早上我试着开机,想打去公司交代事情,没想到童的电话马上打过来了。
两年了,她其实没变。
静就在隔壁,我赶忙关了手机。
和静一起去看病,检查、化验、开药、吊药瓶,直到下午三点。然后把静送回家。
“我去公司转转。”

我去了童的家。不管是不是她传染的,终归割舍不下她。童昨晚那凄烈的哭声,更让我放心不下。
门没锁,推开门,看见童坐在地上,穿着我的衣裤,披头散发,折飞机。
“童,你干什么,这么热的天还穿着我的保暖内衣,童,童……”
童的眼睛看也不看我,只是拿鼻子嗅衣服,喃喃的说着:“老公的味道……”
童疯了。

(20)
童在电脑里给我留了言。

不要怀疑我,也许我说什么你也会不信,毕竟你以前曾认为我霪乱过。不过,我可以发誓,除了威,只有你一个男人。
第一个是你,最后一个也是你。
如果不是那时精神有问题,可能连威都不会沾染我的身体。还记得吗,我不是说威第一次和我上床觉得人格好象分裂了吗?那时,严重的抑郁症,已经导致我精神轻度分裂。
而后,能和你重新在一起,是我最快乐的2个月,仅次于我们刚认识的时候。
我想,你真是我的药。
毒药是你,弄的我不生不死,精神错乱。
灵药也是你,治好了我的精神病。
半个月前,我发现下身不舒服,去医院检查,是性病,而且导致很多妇科病复发。除了你知道的性病外,盆腔积液、宫颈囊肿、宫颈糜烂、阴〈!—->道炎,你所能想象的到的妇科病,几乎全齐了。要知道,在生完宝宝后,妇科病可是全治好了。我很清楚,不是你,就是你老婆传染的。当然,到底是你还是你老婆,现在你自己应该最清楚。你问我为什么不告诉你?我能说吗?如果是你,我不说,还可以装着继续和你好下去,我说了,捅破了、撕破脸的结果只会把你往你老婆那边推;如果是你老婆,一向被你称为贤惠文秀的老婆,红杏出墙,你要受多大打击?而且从我嘴里得知,就算你相信我所说,可是被我知道你选的比我贤惠的老婆还让你戴了绿帽子,你更会觉得脸面挂不住。你那么要面子,心里怎么会受的了?所以,我决定不说。反正不说这种事过不了多久也会昭然于世的。只是,没想到你反而怀疑我。
哎。
你总是需要一万个理由才能坚持爱我,只要一个理由就可以放弃我。
而我,一万个理由也不放弃你,只凭一个理由–爱,就可以坚持到底。
可是,这次还能坚持下去吗?
你知道这两个月我有多开心吗?我做梦都是甜的。只是,我有多开心就有多担心。我怕,美梦容易醒。不知道哪天你又会消失,所以和你在一起,睡觉都是种浪费:我本来可以拿这段时间静静的看着你,实在的摸到你,可是一睡着,就什么也没干、白浪费几个小时了。
失而复得有多开心,得而复失就有多痛苦。
昨晚你决绝的走出我家大门,我崩溃了。
可能你一辈子不会再回来了。
从那刻起,我头昏、眼花、恶心,心砰砰跳的厉害,好象要蹦出来,手脚发凉,发麻。我一夜没睡,不停的给你打电话,就是想告诉你,快来救我,我支持 不住了,我就要疯了!可是打不通,一直都打不通。我只能趁最后还清醒的时间,给你写最后的留言。
不要怀疑我,我没有霪乱过……

从童手里掰出的纸飞机,是用她超声检查报告单和阴〈!—->道镜报告单折成的,上面除性病外还写着:盆腔积液、宫颈囊肿、宫颈糜烂、阴〈!—->道炎、细菌感染……我所能想象的到的妇科病,几乎全齐了。和静一起看病,我知道对女人来说,检查和治疗的过程有多痛苦,而静,除了性病外,远没有童这么多妇科病;而静,检查时有我陪着。

应童父母的要求,我把童送到了她故乡的精神病院。和某些病者比起来,童不具有攻击性,只活在自己的世界里,和一个人喃喃对话。那个人,就是她深爱的、同时深爱着她的“我”。我去看她,她也不认识,可能她认定这个我,并不爱她。
这样也好,对童来说。
她可以永远和爱人生活在一起。

我和静离婚了。离婚前,向她坦承一切。
静吃惊,不过也爽快的承认:她是和别人上过床,性病很可能是别人传染给她,然后给我,再传染童。
“对不起”,静说:“我当时也怀疑过是不是他传染给我的,只是和你找鸡比,我觉得是你传染给我的可能性更大,所以,我就推到你身上了。哎……”静叹口气,“我早知道会牵连到另外一个女人,导致她发疯,一定早就实话告诉你了。我还以为,你和我一样,是失去最爱,随便找个合适的伴,谁知道你还有机会和最爱相守。哎,我是真不知道,我知道了一定会主动退出。我也是女人,我以前也有过最爱。你不会怪我吧?对于我来说,永失最爱,那么霪不霪乱也没关系了,我以为你和我一样达成默契,所以你出轨我知道也从不提;同样,我出轨你也没提。哎……”静又叹口气,“谁知道是你心里还放着她所以一点都没留意呢?”
我已不想再谴责静半句,毕竟,最终导致童发疯的是我,不是她,而且这段婚姻,我也有背叛。签离婚协议时,静坚持把一半财产退给我,悄悄搬走。
而我,一直住在我和童的家,不再离开。

写到这,这段刻骨的爱情终于写完了。
如果告诉你们,最后我带着良心的谴责赎罪,一辈子守在疯了的童身边,你们可能对我的骂声轻一点,心里能接受一点,那么,看到这就请离开吧。

如果,你们想看到我现在的真实生活,那就请接着往下看。


后记:
33岁的我,单身,是一家香料代理商,刚买了一套新房,准备找个正经的女朋友,谈半年,然后结婚生子。

香料总部的同事,知道我离婚,问我想找什么条件的好帮我介绍。说是不是要找没结过婚。
结没结过婚,无所谓。
那外貌呢,喜欢什么类型的?同事问。
无所谓。
身高呢?
无所谓。
你到底有什么要求,这样我们很难帮你介绍。
品德好,愿意和我作个伴就行。
这样的啊,我们公司就有,你看阿芬怎么样?
芬,32岁,是总经销商的行政文秘,我也认识。芬虽然离过婚是单身,可因为长相实在不可恭维,身高只有一米五四,还戴着厚厚的眼镜,所以每位老总的妻子都放心她当文秘,已经干了7、8年,大家知根知底。
可以啊。只要她愿意。
哦,那芬肯定乐意。可是,你愿意?我们刚才其实是开玩笑说的。
真的,我真愿意。

同事撮合后,每天,我都能吃到芬亲手包的肉粽,我也接送她上下班,尽到男朋友的责任。然后,回家,在同城聊天室寻找一夜情。

我很希望告诉别人,和童以后,不仅丧失了爱的能力,也丧失了性的冲动。
我很希望做到孓然一身,只守着童的爱,过完剩下的几十年。
可现实生活并不是如此。我母亲想家里添丁,能有人和我作伴;而我自己,这个经历过童的激情的成熟男人,在寂寞的夜半,冲动强烈。
只是,我连右手都不爱用,怕用的时候会想起和童亲热的情景。

在聊天室里,我专门寻找那些名字带隐晦暗示的女性下手,比如说这个:“空床的半边空着你(女)”。
“空床”显然也被我的名字“无心之竹(男)”吸引了,惺惺相吸,开了QQ单独聊,最后她告诉我地址,让我去她家。

我没有去,而是笑着关了QQ。
QQ上“空床”留给我的地址,是我每天上下班之前,接送女友的地方。

睡觉,明天还要早起去接我女朋友。

躺在床上,黑暗中望着天花板,对童说:童,其实你比我幸福,至少你能在虚幻世界和最爱生活;而我,将继续悲惨的活在现实的社会。这里,尽是些我这样的、永失最爱的男人和女人,独自抚慰自己失去爱的功能的心。
(全文完)

2005年04月04日
你第一次到我这里, 
那时我叫大唐, 
威震世界我强盛无比。 
你赤著双脚、 
衣不遮体。 
诚惶诚恐你走进我的光辉大殿里。 

我记得我叫秦的时候曾让徐福, 
带领三千童男童女, 
远渡东海, 
扎根到你那里。 
因此我认定: 
有我的血液流到你的血管里。 
对於你的潦倒, 
我没有嫌弃。 
我给了你锦衣朝服, 
我盛唐全部礼仪、 
和那双你穿到现在的木屐。 
你千恩万谢, 
满口“哈依、哈依”。 
你藏不住那贪婪的目光, 
我告诫自己—— 
这是一个人面兽心的家夥,就象在地图上: 
它的形状象一只可恶的虫蚁。 
仁至义尽我送你回去, 
还教给你我盛世的诗词汉语。 
你走之後我轻声自语: 
“它还会回来”—— 
我等著你。 


当我叫明的时候我等到了你。 
你手拿倭刀, 
穿著我教你做的唐衣。 
你说你并不得已, 
因为後面有驱赶你的丰臣秀吉。 
杀人放火你奸淫掠虏, 
戚家儿郎把你赶下海去。 
用东海水我洗著伤口, 
贼心不死的禽兽—— 
我等著你! 


日月如梭我身染重疾, 
东方的巨人渐渐不能自己。 
围攻撕咬我的兽群中, 
我又看见了你: 
强盗火拼你咬走了俄国熊罴, 
独占我北方要地。 
贪心不足你膨胀的恶欲。 
终於到了“九.一八”那是一九三一, 
血肉从我身上分离, 
於是有了伪满供你驱骑。 
欲壑难平你得寸进尺, 
疯狂的野兽你竞妄想把世界归己。 
一九三七的七月七, 
我的胸膛上你印上了铁蹄。 
作威作福你那麽得意, 
心在淌血我把仇恨铭记。 
多行不义你必自毙, 
自作自受—— 
蘑菇云中你看见了自己的广岛和长崎。 
夹著尾巴你滚了回去, 
还有那面沾满血腥的膏药旗。 


跟在霸强後面, 
你又觉得有势可倚。 
偷机取巧你开始发迹, 
一夜之间你觉得富得无人可比。 
不改的本性让你又暗藏杀人的利器, 
打著自卫的幌子想把世人蒙弊。 
为富不仁你开始觉得自己家里挤, 
又妄想到我的岛上来“钓鱼”! 
伤疤犹在你就忘了痛, 
参拜亡灵的政客们啊, 
在靖国神社你们是否看见了东条英机? 
往日的屈辱我怎能忘记? 
昨天的病夫现在已有了强壮的身躯! 
睁大眼睛我看你要向何处去? 
还想再来吗? 
——世世代代我等著你! 


狼生的孩子仍然要吃肉, 
魔鬼释缚后还会害人。 
鬼魂在庙宇里在受膜拜, 
人人都知道你贼心不死。 
多少年来我受了你多少凌辱和欺骗, 
强霸面前你又有狗仗人势, 
又见到膏药旗在我的家里?! 
我知道,你早晚还会回来, 
如同饿狼常来觅食。 
子弹上膛的猎枪手中拿紧吧, 
我世世代代等着你! 
—–我等着你!!
2005年01月19日

在.NET Framework中,System.Convert类中提供了较为全面的各种类型、数值之间的转换功能。其中的两个方法可以轻松的实现各种进制的数值间的转换:

Convert.ToInt32(string value, int fromBase):

可以把不同进制数值的字符串转换为数字,其中fromBase参数为进制的格式,只能是2、8、10及16:

如Convert.ToInt32(”0010”,2)执行的结果为2;

Convert.ToString(int value, int toBase):

可以把一个数字转换为不同进制数值的字符串格式,其中toBase参数为进制的格式,只能是2、8、10及16:

如Convert.ToString(2,2)执行的结果为”0010”

现在我们做一个方法实现各种进制间的字符串自由转换:选把它转成数值型,然后再转成相应的进制的字符串:

public string ConvertString(string value, int fromBase, int toBase)

{

  int intValue = Convert.ToInt32(value, fromBase);

  return Convert.ToString(intValue, toBase);
}

其中fromBase为原来的格式

toBase为将要转换成的格式

2005年01月18日

Microsoft.Net Framework为应用程序访问Internet提供了分层的、可扩展的以及受管辖的网络服务,其名字空间System.Net和System.Net.Sockets包含丰富的类可以开发多种网络应用程序。.Net类采用的分层结构允许应用程序在不同的控制级别上访问网络,开发人员可以根据需要选择针对不同的级别编制程序,这些级别几乎囊括了Internet的所有需要–从socket套接字到普通的请求/响应,更重要的是,这种分层是可以扩展的,能够适应Internet不断扩展的需要。
  
  抛开ISO/OSI模型的7层构架,单从TCP/IP模型上的逻辑层面上看,.Net类可以视为包含3个层次:请求/响应层、应用协议层、传输层。WebReqeust和WebResponse 代表了请求/响应层,支持Http、Tcp和Udp的类组成了应用协议层,而Socket类处于传输层。可以如下示意:
 

可见,传输层位于这个结构的最底层,当其上面的应用协议层和请求/响应层不能满足应用程序的特殊需要时,就需要使用这一层进行Socket套接字编程。
  
  而在.Net中,System.Net.Sockets 命名空间为需要严密控制网络访问的开发人员提供了 Windows Sockets (Winsock) 接口的托管实现。System.Net 命名空间中的所有其他网络访问类都建立在该套接字Socket实现之上,如TCPClient、TCPListener 和 UDPClient 类封装有关创建到 Internet 的 TCP 和 UDP 连接的详细信息;NetworkStream类则提供用于网络访问的基础数据流等,常见的许多Internet服务都可以见到Socket的踪影,如Telnet、Http、Email、Echo等,这些服务尽管通讯协议Protocol的定义不同,但是其基础的传输都是采用的Socket。
  
  其实,Socket可以象流Stream一样被视为一个数据通道,这个通道架设在应用程序端(客户端)和远程服务器端之间,而后,数据的读取(接收)和写入(发送)均针对这个通道来进行。


  可见,在应用程序端或者服务器端创建了Socket对象之后,就可以使用Send/SentTo方法将数据发送到连接的Socket,或者使用Receive/ReceiveFrom方法接收来自连接Socket的数据;
  
  针对Socket编程,.NET 框架的 Socket 类是 Winsock32 API 提供的套接字服务的托管代码版本。其中为实现网络编程提供了大量的方法,大多数情况下,Socket 类方法只是将数据封送到它们的本机 Win32 副本中并处理任何必要的安全检查。如果你熟悉Winsock API函数,那么用Socket类编写网络程序会非常容易,当然,如果你不曾接触过,也不会太困难,跟随下面的解说,你会发觉使用Socket类开发windows 网络应用程序原来有规可寻,它们在大多数情况下遵循大致相同的步骤。
  
  在使用之前,你需要首先创建Socket对象的实例,这可以通过Socket类的构造方法来实现:
  
  public Socket(AddressFamily addressFamily,SocketType socketType,ProtocolType protocolType);
  
  
  其中,addressFamily 参数指定 Socket 使用的寻址方案,socketType 参数指定 Socket 的类型,protocolType 参数指定 Socket 使用的协议。
  
  下面的示例语句创建一个 Socket,它可用于在基于 TCP/IP 的网络(如 Internet)上通讯。
  
  Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  
  
  若要使用 UDP 而不是 TCP,需要更改协议类型,如下面的示例所示:
  
  Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
  
  
  一旦创建 Socket,在客户端,你将可以通过Connect方法连接到指定的服务器,并通过Send/SendTo方法向远程服务器发送数据,而后可以通过Receive/ReceiveFrom从服务端接收数据;而在服务器端,你需要使用Bind方法绑定所指定的接口使Socket与一个本地终结点相联,并通过Listen方法侦听该接口上的请求,当侦听到用户端的连接时,调用Accept完成连接的操作,创建新的Socket以处理传入的连接请求。使用完 Socket 后,记住使用 Shutdown 方法禁用 Socket,并使用 Close 方法关闭 Socket。其间用到的方法/函数有:
  
  Socket.Connect方法:建立到远程设备的连接
  public void Connect(EndPoint remoteEP)(有重载方法)
  Socket.Send 方法:从数据中的指示位置开始将数据发送到连接的 Socket。
  public int Send(byte[], int, SocketFlags);(有重载方法)
  Socket.SendTo 方法 将数据发送到特定终结点。
  public int SendTo(byte[], EndPoint);(有重载方法)
  Socket.Receive方法:将数据从连接的 Socket 接收到接收缓冲区的特定位置。
  public int Receive(byte[],int,SocketFlags);
  Socket.ReceiveFrom方法:接收数据缓冲区中特定位置的数据并存储终结点。
  public int ReceiveFrom(byte[], int, SocketFlags, ref EndPoint);
  Socket.Bind 方法:使 Socket 与一个本地终结点相关联:
  public void Bind( EndPoint localEP );
  Socket.Listen方法:将 Socket 置于侦听状态。
  public void Listen( int backlog );
  Socket.Accept方法:创建新的 Socket 以处理传入的连接请求。
  public Socket Accept();
  Socket.Shutdown方法:禁用某 Socket 上的发送和接收
  public void Shutdown( SocketShutdown how );
  Socket.Close方法:强制 Socket 连接关闭
  public void Close();
  
  
  可以看出,以上许多方法包含EndPoint类型的参数,在Internet中,TCP/IP 使用一个网络地址和一个服务端口号来唯一标识设备。网络地址标识网络上的特定设备;端口号标识要连接到的该设备上的特定服务。网络地址和服务端口的组合称为终结点,在 .NET 框架中正是由 EndPoint 类表示这个终结点,它提供表示网络资源或服务的抽象,用以标志网络地址等信息。.Net同时也为每个受支持的地址族定义了 EndPoint 的子代;对于 IP 地址族,该类为 IPEndPoint。IPEndPoint 类包含应用程序连接到主机上的服务所需的主机和端口信息,通过组合服务的主机IP地址和端口号,IPEndPoint 类形成到服务的连接点。
  
  用到IPEndPoint类的时候就不可避免地涉及到计算机IP地址,.Net中有两种类可以得到IP地址实例:
  
  IPAddress类:IPAddress 类包含计算机在 IP 网络上的地址。其Parse方法可将 IP 地址字符串转换为 IPAddress 实例。下面的语句创建一个 IPAddress 实例:
  
  IPAddress myIP = IPAddress.Parse(“192.168.1.2″);
  
  
  Dns 类:向使用 TCP/IP Internet 服务的应用程序提供域名服务。其Resolve 方法查询 DNS 服务器以将用户友好的域名(如”host.contoso.com”)映射到数字形式的 Internet 地址(如 192.168.1.1)。Resolve方法 返回一个 IPHostEnty 实例,该实例包含所请求名称的地址和别名的列表。大多数情况下,可以使用 AddressList 数组中返回的第一个地址。下面的代码获取一个 IPAddress 实例,该实例包含服务器 host.contoso.com 的 IP 地址。
  
  IPHostEntry ipHostInfo = Dns.Resolve(“host.contoso.com”);
  IPAddress ipAddress = ipHostInfo.AddressList[0];

你也可以使用GetHostName方法得到IPHostEntry实例:
  
  IPHosntEntry hostInfo=Dns.GetHostByName(“host.contoso.com”)
  
  
  在使用以上方法时,你将可能需要处理以下几种异常:
  
  SocketException异常:访问Socket时操作系统发生错误引发
  
  ArgumentNullException异常:参数为空引用引发
  
  ObjectDisposedException异常:Socket已经关闭引发
  
  在掌握上面得知识后,下面的代码将该服务器主机( host.contoso.com的 IP 地址与端口号组合,以便为连接创建远程终结点:
  
  IPEndPoint ipe = new IPEndPoint(ipAddress,11000);
  
  
  确定了远程设备的地址并选择了用于连接的端口后,应用程序可以尝试建立与远程设备的连接。下面的示例使用现有的 IPEndPoint 实例与远程设备连接,并捕获可能引发的异常:
  
  try {
   s.Connect(ipe);//尝试连接
  }
  //处理参数为空引用异常
   catch(ArgumentNullException ae) {
   Console.WriteLine(“ArgumentNullException : {0}”, ae.ToString());
  }
  //处理操作系统异常
   catch(SocketException se) {
   Console.WriteLine(“SocketException : {0}”, se.ToString());
  }
   catch(Exception e) {
   Console.WriteLine(“Unexpected exception : {0}”, e.ToString());
  }
  
  
  需要知道的是:Socket 类支持两种基本模式:同步和异步。其区别在于:在同步模式中,对执行网络操作的函数(如 Send 和 Receive)的调用一直等到操作完成后才将控制返回给调用程序。在异步模式中,这些调用立即返回。
  
  另外,很多时候,Socket编程视情况不同需要在客户端和服务器端分别予以实现,在客户端编制应用程序向服务端指定端口发送请求,同时编制服务端应用程序处理该请求,这个过程在上面的阐述中已经提及;当然,并非所有的Socket编程都需要你严格编写这两端程序;视应用情况不同,你可以在客户端构造出请求字符串,服务器相应端口捕获这个请求,交由其公用服务程序进行处理。以下事例语句中的字符串就向远程主机提出页面请求:
  
  string Get = “GET / HTTP/1.1\r\nHost: ” + server + “\r\nConnection: Close\r\n\r\n”;
  
  
  远程主机指定端口接受到这一请求后,就可利用其公用服务程序进行处理而不需要另行编制服务器端应用程序。
  
  综合运用以上阐述的使用Visual C#进行Socket网络程序开发的知识,下面的程序段完整地实现了Web页面下载功能。用户只需在窗体上输入远程主机名(Dns 主机名或以点分隔的四部分表示法格式的 IP 地址)和预保存的本地文件名,并利用专门提供Http服务的80端口,就可以获取远程主机页面并保存在本地机指定文件中。如果保存格式是.htm格式,你就可以在Internet浏览器中打开该页面。适当添加代码,你甚至可以实现一个简单的浏览器程序。
  


实现此功能的主要源代码如下:
  
  //”开始”按钮事件
  private void button1_Click(object sender, System.EventArgs e) {
   //取得预保存的文件名
   string fileName=textBox3.Text.Trim();
   //远程主机
   string hostName=textBox1.Text.Trim();
   //端口
   int port=Int32.Parse(textBox2.Text.Trim());
   //得到主机信息
   IPHostEntry ipInfo=Dns.GetHostByName(hostName);
   //取得IPAddress[]
   IPAddress[] ipAddr=ipInfo.AddressList;
   //得到ip
   IPAddress ip=ipAddr[0];
   //组合出远程终结点
   IPEndPoint hostEP=new IPEndPoint(ip,port);
   //创建Socket 实例
   Socket socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
   try
   {
   //尝试连接
   socket.Connect(hostEP);
   }
   catch(Exception se)
   {
   MessageBox.Show(“连接错误”+se.Message,”提示信息
   ,MessageBoxButtons.RetryCancel,MessageBoxIcon.Information);
  }
  //发送给远程主机的请求内容串
  string sendStr=”GET / HTTP/1.1\r\nHost: ” + hostName +
  “\r\nConnection: Close\r\n\r\n”;
   //创建bytes字节数组以转换发送串
   byte[] bytesSendStr=new byte[1024];
   //将发送内容字符串转换成字节byte数组
   bytesSendStr=Encoding.ASCII.GetBytes(sendStr);
  try
  {
  //向主机发送请求
  socket.Send(bytesSendStr,bytesSendStr.Length,0);
  }
  catch(Exception ce)
   {
   MessageBox.Show(“发送错误:”+ce.Message,”提示信息
   ,MessageBoxButtons.RetryCancel,MessageBoxIcon.Information);
   }
   //声明接收返回内容的字符串
   string recvStr=”";
   //声明字节数组,一次接收数据的长度为1024字节
   byte[] recvBytes=new byte[1024];
   //返回实际接收内容的字节数
   int bytes=0;
  //循环读取,直到接收完所有数据
  while(true)
  {
  bytes=socket.Receive(recvBytes,recvBytes.Length,0);
  //读取完成后退出循环
  if(bytes<=0)
  break;
  //将读取的字节数转换为字符串
  recvStr+=Encoding.ASCII.GetString(recvBytes,0,bytes);
  }
  //将所读取的字符串转换为字节数组
  byte[] content=Encoding.ASCII.GetBytes(recvStr);
   try
   {
   //创建文件流对象实例
   FileStream fs=new FileStream(fileName,FileMode.OpenOrCreate,FileAccess.ReadWrite);
  //写入文件
  fs.Write(content,0,content.Length);
  }
  catch(Exception fe)
   {
   MessageBox.Show(“文件创建/写入错误:”+fe.Message,”提示信息”,MessageBoxButtons.RetryCancel,MessageBoxIcon.Information);
   }
   //禁用Socket
   socket.Shutdown(SocketShutdown.Both);
   //关闭Socket
   socket.Close();
   }
   }
  
  
  程序在WindowsXP中文版、.Net Frameworkd 中文正式版、Visual Studio.Net中文正式版下调试通过

 

C#网络编程初探

我们知道C#和C++的差异之一,就是他本身没有类库,所使用的类库是.Net框架中的类库–.Net FrameWork SDK。在.Net FrameWork SDK中为网络编程提供了二个名称空间:”System.Net”和”System.Net.Sockets”。C#就是通过这二个名称空间中封装的类和方法实现网络通讯的。

  首先我们解释一下在网络编程时候,经常遇到的几个概念:同步(synchronous)、异步(asynchronous)、阻塞(Block)和非阻塞(Unblock):

  所谓同步方式,就是发送方发送数据包以后,不等接受方响应,就接着发送下一个数据包。异步方式就是当发送方发送一个数据包以后,一直等到接受方响应后,才接着发送下一个数据包。而阻塞套接字是指执行此套接字的网络调用时,直到调用成功才返回,否则此套节字就一直阻塞在网络调用上,比如调用StreamReader 类的Readlin ( )方法读取网络缓冲区中的数据,如果调用的时候没有数据到达,那么此Readlin ( )方法将一直挂在调用上,直到读到一些数据,此函数调用才返回;而非阻塞套接字是指在执行此套接字的网络调用时,不管是否执行成功,都立即返回。同样调用StreamReader 类的Readlin ( )方法读取网络缓冲区中数据,不管是否读到数据都立即返回,而不会一直挂在此函数调用上。在Windows网络通信软件开发中,最为常用的方法就是异步非阻塞套接字。平常所说的C/S(客户端/服务器)结构的软件采用的方式就是异步非阻塞模式的。

  其实在用C#进行网络编程中,我们并不需要了解什么同步、异步、阻塞和非阻塞的原理和工作机制,因为在.Net FrameWrok SDK中已经已经把这些机制给封装好了。下面我们就用C#开一个具体的网络程序来说明一下问题。

  一.本文中介绍的程序设计及运行环境

   (1).微软视窗2000 服务器版

   (2)..Net Framework SDK Beta 2以上版本

  二.服务器端程序设计的关键步骤以及解决办法:

  在下面接受的程序中,我们采用的是异步阻塞的方式。

  (1).首先要要在给定的端口上面创建一个”tcpListener”对象侦听网络上面的请求。当接收到连结请求后通过调用”tcpListener”对象的”AcceptSocket”方法产生一个用于处理接入连接请求的Socket的实例。下面是具体实现代码:

//创建一个tcpListener对象,此对象主要是对给定端口进行侦听
tcpListener = new TcpListener ( 1234 ) ;
//开始侦听
tcpListener.Start ( ) ;
//返回可以用以处理连接的Socket实例
socketForClient = tcpListener.AcceptSocket ( ) ;

  (2).接受和发送客户端数据:

  此时Socket实例已经产生,如果网络上有请求,在请求通过以后,Socket实例构造一个”NetworkStream”对象,”NetworkStream”对象为网络访问提供了基础数据流。我们通过名称空间”System.IO”中封装的二个类”StreamReader”和”StreamWriter”来实现对”NetworkStream”对象的访问。其中”StreamReader”类中的ReadLine ( )方法就是从”NetworkStream”对象中读取一行字符;”StreamWriter”类中的WriteLine ( )方法就是对”NetworkStream”对象中写入一行字符串。从而实现在网络上面传输字符串,下面是具体的实现代码:

try
{
//如果返回值是”true”,则产生的套节字已经接受来自远方的连接请求
if ( socketForClient.Connected )
{
ListBox1.Items.Add ( “已经和客户端成功连接!” ) ;
while ( true )
{
//创建networkStream对象通过网络套节字来接受和发送数据
networkStream = new NetworkStream ( socketForClient ) ;
//从当前数据流中读取一行字符,返回值是字符串
streamReader = new StreamReader ( networkStream ) ;
string msg = streamReader.ReadLine ( ) ;
ListBox1.Items.Add ( “收到客户端信息:” + msg ) ;
streamWriter = new StreamWriter ( networkStream ) ;
if ( textBox1.Text != “” )
{
ListBox1.Items.Add ( “往客户端反馈信息:” + textBox1.Text ) ;
//往当前的数据流中写入一行字符串
streamWriter.WriteLine ( textBox1.Text ) ;
//刷新当前数据流中的数据
streamWriter.Flush ( ) ;
}
}
}
}
catch ( Exception ey )
{
MessageBox.Show ( ey.ToString ( ) ) ;
}


  (3).最后别忘了要关闭所以流,停止侦听网络,关闭套节字,具体如下:

//关闭线程和流
networkStream.Close ( ) ;
streamReader.Close ( ) ;
streamWriter.Close ( ) ;
_thread1.Abort ( ) ;
tcpListener.Stop ( ) ;
socketForClient.Shutdown ( SocketShutdown.Both ) ;
socketForClient.Close ( ) ;
  三.C#网络编程服务器端程序的部分源代码(server.cs):

  由于在此次程序中我们采用的结构是异步阻塞方式,所以在实际的程序中,为了不影响服务器端程序的运行速度,我们在程序中设计了一个线程,使得对网络请求侦听,接受和发送数据都在线程中处理,请在下面的代码中注意这一点,下面是server.cs的完整代码:

using System ;
using System.Drawing ;
using System.Collections ;
using System.ComponentModel ;
using System.Windows.Forms ;
using System.Data ;
using System.Net.Sockets ;
using System.IO ;
using System.Threading ;
using System.Net ;
//导入程序中使用到的名字空间
public class Form1 : Form
{
private ListBox ListBox1 ;
private Button button2 ;
private Label label1 ;
private TextBox textBox1 ;
private Button button1 ;
private Socket socketForClient ;
private NetworkStream networkStream ;
private TcpListener tcpListener ;
private StreamWriter streamWriter ;
private StreamReader streamReader ;
private Thread _thread1 ;
private System.ComponentModel.Container components = null ;
public Form1 ( )
{
InitializeComponent ( ) ;
}
//清除程序中使用的各种资源
protected override void Dispose ( bool disposing )
{
if ( disposing )
{
if ( components != null )
{
components.Dispose ( ) ;
}
}
base.Dispose ( disposing ) ;
}
private void InitializeComponent ( )
{
label1 = new Label ( ) ;
button2 = new Button ( ) ;
button1 = new Button ( ) ;
ListBox1 = new ListBox ( ) ;
textBox1 = new TextBox ( ) ;
SuspendLayout ( ) ;
label1.Location = new Point ( 8 , 168 ) ;
label1.Name = “label1″ ;
label1.Size = new Size ( 120 , 23 ) ;
label1.TabIndex = 3 ;
label1.Text = “往客户端反馈信息:” ;
//同样的方式设置其他控件,这里略去

this.Controls.Add ( button1 ) ;
this.Controls.Add ( textBox1 ) ;
this.Controls.Add ( label1 ) ;
this.Controls.Add ( button2 ) ;
this.Controls.Add ( ListBox1 ) ;
this.MaximizeBox = false ;
this.MinimizeBox = false ;
this.Name = “Form1″ ;
this.Text = “C#的网络编程服务器端!” ;
this.Closed += new System.EventHandler ( this.Form1_Closed ) ;
this.ResumeLayout ( false ) ;

}
private void Listen ( )
{
//创建一个tcpListener对象,此对象主要是对给定端口进行侦听
tcpListener = new TcpListener ( 1234 ) ;
//开始侦听
tcpListener.Start ( ) ;
//返回可以用以处理连接的Socket实例
socketForClient = tcpListener.AcceptSocket ( ) ;
try
{
//如果返回值是”true”,则产生的套节字已经接受来自远方的连接请求
if ( socketForClient.Connected )
{
ListBox1.Items.Add ( “已经和客户端成功连接!” ) ;
while ( true )
{
//创建networkStream对象通过网络套节字来接受和发送数据
networkStream = new NetworkStream ( socketForClient ) ;
//从当前数据流中读取一行字符,返回值是字符串
streamReader = new StreamReader ( networkStream ) ;
string msg = streamReader.ReadLine ( ) ;
ListBox1.Items.Add ( “收到客户端信息:” + msg ) ;
streamWriter = new StreamWriter ( networkStream ) ;
if ( textBox1.Text != “” )
{
ListBox1.Items.Add ( “往客户端反馈信息:” + textBox1.Text ) ;
//往当前的数据流中写入一行字符串
streamWriter.WriteLine ( textBox1.Text ) ;
//刷新当前数据流中的数据
streamWriter.Flush ( ) ;
}
}
}
}
catch ( Exception ey )
{
MessageBox.Show ( ey.ToString ( ) ) ;
}
}
static void Main ( )
{
Application.Run ( new Form1 ( ) ) ;
}

private void button1_Click ( object sender , System.EventArgs e )
{
ListBox1.Items .Add ( “服务已经启动!” ) ;
_thread1 = new Thread ( new ThreadStart ( Listen ) ) ;
_thread1.Start ( ) ;

}

private void button2_Click ( object sender , System.EventArgs e )
{
//关闭线程和流
networkStream.Close ( ) ;
streamReader.Close ( ) ;
streamWriter.Close ( ) ;
_thread1.Abort ( ) ;
tcpListener.Stop ( ) ;
socketForClient.Shutdown ( SocketShutdown.Both ) ;
socketForClient.Close ( ) ;
}
private void Form1_Closed ( object sender , System.EventArgs e )
{
//关闭线程和流
networkStream.Close ( ) ;
streamReader.Close ( ) ;
streamWriter.Close ( ) ;
_thread1.Abort ( ) ;
tcpListener.Stop ( ) ;
socketForClient.Shutdown ( SocketShutdown.Both ) ;
socketForClient.Close ( ) ;
}
}



   四.客户端程序设计的关键步骤以及解决办法: 

  (1).连接到服务器端的指定端口:

  我们采用的本地机既做服务器也做客户机,你可以通过修改IP地址来确定自己想要连接的服务器。我们在连接的时候采用了”TcpClient”类,此类是在较高的抽象级别(高于Socket类)上面提供TCP服务。下面代码就是连接到本地机(端口为1234),并获取响应流:



//连接到服务器端口,在这里是选用本地机器作为服务器,你可以通过修改IP地址来改变服务器
try
{
myclient = new TcpClient ( “localhost” , 1234 ) ;
}
catch
{
MessageBox.Show ( “没有连接到服务器!” ) ;
return ;
}
//创建networkStream对象通过网络套节字来接受和发送数据
networkStream = myclient.GetStream ( ) ;
streamReader = new StreamReader ( networkStream ) ;
streamWriter = new StreamWriter ( networkStream ) ;

  (2).实现接受和发送数据:

  在接受和发送数据上面,我们依然采用了”NetworkStream”类,因为对他进行操作比较简单,具体实现发送和接受还是通过命名空间”System.IO”中”StreamReader”类ReadLine ( )方法和”StreamWriter”类的WriteLine ( )方法。具体的实现方法如下:

if ( textBox1.Text == “” )
{
MessageBox.Show ( “请确定文本框为非空!” ) ;
textBox1.Focus ( ) ;
return ;
}
try
{
string s ;
//往当前的数据流中写入一行字符串
streamWriter.WriteLine ( textBox1.Text ) ;
//刷新当前数据流中的数据
streamWriter.Flush ( ) ;
//从当前数据流中读取一行字符,返回值是字符串
s = streamReader.ReadLine ( ) ;
ListBox1.Items.Add ( “读取服务器端发送内容:” + s ) ;
}
catch ( Exception ee )
{
MessageBox.Show ( “从服务器端读取数据出现错误,类型为:” + ee.ToString ( ) ) ;
}


  (3).最后一步和服务器端是一样的,就是要关闭程序中创建的流,具体如下:

streamReader.Close ( ) ;
streamWriter.Close ( ) ;
networkStream.Close ( ) ;
  五.客户端的部分代码:

  由于在客户端不需要侦听网络,所以在调用上面没有程序阻塞情况,所以在下面的代码中,我们没有使用到线程,这是和服务器端程序的一个区别的地方。总结上面的这些关键步骤,可以得到一个用C#网络编程 完整的客户端程序(client.cs),具体如下:

using System ;
using System.Drawing ;
using System.Collections ;
using System.ComponentModel ;
using System.Windows.Forms ;
using System.Data ;
using System.Net.Sockets ;
using System.IO ;
using System.Threading ;
//导入程序中使用到的名字空间
public class Form1 : Form
{
private ListBox ListBox1 ;
private Label label1 ;
private TextBox textBox1 ;
private Button button3 ;
private NetworkStream networkStream ;
private StreamReader streamReader ;
private StreamWriter streamWriter ;
TcpClient myclient ;
private Label label2 ;

private System.ComponentModel.Container components = null ;

public Form1 ( )
{
InitializeComponent ( ) ;
}
//清除程序中使用的各种资源
protected override void Dispose ( bool disposing )
{
if ( disposing )
{
if ( components != null )
{
components.Dispose ( ) ;
}
}
base.Dispose ( disposing ) ;
}
private void InitializeComponent ( )
{
label1 = new Label ( ) ;
button3 = new Button ( ) ;
ListBox1 = new ListBox ( ) ;
textBox1 = new TextBox ( ) ;
label2 = new Label ( ) ;
SuspendLayout ( ) ;
label1.Location = new Point ( 8 , 168 ) ;
label1.Name = “label1″ ;
label1.Size = new Size ( 56 , 23 ) ;
label1.TabIndex = 3 ;
label1.Text = “信息:” ;
//同样方法设置其他控件
AutoScaleBaseSize = new Size ( 6 , 14 ) ;
ClientSize = new Size ( 424 , 205 ) ;
this.Controls.Add ( button3 ) ;
this.Controls.Add ( textBox1 ) ;
this.Controls.Add ( label1 ) ;
this.Controls.Add ( label2 ) ;
this.Controls.Add ( ListBox1 ) ;
this.MaximizeBox = false ;
this.MinimizeBox = false ;
this.Name = “Form1″ ;
this.Text = “C#的网络编程客户器端!” ;
this.Closed += new System.EventHandler ( this.Form1_Closed ) ;
this.ResumeLayout ( false ) ;
//连接到服务器端口,在这里是选用本地机器作为服务器,你可以通过修改IP地址来改变服务器
try
{
myclient = new TcpClient ( “localhost” , 1234 ) ;
}
catch
{
MessageBox.Show ( “没有连接到服务器!” ) ;
return ;
}
//创建networkStream对象通过网络套节字来接受和发送数据
networkStream = myclient.GetStream ( ) ;
streamReader = new StreamReader ( networkStream ) ;
streamWriter = new StreamWriter ( networkStream ) ;
}
static void Main ( )
{
Application.Run ( new Form1 ( ) ) ;
}

private void button3_Click ( object sender , System.EventArgs e )
{

if ( textBox1.Text == “” )
{
MessageBox.Show ( “请确定文本框为非空!” ) ;
textBox1.Focus ( ) ;
return ;
}
try
{
string s ;
//往当前的数据流中写入一行字符串
streamWriter.WriteLine ( textBox1.Text ) ;
//刷新当前数据流中的数据
streamWriter.Flush ( ) ;
//从当前数据流中读取一行字符,返回值是字符串
s = streamReader.ReadLine ( ) ;
ListBox1.Items.Add ( “读取服务器端发送内容:” + s ) ;
}
catch ( Exception ee )
{
MessageBox.Show ( “从服务器端读取数据出现错误,类型为:” + ee.ToString ( ) ) ;
}
}

private void Form1_Closed ( object sender , System.EventArgs e )
{
streamReader.Close ( ) ;
streamWriter.Close ( ) ;
networkStream.Close ( ) ;

}
}

用C#实现基于TCP协议的网络通讯

TCP协议是一个基本的网络协议,基本上所有的网络服务都是基于TCP协议的,如HTTP,FTP等等,所以要了解网络编程就必须了解基于TCP协议的编程。然而TCP协议是一个庞杂的体系,要彻底的弄清楚它的实现不是一天两天的功夫,所幸的是在.net framework环境下,我们不必要去追究TCP协议底层的实现,一样可以很方便的编写出基于TCP协议进行网络通讯的程序。
   
  要进行基于TCP协议的网络通讯,首先必须建立同远程主机的连接,连接地址通常包括两部分——主机名和端口,如www.yesky.com:80中,www.yesky.com就是主机名,80指主机的80端口,当然,主机名也可以用IP地址代替。当连接建立之后,就可以使用这个连接去发送和接收数据包,TCP协议的作用就是保证这些数据包能到达终点并且能按照正确的顺序组装起来。
   
  在.net framework的类库(Class Library)中,提供了两个用于TCP网络通讯的类,分别是TcpClient和TcpListener。由其英文意义显而易见,TcpClient类是基于TCP协议的客户端类,而TcpListener是服务器端,监听(Listen)客户端传来的连接请求。TcpClient类通过TCP协议与服务器进行通讯并获取信息,它的内部封装了一个Socket类的实例,这个Socket对象被用来使用TCP协议向服务器请求和获取数据。因为与远程主机的交互是以数据流的形式出现的,所以传输的数据可以使用.net framework中流处理技术读写。在我们下边的例子中,你可以看到使用NetworkStream类操作数据流的方法。
   
  在下面的例子中,我们将建立一个时间服务器,包括服务器端程序和客户端程序。服务器端监听客户端的连接请求,建立连接以后向客户端发送当前的系统时间。
   
  先运行服务器端程序,下面截图显示了服务器端程序运行的状况:
   
   
   
  然后运行客户端程序,客户端首先发送连接请求到服务器端,服务器端回应后发送当前时间到客户端,这是客户端程序的截图:
   
   
   
  发送完成后,服务器端继续等待下一次连接:
   
   
   
  通过这个例子我们可以了解TcpClient类的基本用法,要使用这个类,必须使用System.Net.Socket命名空间,本例用到的三个命名空间如下:
   
  using System;
  using System.Net.Sockets;
  using System.Text;//从字节数组中获取字符串时使用该命名空间中的类
   
  首先讨论一下客户端程序,开始我们必须初始化一个TcpClient类的实例:
   
  TcpClient client = new TcpClient(hostName, portNum);
   
  然后使用TcpClient类的GetStream()方法获取数据流,并且用它初始化一个NetworkStream类的实例:
   
  NetworkStream ns = client.GetStream();
   
  注意,当使用主机名和端口号初始化TcpClient类的实例时,直到跟服务器建立了连接,这个实例才算真正建立,程序才能往下执行。如果因为网络不通,服务器不存在,服务器端口未开放等等原因而不能连接,程序将抛出异常并且中断执行。
   
  建立数据流之后,我们可以使用NetworkStream类的Read()方法从流中读取数据,使用Write()方法向流中写入数据。读取数据时,首先应该建立一个缓冲区,具体的说,就是建立一个byte型的数组用来存放从流中读取的数据。Read()方法的原型描述如下:
   
  public override int Read(in byte[] buffer,int offset,int size)
   
  buffer是缓冲数组,offset是数据(字节流)在缓冲数组中存放的开始位置,size是读取的字节数目,返回值是读取的字节数。在本例中,简单地使用该方法来读取服务器反馈的信息:
   
  byte[] bytes = new byte[1024];//建立缓冲区
  int bytesRead = ns.Read(bytes, 0, bytes.Length);//读取字节流
   
  然后显示到屏幕上:
   
  Console.WriteLine(Encoding.ASCII.GetString(bytes,0,bytesRead));
   
  最后不要忘记关闭连接:
   
  client.Close();
   
  下面是本例完整的程序清单:
   
  using System;
  using System.Net.Sockets;
  using System.Text;
   
  namespace TcpClientExample
  {
  public class TcpTimeClient
  {
  private const int portNum = 13;//服务器端口,可以随意修改
  private const string hostName = “127.0.0.1″;//服务器地址,127.0.0.1指本机
   
  [STAThread]
  static void Main(string[] args)
  {
  try
  {
  Console.Write(“Try to connect to “+hostName+”:”+portNum.ToString()+”\r\n”);
  TcpClient client = new TcpClient(hostName, portNum);
  NetworkStream ns = client.GetStream();
  byte[] bytes = new byte[1024];
  int bytesRead = ns.Read(bytes, 0, bytes.Length);
   
  Console.WriteLine(Encoding.ASCII.GetString(bytes,0,bytesRead));
   
  client.Close();
  Console.ReadLine();//由于是控制台程序,故为了清楚的看到结果,可以加上这句
   
  }
  catch (Exception e)
  {
  Console.WriteLine(e.ToString());
  }
  }
  }
  }
   
  上面这个例子清晰地演示了客户端程序的编写要点,下面我们讨论一下如何建立服务器程序。这个例子将使用TcpListener类,在13号端口监听,一旦有客户端连接,将立即向客户端发送当前服务器的时间信息。
   
  TcpListener的关键在于AcceptTcpClient()方法,该方法将检测端口是否有未处理的连接请求,如果有未处理的连接请求,该方法将使服务器同客户端建立连接,并且返回一个TcpClient对象,通过这个对象的GetStream方法建立同客户端通讯的数据流。事实上,TcpListener类还提供一个更为灵活的方法AcceptSocket(),当然灵活的代价是复杂,对于比较简单的程序,AcceptTcpClient()已经足够用了。此外,TcpListener类提供Start()方法开始监听,提供Stop()方法停止监听。
   
  首先我们使用端口初始化一个TcpListener实例,并且开始在13端口监听:
   
  private const int portNum = 13;
  TcpListener listener = new TcpListener(portNum);
  listener.Start();//开始监听
   
  如果有未处理的连接请求,使用AcceptTcpClient方法进行处理,并且获取数据流:
   
  TcpClient client = listener.AcceptTcpClient();
  NetworkStream ns = client.GetStream();
   
  然后,获取本机时间,并保存在字节数组中,使用NetworkStream.Write()方法写入数据流,然后客户端就可以通过Read()方法从数据流中获取这段信息:
   
  byte[] byteTime = Encoding.ASCII.GetBytes(DateTime.Now.ToString());
  ns.Write(byteTime, 0, byteTime.Length);
  ns.Close();//不要忘记关闭数据流和连接
  client.Close();
   
  服务器端程序完整的程序清单如下:
   
  using System;
  using System.Net.Sockets;
  using System.Text;
   
   
  namespace TimeServer
  {
  class TimeServer
  {
  private const int portNum = 13;
   
  [STAThread]
  static void Main(string[] args)
  {
  bool done = false;
  TcpListener listener = new TcpListener(portNum);
  listener.Start();
  while (!done)
  {
  Console.Write(“Waiting for connection…”);
  TcpClient client = listener.AcceptTcpClient();
   
  Console.WriteLine(“Connection accepted.”);
  NetworkStream ns = client.GetStream();
   
  byte[] byteTime = Encoding.ASCII.GetBytes(DateTime.Now.ToString());
   
  try
  {
  ns.Write(byteTime, 0, byteTime.Length);
  ns.Close();
  client.Close();
  }
  catch (Exception e)
  {
  Console.WriteLine(e.ToString());
  }
  }
   
  listener.Stop();
  }
  }
  }
   
  把上面两段程序分别编译运行,OK,我们已经用C#实现了基于TCP协议的网络通讯,怎么样?很简单吧!
   
  使用上面介绍的基本方法,我们可以很容易的编写出一些很有用的程序,如FTP,电子邮件收发,点对点即时通讯等等,你甚至可以自己编制一个QQ来!

2004年12月29日

 private void Form1_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)
  {
  if (e.Data.GetDataPresent(DataFormats.FileDrop))
  e.Effect = DragDropEffects.Link;
  else e.Effect = DragDropEffects.None;
  }

  private void Form1_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
  {
  //其中label1.Text显示的就是拖进文件的文件名;
  label1.Text = ((System.Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();
  }

注:窗体的AllowDrop=True;

2004年12月28日

using System;
using System.Security.Cryptography; 
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;
using System.Collections;

namespace CMPP.YOURCOMPANY
{
 public delegate void ReportEventHandler(object sender, ReportEventArgs e);  //声明一个事件的指代(指针)
 public delegate void SMSEventHandler(object sender, SMSEventArgs e);   //声明一个事件的指代(指针)
 public delegate void TerminateEventHandler(object sender,TerminateEventArgs e);   //声明收到终止信号
 public delegate void TerminateRespEventHandler(object sender,TerminateRespEventArgs e);  //回应事件发生
 public delegate void TestEventHandler(object sender,TestEventArgs e);
 public delegate void TestRespEventHandler(object sender,TestRespEventArgs e);
 public delegate void ConnectRespEventHandler(object sender,ConnectRespEventArgs e);
 public delegate void CancelRespEventHandler(object sender,CancelRespEventArgs e);
 public delegate void SubmitRespEventHandler(object sender,SubmitRespEventArgs e);
 public delegate void QueryRespEventHandler(object sender,QueryRespEventArgs e);
 public delegate void LogonSuccEventHandler(object sender,EventArgs e); //当成功登录系统
 public delegate void SocketClosedEventHandler(object sender,EventArgs e); //当套接字被检测到关闭
 public delegate void FailedItemDeletedEventHandler(object sender,WaitingQueueItemEventArgs e); //当一条等待队列的消息超过60秒没有回应
 

 public delegate void CMPPClientSvcStopEventHandler(object sender, ClientQueueStateArgs e); //当CMPP服务停止时候触发事件

 /// <summary>
 /// 作为CMPP协议的客户端,具有的登陆、发送、接受功能
 /// 会开3 个线程处理: 1、处理需要发送 MO(下行)的消息
 ///       2、处理从移动服务器发送过来CMPP的消息
 ///       3、处理连接断等信息,检查需要重发的消息,检查收到的报告、短信,并调用 OnReport 事件 OnSMS事件
 /// </summary>
 public class CMPPClient
 {
  public static long CMPP_ACTIVE_TEST_C_TICKs= 30  ;  // *3 ;  //长连接的active_test测试时间
  public static long CMPP_ACTIVE_TEST_T_TICKs= 60 ;    // 消息失败时间 60秒
  public static int CMPP_ACTIVE_TEST_N_COUNT=3;  //3次 
  //public static int CMPP_MSG_MAX=100;   //一次取得的最大消息数量
  public static int CMPP_Port=7890;
 
  public event ReportEventHandler onReportHandler;   //指向事件处理代码的指针
  public event SMSEventHandler onSMSHandler;     //短信到来处理
  public event TestEventHandler onTestHandler;
  public event TestRespEventHandler onTestRespHandler;
  public event ConnectRespEventHandler onConnectRespHandler;
  public event CancelRespEventHandler onCancelRespHandler;
  public event TerminateEventHandler onTerminateHandler;
  public event TerminateRespEventHandler onTerminateRespHandler;
  public event SubmitRespEventHandler onSubmitRespHandler;
  public event QueryRespEventHandler onQueryRespHandler;
  public event LogonSuccEventHandler onLogonSuccEventHandler;
  public event SocketClosedEventHandler onSocketClosedHandler;
  public event FailedItemDeletedEventHandler onWaitingItemDeltedHandler; //当等待队列消息超时
 
  public event CMPPClientSvcStopEventHandler onClientSvcStopedHandler;  //当服务停止时候的事件

  //private 函数区域//////////////////////////////////////////////////////////////////////
  private Socket  tcp=null;    
  private IPHostEntry ip=null;  
  private IPEndPoint  cmpp_ep=null;  
  private int   RecvTimeOut =1000;       //2000ms的接受超时
  private int   SendTimeout =2000;       //2000ms的发送超时
  private string  CMPP_Server=”";   //移动的服务器IP或者DNS名
  private string  systemID=”";   //企业编号
  private string  userName=”";   //sp的号码 /企业编号
  private string  PassWord=”";   //口令 
  private bool  isStop=false;   //本服务是否终止运行
  private bool  isLogin=false;   //是否已经登录   
  private Thread  Send_Thread;   //发送线程,专门处理对移动的数据包
  private Thread  Recv_Thread;   //专门处理接收包
  private Thread  Deamo_Thread;   //监控线程
  private string  ErrorInfo=”";   //存放最后一次发生的错误信息 或者参考信息     
  private DateTime _current_time=DateTime.Now;     //上一次 ping的时间 
  private uint  lastSequence;   //流水号,每一次重新启动都需要重新设定 lastSequence
  private SortedList _outSeqQueue=new SortedList();   //消息队列存储 QueueItem,存储发送队列中的状态
  private SortedList  _waitingSeqQueue=new SortedList(); //消息队列存储 QueueItem
  private int   sub_resp=0;       //最后返回的包 Sequence
  private DateTime _lastOkTime;      //最后正确发送消息时间
  private bool  _bNre=false;      //空引用错误,套接字错误
 
  //private ManualResetEvent _connectionDone=new ManualResetEvent(false); //是否连接到套接字服务器,也就是CMPP服务器
  //private ManualResetEvent _lastsendDone=new ManualResetEvent(false);  //上一次发送是否完毕
  //private ManualResetEvent _lastrecvDone=new ManualResetEvent(false);  //上一次接收是否完毕
      
  private void ping()    //发送一次ping包 ,不经过_outSeqQueue 直接存储在 out queue中
  {
   uint seq=this.getNextSequence();
   MSG.CMPP_MSG_TEST test=new MSG.CMPP_MSG_TEST(seq);
   QueueItem q=new QueueItem(seq,(uint)MSG.CMPP_COMMAND_ID.CMPP_ACTIVE_TEST,0,0);
   q.setmsgObj(test);
   this.addToOutQueue(q);
  }
  
  private string getValIdTime(DateTime d)        //返回短信存活时间
  {
   DateTime n=d.AddHours(2); //2小时
   return(n.Year.ToString().Substring(2) + n.Month.ToString().PadLeft(2,’0′)+n.Day.ToString().PadLeft(2,’0′)+n.Hour.ToString().PadLeft(2,’0′)+n.Minute.ToString().PadLeft(2,’0′)+n.Second.ToString().PadLeft(2,’0′)+”032+”);           
  }
 
  private bool isPingTime( )  //是否到了ping一次的时间
  {
   System.TimeSpan   l=(DateTime.Now – this._current_time );
  
   if ( l.TotalSeconds >= (CMPPClient.CMPP_ACTIVE_TEST_C_TICKs))
   {   
    lock(this)
    {
     this._current_time =DateTime.Now;       
     return(true);
    }
   }
   else
   {
    return(false);
   }
  }
 
  private void checkReSend()    //是否需要再一次ping //查询 _waitingSeqQueue 是否存在 上一次 没有相应的消息
  {   //调查waiting queue 中的所有消息,如果入列时间超过60
   for(int i=0;i<this._waitingSeqQueue.Count;i++)
   {
    Thread.Sleep(20);
    QueueItem q=(QueueItem)this._waitingSeqQueue.GetByIndex(i);  
    if(q!=null)
    {
     DateTime this_time=DateTime.Now ; //去当前时间
     TimeSpan t=this_time-q.inQueueTime ;
     if(t.TotalSeconds >CMPPClient.CMPP_ACTIVE_TEST_T_TICKs ) //达到超时时间
     {//需要重新发送消息
      if(q.FailedCount>=CMPPClient.CMPP_ACTIVE_TEST_N_COUNT)
      {
       //报告消息发送失败
       if(this.onWaitingItemDeltedHandler!=null)
       {
        WaitingQueueItemEventArgs e=new WaitingQueueItemEventArgs(q);
        this.onWaitingItemDeltedHandler(this,e);
       }
       this.delFromWaitingQueue(q); //从等待队列中删除
       //q.MsgState =(int)MSG_STATE.SENDED_WAITTING;
      }
      else
      {//可以尝试继续发送
       q.inQueueTime = this_time;
       q.FailedCount ++ ;
       q.MsgState =(int)MSG_STATE.SENDED_WAITTING ;
       this.sendQueueItem(q);     
      }
     }     
    }
   }   
 
  }
 
  private void startThreads()
  {
   Deamo_Thread=new Thread(new ThreadStart(this.DeamonThread));
   Deamo_Thread.Start();
  }
 
  private QueueItem newQueueItem(int msgtype,int msgstate,object msg)  //生成一个消息队列成员对象实例
  {
   uint seq=this.getNextSequence();   //
   QueueItem q=new QueueItem(seq,(uint)msgtype,0,msgstate);
   q.setmsgObj(msg);       //设定消息为 object
   return(q);
  }
 
  private QueueItem getOutQueueItem(uint seq)  //获取MT 队列中的消息项目
  {
   lock(this)
   {
    return((QueueItem)this._outSeqQueue[seq]) ;
   }
  }
 
  private QueueItem getWaitingQueueItem(uint seq)  //获取等待队列中的消息
  {
   return((QueueItem) this._waitingSeqQueue[seq]);
  }
       
  private void addToOutQueue(QueueItem q)
  {
   lock(this)
   {
    this._outSeqQueue.Add(q.Sequence,q);    
   }
  }
 
  private void addToWaitingQueue(QueueItem q)
  {
   lock(this)
   {
    if(!this._waitingSeqQueue.ContainsKey(q.Sequence))
    {
     this._waitingSeqQueue.Add(q.Sequence,q);  
    }
   }
  }
 
  private QueueItem getTopOutQueue()     //需要在取之前进行判断
  {
   for(int i=0;i<this._outSeqQueue.Count;i++)
   {
    QueueItem q=(QueueItem)this._outSeqQueue.GetByIndex(i);  
    if(q!=null)
    {
     if(q.MsgState==(int)MSG_STATE.NEW)  //新消息,立即返回
     {
      lock(this)
      {
       q.MsgState =(int)MSG_STATE.SENDING; //发送状态
      }
      return(q);  
     }
     else
     {
      q=null;
     }
    }
   }   
   return(null);
  }
 
  private ArrayList getTop16Queue() //返回16条最顶的消息
  {
   int arrlength=0;
   ArrayList reArr=new ArrayList() ;
   QueueItem q=getTopOutQueue();
   while(q!=null || arrlength <= 16)
   {    
    if(q!=null)
    {
     reArr.Add(q);
     arrlength++;
    }
    else
    {
     break;
    }
    q=getTopOutQueue();
   }
   
   if(arrlength>0)
   {
    return(reArr);  
   }
   else
   {
    return(null);
   }
  }
 
  private void delFromOutQueue(QueueItem  q)
  {
   lock(this)
   {
    this._outSeqQueue.Remove(q.Sequence);  
   }
  }
 
  private void delFromOutQueue(uint seq)
  {
   lock(this)
   {
    this._outSeqQueue.Remove(seq); 
   }
  }
 
  private void delFromWaitingQueue(QueueItem q)
  {
   lock(this)
   {
    this._waitingSeqQueue.Remove(q.Sequence); 
   }
  }
 
  private void delFromWaitingQueue(uint seq)
  {
   this._waitingSeqQueue.Remove(seq); 
  }
 
  private void  SendLogin(string SystemID,string spNum,string Password)
  {//发送登录验证包   
   systemID=SystemID;
   userName=spNum;
   PassWord=Password;
   uint seq=this.getNextSequence(); //取得一个流水号
   MSG.CMPP_MSG_CONNECT cn=new MSG.CMPP_MSG_CONNECT(seq);
   cn.Password =Password.Trim();
   cn.SourceAdd =SystemID.Trim();
   tcp.Send(cn.ToBytes());
  }
 

  private byte[]  prepairPKs(QueueItem outitem)//将QueueItem发送出去
  {
   uint seq=outitem.Sequence ;
   uint msgtype=outitem.MsgType;  
   switch(msgtype)
   {
    case (uint)MSG.CMPP_COMMAND_ID.CMPP_ACTIVE_TEST :
     MSG.CMPP_MSG_TEST test=(MSG.CMPP_MSG_TEST) outitem.getMsgObj(); //发送队列中取出
     lock(this)
     {
      outitem.MsgState =(int)MSG_STATE.SENDING;
      this.delFromOutQueue(seq);
      this.addToWaitingQueue(outitem);    //等待服务器的active_TEST_resp
     }
     outitem.MsgState =(int)MSG_STATE.SENDED_WAITTING ;
     return(test.toBytes());      
      
 
    case (uint)MSG.CMPP_COMMAND_ID.CMPP_ACTIVE_TEST_RESP:
     MSG.CMPP_MSG_TEST_RESP test_reply=(MSG.CMPP_MSG_TEST_RESP)outitem.getMsgObj(); //发送队列中取出//取出需要发送的具体消息
     lock(this)
     {
      outitem.MsgState =(int)MSG_STATE.SENDING ;
      this.delFromOutQueue(seq);
     }
     outitem.MsgState = (int)MSG_STATE.SENDING_FINISHED ;  //完成
     return(test_reply.toBytes());
      
      
 
    case (uint)MSG.CMPP_COMMAND_ID.CMPP_CANCEL :
     MSG.CMPP_MSG_CANCEL cancel=(MSG.CMPP_MSG_CANCEL)outitem.getMsgObj();    //还原成消息类
     lock(this)
     {
      outitem.MsgState =(int)MSG_STATE.SENDING ;
      this.delFromOutQueue(seq);
      this.addToWaitingQueue(outitem);    //等待回应
     }
     outitem.MsgState =(int)MSG_STATE.SENDED_WAITTING ;
     return(cancel.toBytes());     
 
    case (uint)MSG.CMPP_COMMAND_ID.CMPP_DELIVER_RESP:
     MSG.CMPP_MSG_DELIVER_RESP deliver_resp=(MSG.CMPP_MSG_DELIVER_RESP)outitem.getMsgObj(); //发送队列中取出;
     lock(this)
     {
      outitem.MsgState =(int)MSG_STATE.SENDING ;
      this.delFromOutQueue(seq);
     }
     outitem.MsgState=(int)MSG_STATE.SENDING_FINISHED  ;  //完成
     return (deliver_resp.toBytes());      
      
 
    case (uint)MSG.CMPP_COMMAND_ID.CMPP_QUERY  :
     MSG.CMPP_MSG_QUERY query = (MSG.CMPP_MSG_QUERY )outitem.getMsgObj(); //发送队列中取出;
     lock(this)
     {
      outitem.MsgState =(int)MSG_STATE.SENDING  ;
      this.delFromOutQueue(seq);
      this.addToWaitingQueue(outitem);
     }
     outitem.MsgState =(int)MSG_STATE.SENDED_WAITTING ; //等待回应
     return(query.toBytes());      
      
    case (uint)MSG.CMPP_COMMAND_ID.CMPP_SUBMIT :
     MSG.CMPP_MSG_SUBMIT submit =(MSG.CMPP_MSG_SUBMIT)outitem.getMsgObj(); //发送队列中取出;
     lock(this)
     {
      outitem.MsgState =(int)MSG_STATE.SENDING ;
      this.delFromOutQueue(seq);
      this.addToWaitingQueue (outitem);
     }
     outitem.MsgState =(int)MSG_STATE.SENDING_FINISHED ;
     return(submit.toBytes());
            
    case (uint)MSG.CMPP_COMMAND_ID.CMPP_TERMINATE :
     MSG.CMPP_MSG_TERMINATE terminate=(MSG.CMPP_MSG_TERMINATE)outitem.getMsgObj(); //发送队列中取出;
     lock(this)
     {
      outitem.MsgState =(int)MSG_STATE.SENDING ;
      this.delFromOutQueue(seq);
      this.addToWaitingQueue(outitem);
     }
     outitem.MsgState =(int)MSG_STATE.SENDED_WAITTING ;
     return(terminate.toBytes());     
 
    case (uint)MSG.CMPP_COMMAND_ID.CMPP_TERMINATE_RESP :
     MSG.CMPP_MSG_TERMINATE_RESP terminate_resp=(MSG.CMPP_MSG_TERMINATE_RESP)outitem.getMsgObj(); //发送队列中取出;
     lock(this)
     {
      outitem.MsgState =(int)MSG_STATE.SENDING ;
      this.delFromOutQueue(seq);
     }
     outitem.MsgState =(int)MSG_STATE.SENDING_FINISHED  ;
     return(terminate_resp.toBytes()); 

    default:  
     test=(MSG.CMPP_MSG_TEST) outitem.getMsgObj(); //发送队列中取出
     lock(this)
     {
      outitem.MsgState =(int)MSG_STATE.SENDING;
      this.delFromOutQueue(seq);
      this.addToWaitingQueue(outitem);    //等待服务器的active_TEST_resp
     }
     outitem.MsgState =(int)MSG_STATE.SENDED_WAITTING ;
     return(test.toBytes()); 
   }   
  }

  private void sendQueueItem(QueueItem outitem)//将QueueItem发送出去
  {
   uint seq=outitem.Sequence ;
   uint msgtype=outitem.MsgType;
   try
   {
    switch(msgtype)
    {
     case (uint)MSG.CMPP_COMMAND_ID.CMPP_ACTIVE_TEST :
      MSG.CMPP_MSG_TEST test=(MSG.CMPP_MSG_TEST) outitem.getMsgObj(); //发送队列中取出
      lock(this)
      {
       outitem.MsgState =(int)MSG_STATE.SENDING;
       this.delFromOutQueue(seq);
       this.addToWaitingQueue(outitem);    //等待服务器的active_TEST_resp
      }
      tcp.Send(test.toBytes());
      outitem.MsgState =(int)MSG_STATE.SENDED_WAITTING ;
      break;
 
     case (uint)MSG.CMPP_COMMAND_ID.CMPP_ACTIVE_TEST_RESP:
      MSG.CMPP_MSG_TEST_RESP test_reply=(MSG.CMPP_MSG_TEST_RESP)outitem.getMsgObj(); //发送队列中取出//取出需要发送的具体消息
      lock(this)
      {
       outitem.MsgState =(int)MSG_STATE.SENDING ;
       this.delFromOutQueue(seq);
      }
      tcp.Send(test_reply.toBytes());
      outitem.MsgState = (int)MSG_STATE.SENDING_FINISHED ;  //完成
      break;
 
     case (uint)MSG.CMPP_COMMAND_ID.CMPP_CANCEL :
      MSG.CMPP_MSG_CANCEL cancel=(MSG.CMPP_MSG_CANCEL)outitem.getMsgObj();    //还原成消息类
      lock(this)
      {
       outitem.MsgState =(int)MSG_STATE.SENDING ;
       this.delFromOutQueue(seq);
       this.addToWaitingQueue(outitem);    //等待回应
      }
      tcp.Send(cancel.toBytes());     
      outitem.MsgState =(int)MSG_STATE.SENDED_WAITTING ;
      break;
 
     case (uint)MSG.CMPP_COMMAND_ID.CMPP_DELIVER_RESP:
      MSG.CMPP_MSG_DELIVER_RESP deliver_resp=(MSG.CMPP_MSG_DELIVER_RESP)outitem.getMsgObj(); //发送队列中取出;
      lock(this)
      {
       outitem.MsgState =(int)MSG_STATE.SENDING ;
       this.delFromOutQueue(seq);
      }
      tcp.Send(deliver_resp.toBytes());
      outitem.MsgState=(int)MSG_STATE.SENDING_FINISHED  ;  //完成
      break;
 
     case (uint)MSG.CMPP_COMMAND_ID.CMPP_QUERY  :
      MSG.CMPP_MSG_QUERY query = (MSG.CMPP_MSG_QUERY )outitem.getMsgObj(); //发送队列中取出;
      lock(this)
      {
       outitem.MsgState =(int)MSG_STATE.SENDING  ;
       this.delFromOutQueue(seq);
       this.addToWaitingQueue(outitem);
      }
      tcp.Send(query.toBytes());
      outitem.MsgState =(int)MSG_STATE.SENDED_WAITTING ; //等待回应
      break;
 
     case (uint)MSG.CMPP_COMMAND_ID.CMPP_SUBMIT :
      MSG.CMPP_MSG_SUBMIT submit =(MSG.CMPP_MSG_SUBMIT)outitem.getMsgObj(); //发送队列中取出;
      lock(this)
      {
       outitem.MsgState =(int)MSG_STATE.SENDING ;
       this.delFromOutQueue(seq);
       this.addToWaitingQueue (outitem);
      }
      tcp.Send(submit.toBytes());
      outitem.MsgState =(int)MSG_STATE.SENDING_FINISHED ;
      break;
 
     case (uint)MSG.CMPP_COMMAND_ID.CMPP_TERMINATE :
      MSG.CMPP_MSG_TERMINATE terminate=(MSG.CMPP_MSG_TERMINATE)outitem.getMsgObj(); //发送队列中取出;
      lock(this)
      {
       outitem.MsgState =(int)MSG_STATE.SENDING ;
       this.delFromOutQueue(seq);
       this.addToWaitingQueue(outitem);
      }
      if(this.tcpIsCanUse())
      {
       tcp.Send(terminate.toBytes());
       outitem.MsgState =(int)MSG_STATE.SENDED_WAITTING ;       
      }
      this.isStop =true;     //通知其他线程可以退出了
      break;
 
     case (uint)MSG.CMPP_COMMAND_ID.CMPP_TERMINATE_RESP :
      MSG.CMPP_MSG_TERMINATE_RESP terminate_resp=(MSG.CMPP_MSG_TERMINATE_RESP)outitem.getMsgObj(); //发送队列中取出;
      lock(this)
      {
       outitem.MsgState =(int)MSG_STATE.SENDING ;
       this.delFromOutQueue(seq);       
      }
      tcp.Send(terminate_resp.toBytes());
      outitem.MsgState =(int)MSG_STATE.SENDING_FINISHED  ;     
      break;
    }
    LogLastOkTime(DateTime.Now );  //记录当前最后一次消息soket正确时间
   }
   catch(SocketException se)
   {
    //发生套接字错误
    this.ErrorInfo =this.ErrorInfo +”\r\n”+se.ToString ();
   }
   catch(NullReferenceException nre)
   {
    this._bNre =true;  //出现空引用错误
    this.ErrorInfo =this.ErrorInfo +”\r\n”+nre.ToString ();
   }
  }
 
  private bool tcpIsCanUse()  //测试当前tcp是否可用
  {
   bool reval=true;
   DateTime t=DateTime.Now ;
   TimeSpan ts=t- this._lastOkTime;
   if(ts.TotalSeconds > CMPPClient.CMPP_ACTIVE_TEST_T_TICKs ) //60秒
   {
    reval=false;  //不可用
   }
   if(this._bNre )
   {
    reval=false;
   }
   return(reval);
  }
 
  private void _reStartRecvNSend()
  {
   Send_Thread=new Thread(new ThreadStart(this.SendSPMsgThread));
   Send_Thread.Start();
   Recv_Thread=new Thread(new ThreadStart(this.RecvISMGMsgThread));
   Recv_Thread.Start();
  }
 
  private void LogLastOkTime(DateTime lastoktime)
  {
   lock(this)
   {
    this._lastOkTime=lastoktime;  //设定最后成功消息交互时间
   }
  }
 
  private void defaultReportHandler() //却省的报告事件处理函数
  {
 
  }
 
  private void defaultSMSHandler()
  {
 
  }
 
  private void defaultTeminateHandler()
  {
 
  }
 
  private void defaultTestEventHandler()
  {
 
  }
  private void defaultTestRespEventHandler()
  {
 
  }
  private void defaultTerminateEventHandler()
  {
  }
  private void defaultTerminateRespEventHandler()
  {
  }
  private void defaultCancelRespEventHandler()
  {
  }
  private void defaultQueryRespEventHandler()
  {
  }
 
  private void defaultConnectRespEventHandler()
  {
   QueueItem q=new QueueItem(this.getNextSequence(),(uint)MSG.CMPP_COMMAND_ID.CMPP_ACTIVE_TEST,0,(int)MSG_STATE.NEW);
   MSG.CMPP_MSG_TEST test=new MSG.CMPP_MSG_TEST(q.Sequence ); //立即发送包过去
   q.setmsgObj(test);
   this.addToOutQueue(q);  
  }
  private void defaultSubmitRespEventHandler()
  {
  }

  private void defaultClientStopEventHandler()
  {}
    
  private void rePortError(string info)
  {
 
  }
       
  private bool _init(string CMPPServer,int CMPPPort)
  {
   bool reVal=false;
   CMPP_Server=CMPPServer;
   CMPP_Port=CMPPPort;
   try
   {
    tcp=new Socket(AddressFamily.InterNetwork ,SocketType.Stream ,ProtocolType.Tcp );
    ip=Dns.GetHostByName(CMPP_Server);
    cmpp_ep=new IPEndPoint(ip.AddressList[0],CMPP_Port);
    tcp.Connect(cmpp_ep); //连接
    reVal=true;  
   }
   catch(SocketException se)
   {
    ErrorInfo=”Socker Error:” + se.ToString();
   }
   return(reVal);  
  }
  private uint getNextSequence()
  {
   lock(typeof(CMPPClient))
   {
    try
    {
     lastSequence++;
    }
    catch(OverflowException ofe)
    {
     this.ErrorInfo =this.ErrorInfo +”\r\n”+ofe.ToString();
     lastSequence=uint.MinValue;
    }       
    return(lastSequence);
   }
  }
 
  private void RecvISMGMsgThread()   //处理ISMG消息的线程
  {
   while(!this.isStop )
   {
    try
    {    
     byte[] rbuf=new byte[10240]; //结果缓冲区
     byte[] recv_temp=new Byte[1024]; //recv临时缓冲区
     int index=0;
     int msglength=tcp.Receive(rbuf);  //阻塞接收//分析收到的数据
 
     MSG.CMPP_MSG_Header header;  //=new MSG.CMPP_MSG_Header(rbuf,index); //取得一个消息                   
     while(index<msglength) //逐个消息分析
     {
      header=new MSG.CMPP_MSG_Header(rbuf,index); //取得一个消息      
      byte[] the_pk= new byte[header.MSGLength] ;   //生成此消息的大小
      for(int i=0;i<header.MSGLength ;i++)
      {
       the_pk[i]=rbuf[index++];
      }      
      uint seq; //取得回复消息的下一个流水序列号
      switch(header.Command_ID)
      {
       case (uint)MSG.CMPP_COMMAND_ID.CMPP_ACTIVE_TEST : //服务器给客户的测试信号
        this.ErrorInfo =this.ErrorInfo +”\r\n”+”收到:CMPP_ACTIVE_TEST”;
        MSG.CMPP_MSG_TEST test=new MSG.CMPP_MSG_TEST(the_pk);
        seq=test.Sequence;       //取得发送过来的流水号
        MSG.CMPP_MSG_TEST_RESP test_reply=new MSG.CMPP_MSG_TEST_RESP(seq);  
        tcp.Send(test_reply.toBytes());    //马上送出回应包,不需要进入队列 
        if(this.onTestHandler!=null)
        {
         TestEventArgs e=new TestEventArgs(test);
         onTestHandler(this,e);
        }
        else
        {
         defaultTestEventHandler();
        }
        this.ErrorInfo =this.ErrorInfo +”\r\n”+”发送:CMPP_ACTIVE_TEST_RESP “;
        break;
 
       case (uint)MSG.CMPP_COMMAND_ID.CMPP_ACTIVE_TEST_RESP : //服务器的回应消息,应当丢弃不管
        this.ErrorInfo =this.ErrorInfo +”\r\n”+(“收到:CMPP_ACTIVE_TEST_RESP “);
        MSG.CMPP_MSG_TEST_RESP test_reply2=new MSG.CMPP_MSG_TEST_RESP(the_pk); //构造消息
        seq=test_reply2.Sequence;    //寻找 曾经发送过去的消息        
        this.delFromWaitingQueue(seq);      //删除等待队列中的消息 //清空等待回应队列
        if(this.onTestRespHandler!=null)
        {
         TestRespEventArgs e=new TestRespEventArgs(test_reply2);
         onTestRespHandler(this,e);
        }
        else
        {
         defaultTestRespEventHandler();
        }
        break;
 
       case (uint)MSG.CMPP_COMMAND_ID.CMPP_CANCEL_RESP :
        this.ErrorInfo =this.ErrorInfo +”\r\n”+(“收到:CMPP_CANCEL_RESP “);
        MSG.CMPP_MSG_CANCEL_RESP cancel_reply=new MSG.CMPP_MSG_CANCEL_RESP(the_pk);//构造消息
        seq=cancel_reply.Sequence;
        this.delFromWaitingQueue(seq);
        if(this.onCancelRespHandler!=null)
        {
         CancelRespEventArgs e=new CancelRespEventArgs(cancel_reply);
         onCancelRespHandler(this,e);
        }
        else
        {
         defaultCancelRespEventHandler();
        }
        break;
 
       case (uint)MSG.CMPP_COMMAND_ID.CMPP_CONNECT_RESP :   //检查下消息的正确性,清除等待队列 设定连接成功标志
        this.ErrorInfo =this.ErrorInfo +”\r\n”+(“收到:CMPP_CONNECT_RESP “);
        MSG.CMPP_MSG_CONNECT_RESP cn_reply=new MSG.CMPP_MSG_CONNECT_RESP(the_pk);
        seq=cn_reply.Sequence;     //取得消息的seq
        if(this.onConnectRespHandler !=null)
        {
         ConnectRespEventArgs e=new ConnectRespEventArgs(cn_reply);
         onConnectRespHandler(this,e);
        }
        else
        {
         defaultConnectRespEventHandler();
        }
        if(cn_reply.isOk)
        {
         this.isLogin  =true;
        }
        else
        {
         this.isLogin  =false;
        }
        this.delFromWaitingQueue(seq);    //删除队列中的等待连接信息包
        break;
 
       case (uint)MSG.CMPP_COMMAND_ID.CMPP_DELIVER:    //检查消息正确定,立即返回 正确 或者 失败,正确则处理是否状态包,不是状态包则存到MO缓存,表示收到信息,时状态包则判断缓存消息进行消息送达处理
        this.ErrorInfo =this.ErrorInfo +”\r\n”+(“收到:CMPP_DELIVER “);
        BIConvert.DumpBytes(the_pk,”c:\\CMPP_DELIVER.txt”);//保留映像
        MSG.CMPP_MSG_DELIVER deliver=new MSG.CMPP_MSG_DELIVER(the_pk);       
        seq=(uint)deliver.ISMGSequence;       //发过来的流水号,需要立即发送一个deliver_resp       //一条 ISMG–〉SP 的消息
        MSG.CMPP_MSG_DELIVER_RESP deliver_resp=new MSG.CMPP_MSG_DELIVER_RESP(seq);      
        deliver_resp.MsgID =deliver.MsgID ;
        deliver_resp.Result =0;
        byte[] t=deliver_resp.toBytes();
        tcp.Send(t);
        this.ErrorInfo =this.ErrorInfo +”\r\n”+(“发送:CMPP__DELIVER_RESP “);
        if(deliver.isReport)
        {      //删除等待队列的消息//报告消息已经正确发送到        
         //UInt64 ReportMsgID=deliver.ReportMsgID ; //取得消息ID ,更新 MsgID
         string StateReport=deliver.StateReport; //取得关于此消息的状态
         //_debugBs(the_pk);
         ReportEventArgs arg=new ReportEventArgs(the_pk,MSG.CMPP_MSG_Header.HeaderLength+8+21+10+1+1+1+21+1+1);    //构造报告事件参数
         //ReportEventArgs arg=new ReportEventArgs(ReportMsgID.ToString(),
         if(this.onReportHandler!=null) //ReportEventArgs传递的字节数组是 报告信息包的数据,在此不考虑多个报告的情况
         {
          onReportHandler(this,arg);
         }
         else
         {
          this.defaultReportHandler(); 
         }
        }
        else
        {//SMSEventArgs 传递的整个deliver包
         SMSEventArgs smsarg=new SMSEventArgs (the_pk,MSG.CMPP_MSG_Header.HeaderLength); 
         if(this.onSMSHandler!=null)
         {
          onSMSHandler(this,smsarg);   //触发事件,应当很快结束处理,不要靠考虑存储之类的耗费资源事宜
         }
         else
         {
          defaultSMSHandler();
         }
        }   
        break;
 
       case (uint)MSG.CMPP_COMMAND_ID.CMPP_QUERY_RESP :
        this.ErrorInfo =this.ErrorInfo +”\r\n”+(“收到:CMPP_QUERY_RESP “);
        //收到消息,处理后存入数据库
        MSG.CMPP_MSG_QUERY_RESP query_resp=new MSG.CMPP_MSG_QUERY_RESP(the_pk);
        this.delFromWaitingQueue(query_resp.Sequence );   //将等待的队列中的元素删除
        if(this.onQueryRespHandler!=null)
        {
         QueryRespEventArgs e=new QueryRespEventArgs(query_resp);
        }
        else
        {
         defaultQueryRespEventHandler();
        }
        break;
 
       case (uint)MSG.CMPP_COMMAND_ID.CMPP_SUBMIT_RESP :    //收到服务器送达的慧英消息
        this.ErrorInfo =this.ErrorInfo +”\r\n”+(“收到:CMPP_SUBMIT_RESP “);        
        MSG.CMPP_MSG_SUBMIT_RESP submit_resp=new MSG.CMPP_MSG_SUBMIT_RESP(the_pk); 
        BIConvert.DumpBytes(the_pk,”c:\\CMPP_SUBMIT_RESP.txt”);//保留映像
        //BIConvert.DumpBytes(initValue,”c:\\CMPP_SUBMIT_RESP.txt”);//保留映像
        sub_resp++; //该变量仅供测试使用
        delFromWaitingQueue(submit_resp.Sequence);  //删除需要等待的消息
        if(this.onSubmitRespHandler!=null)
        {
         SubmitRespEventArgs e=new SubmitRespEventArgs(submit_resp);
         //submit_resp.
         onSubmitRespHandler(this,e);
        }
        else
        {
         defaultSubmitRespEventHandler();
        }
 
        break;
 
       case (uint)MSG.CMPP_COMMAND_ID.CMPP_TERMINATE :
        this.ErrorInfo =this.ErrorInfo +”\r\n”+”收到:CMPP_TERMINATE”;
        MSG.CMPP_MSG_TERMINATE terminate=new MSG.CMPP_MSG_TERMINATE(the_pk);
        seq=terminate.Sequence;
        MSG.CMPP_MSG_TERMINATE_RESP  terminate_resp=new MSG.CMPP_MSG_TERMINATE_RESP(seq);
        this.ErrorInfo =this.ErrorInfo +”\r\n”+”收到:CMPP_TERMINATE_RESP”;
        tcp.Send(terminate_resp.toBytes()); 
        if(this.onTerminateHandler!=null)
        {
         TerminateEventArgs e=new TerminateEventArgs(terminate);
         onTerminateHandler(this,e);
         this.StopMe() ; //准备自我停止?
        }
        else
        {
         defaultTerminateEventHandler();
        }
        this._StopMe();  //发出终止设定        
        return;   //退出线程        
 
       case (uint)MSG.CMPP_COMMAND_ID.CMPP_TERMINATE_RESP :
        this.ErrorInfo =this.ErrorInfo +”\r\n”+”收到:CMPP_TERMINATE_RESP”;
        MSG.CMPP_MSG_TERMINATE_RESP ter_resp=new MSG.CMPP_MSG_TERMINATE_RESP(the_pk);
        seq=ter_resp.Sequence ;  //取得流水信号
        this.delFromOutQueue(seq);   //删除输出表重点项目
        if(this.onTerminateRespHandler!=null)
        {
         TerminateRespEventArgs e=new TerminateRespEventArgs(ter_resp);
         onTerminateRespHandler(this,e);
        }
        else
        {
         defaultTerminateRespEventHandler();
        }
        this._StopMe();
        break;
      }            
     }     
     LogLastOkTime(DateTime.Now );  //记录当前最后一次消息soket正确时间
    }
    catch(SocketException se)
    {
     //超时   
    }
    Thread.Sleep(50);
   }  
  }
  //debug
//  private void _debugBs(byte[] the_pk) //存储byte字节
//  {
//   
//  }
  //debug
 
  private void DeamonThread()    //监视本系统连接是否正常
  {//此线程是监视线程
   int  t_count =0;   //循环时间计数
   _reStartRecvNSend();   //启动接收和发送
   while(! this.isStop)
   {      
    t_count++;    //0.1秒   
    if(tcpIsCanUse()) 
    {
     if(this.isPingTime())
     {
      this.ping();  //发送一个ping包
     }
     if(t_count>50)  // 500*100=50000=50秒
     {
      t_count=0;
      checkReSend() ; //检查需要重新发送的消息
      //触发一个事件,让系统自动检查消息队列,存储消息队列中的消息状态
     }
    }
    else
    {
     EventArgs e=new EventArgs();
     if(this.onSocketClosedHandler!=null)
     {
      onSocketClosedHandler(this,e);
     }
     else
     {     
     }
     this.isStop =true;  //通知其他线程退出
    }
    Thread.Sleep(1000);
   }
  }  
 
  private void SendSPMsgThread()
  {
   while (!this.isStop )
   {
    Thread.Sleep(10);
    if(this.isLogin)
    {
     ArrayList lists=this.getTop16Queue();  //取出16条最顶的消息    
     if(lists!=null  && lists.Count >0)
     {
      int count=lists.Count;            
      ArrayList pks=new ArrayList( count); //定义容量
      for (int i=0;i<lists.Count; i++)
      {
       QueueItem outitem=(QueueItem)lists[i]; //取出每一个消息对象
       if(outitem!=null)
       {
        try
        {
         sendQueueItem(outitem);    //发送每一个消息
        }
        catch(SocketException se)
        {
         //发送失败
         outitem.FailedCount ++;
        }
       }      
      }
     }
    }
    Thread.Sleep(100);
   }  
  } 

  private void _StopMe()
  {
   lock(this)
   {
    this.isStop =true;
   }
  }
 
  private void _forcedSubThread(Thread t)   //强制停止线程
  {
   try
   {
    t.Abort();
    t.Join(); 
   }
   catch(Exception )
   {}
  }
 
  //private 函数区域//////////////////////////////////////////////////////////////////
 
 
  //公用函数 属性区域////////////////////////////////////////
  public bool Init(string CMPPServer,int CMPPPort)
  {
   return(this._init(CMPPServer,CMPPPort));
  }
 
  public bool Init(string CMPPServer,int CMPPPort,int recvtimeout,int sendtimeout)
  {
   this.RecvTimeOut =recvtimeout;
   this.SendTimeout =sendtimeout;
   return(this._init(CMPPServer,CMPPPort));
  }
 
  public bool Init(string CMPPServer,int CMPPPort,int recvtimeout)
  {
   this.RecvTimeOut =recvtimeout;
   this.SendTimeout =recvtimeout;
   return(this._init(CMPPServer,CMPPPort));
  }
  
  public bool Login(string SystemID,string UserName,string Password)
  {
   try
   {
    SendLogin(SystemID, UserName, Password);
    this.LogLastOkTime(DateTime.Now);    //最后一次正确的发送
   }
   catch(SocketException se)
   {
    //发送出错
    this.ErrorInfo = this.ErrorInfo +”\r\n”+se.ToString();
    return(false);
   }
   DateTime t1=DateTime.Now;
   while(!this.isLogin)
   {
    byte[] rbuf=new Byte[400];
    int l;
    try
    {
     l=tcp.Receive(rbuf) ;
     if(l>16)
     {
      if(BIConvert.Bytes2UInt(rbuf,4)==(uint)MSG.CMPP_COMMAND_ID.CMPP_CONNECT_RESP)
      {
       MSG.CMPP_MSG_CONNECT_RESP resp=new MSG.CMPP_MSG_CONNECT_RESP(rbuf);
       if(resp.isOk)
       {
        EventArgs e=new EventArgs();
        if(onLogonSuccEventHandler!=null)
        {
         onLogonSuccEventHandler(this,e);
        }
        else
        {
         this.defaultConnectRespEventHandler();
        }
        this.isLogin =true;
       }
       else
       {
       }
       break;
      }
     }
     this._lastOkTime =DateTime.Now ;  //更新当前最后成功收发套接字的时间
    }
    catch(SocketException)
    {
    }
    System.TimeSpan t=DateTime.Now – t1;
    if(t.TotalSeconds > 10)
    {
     break;
    }
   }  
   if(this.isLogin)
   { //登录ok,就立即发送active_test包
    this.ErrorInfo =this.ErrorInfo + “\r\n”+” Logon succ! “;    
    startThreads();  // 启动 主监视程序de线程
    return(true);
   }
   else
   {
    return(false);
   }
  }
   
  public uint SubmitSMS(string to_user,string fee_code,string svc_code, string fee_user,string spnum,string content,int fee_usertype)
  {
   MSG.CMPP_MSG_SUBMIT sndmsg; 
   uint seq=this.getNextSequence();   //取得下一个sequence
   sndmsg=new MSG.CMPP_MSG_SUBMIT(seq);
   sndmsg.FeeCode =fee_code;
   sndmsg.FeeTerminalId =to_user;
   sndmsg.FeeType=MSG.FeeType.FEE_TERMINAL_PERITEM; //按条收取
   sndmsg.FeeUserType = fee_usertype ;
   sndmsg.Msg_Level=0;
   sndmsg.MSGFormat = (uint)MSG.Msg_Format.UCS2;
   sndmsg.SMS_Content=content;
   sndmsg.SrcID=spnum;         //长号码
   sndmsg.SPID=this.systemID ;
   sndmsg.Svc_Code= svc_code;
   sndmsg.UDHI=0;
   sndmsg.ValIdTime=getValIdTime(DateTime.Now);        //存活时间
   sndmsg.addTerminalID(to_user);
   QueueItem q=new QueueItem(seq,(uint)MSG.CMPP_COMMAND_ID.CMPP_SUBMIT  ,0,0); 
   q.setmsgObj(sndmsg);
   this.addToOutQueue(q);  
   return(seq);
  }
 
  public uint SendMsg(string to_user,string fee_user,string fee,string svccode,string content,string spnum)
  {
   uint seq=this.getNextSequence();
   MSG.CMPP_MSG_SUBMIT sndmsg=new MSG.CMPP_MSG_SUBMIT(seq) ;
   sndmsg.FeeCode=fee;
   sndmsg.FeeType=MSG.FeeType.FEE_TERMINAL_PERITEM ;
   sndmsg.FeeTerminalId =fee_user;
   sndmsg.FeeUserType =(int)MSG.FeeUserType.FEE_NULL ;    //计费 按照计费号码计费
   sndmsg.SPID =this.systemID ;         //企业代码
   sndmsg.UDHI=0;             //
   sndmsg.MSGFormat=(uint)MSG.Msg_Format.GB2312 ;
   sndmsg.SMS_Content =content;
   sndmsg.SrcID=spnum;
   sndmsg.Svc_Code=svccode;
   sndmsg.addTerminalID(to_user);
   QueueItem q=new QueueItem(seq,(uint)MSG.CMPP_COMMAND_ID.CMPP_SUBMIT  ,0,0); 
   q.setmsgObj(sndmsg);
   this.addToOutQueue(q);
   return(seq);
  }
 
  public uint SendSMC(string fee_user,string feecode,string svccode)  //向计费用户发送一条包月计费信息
  {
   uint seq=this.getNextSequence();
   MSG.CMPP_MSG_SUBMIT sndmsg=new MSG.CMPP_MSG_SUBMIT(seq) ;
   sndmsg.SMS_Delivery_Type=2;         //产生包月SMC
   sndmsg.FeeCode=feecode;
   sndmsg.FeeType=MSG.FeeType.FEE_TERMINAL_MONTH ;   //包月计费
   sndmsg.FeeTerminalId =fee_user;
   sndmsg.FeeUserType =(int)MSG.FeeUserType.FEE_TERMINAL_ID  ;    //计费 按照计费号码计费
   sndmsg.SPID =this.systemID ;         //企业代码
   sndmsg.UDHI=0;             //
   sndmsg.MSGFormat=(uint)MSG.Msg_Format.UCS2 ;
   sndmsg.SMS_Content =”SMC”;  
   sndmsg.SrcID =this.userName;         //sp的特符号码
   sndmsg.Svc_Code=svccode;
   sndmsg.addTerminalID(fee_user);
   QueueItem q=new QueueItem(seq,(uint)MSG.CMPP_COMMAND_ID.CMPP_SUBMIT ,0,0); 
   q.setmsgObj(sndmsg);
   this.addToOutQueue(q);
   return(seq);
  }
 
  public uint SendSMT(string to_user,string feecode,string svccode,string spnum,string content)
  {
   uint seq=this.getNextSequence();
   MSG.CMPP_MSG_SUBMIT sndmsg=new MSG.CMPP_MSG_SUBMIT(seq) ;
   sndmsg.SMS_Delivery_Type=1;         //产生包月SMC
   sndmsg.FeeCode=feecode;          //包月计费代码
   sndmsg.FeeType=MSG.FeeType.FEE_TERMINAL_MONTH ;   //包月计费
   sndmsg.FeeTerminalId =to_user;
   sndmsg.FeeUserType =(int)MSG.FeeUserType.FEE_TERMINAL_ID  ;    //计费 按照计费号码计费
   sndmsg.SPID =this.systemID ;         //企业代码
   sndmsg.UDHI=0;             //
   sndmsg.MSGFormat=(uint)MSG.Msg_Format.UCS2 ;
   sndmsg.SMS_Content =content;
   sndmsg.SrcID =spnum;         //sp的特符号码
   sndmsg.Svc_Code=svccode;
   sndmsg.addTerminalID(to_user);
   QueueItem q=new QueueItem(seq,(uint)MSG.CMPP_COMMAND_ID.CMPP_SUBMIT ,0,0); 
   q.setmsgObj(sndmsg);
   this.addToOutQueue(q);
   return(seq);
  }
  
  public uint SendQuery(string svccode,string whichday) //查询某个业务的总计数
  {
   string wd=whichday.Trim();
   int query_type=0;
   if(svccode==null || svccode.CompareTo(“”)==0)
   {//查询全部页数量
   }
   else
   {//查询某项业务
    query_type=1;
   }
   if(wd==null|| wd.CompareTo (“”)==0)
   {
    DateTime d=DateTime.Now;
    wd=d.Year.ToString()+d.Month.ToString().PadLeft(2,’0′)+d.Day.ToString().PadLeft(2,’0′);       
   }
   uint seq=this.getNextSequence();
   MSG.CMPP_MSG_QUERY query=new MSG.CMPP_MSG_QUERY(seq); 
   query.Query_Type =query_type;
   query.Query_Code =svccode;
   query.Time =wd;     //设定那一天
   QueueItem q=new QueueItem(seq,(uint)MSG.CMPP_COMMAND_ID.CMPP_QUERY ,0,0); 
   q.setmsgObj(query);
   this.addToOutQueue(q);
   return(seq);   //返回消息的内部编号
  }
 
  public uint StopCMPPConnection()   //停止CMPP协议的socket连接
  {
   uint seq=this.getNextSequence();
   MSG.CMPP_MSG_TERMINATE t=new MSG.CMPP_MSG_TERMINATE(seq);
   QueueItem q=new QueueItem(seq,(uint)MSG.CMPP_COMMAND_ID.CMPP_TERMINATE,0,0);
   q.setmsgObj(t);
   this.addToOutQueue(q);
   return(seq); //返回终止消息,便于等待
  }
 

  public uint CancelMsg( string   msgid)
  {
   uint seq=this.getNextSequence();
   MSG.CMPP_MSG_CANCEL  cancel=new MSG.CMPP_MSG_CANCEL(seq); 
   cancel.MsgID =msgid;
   QueueItem q=new QueueItem(seq,(uint)MSG.CMPP_COMMAND_ID.CMPP_CANCEL  ,0,0); 
   q.setmsgObj(cancel);
   this.addToOutQueue(q);
   return(seq);   //返回消息的内部编号
  }
 
  public void StopMe()
  {
   if(!this.isStop)
   {
    if(this.tcpIsCanUse())//发送一条对服务器的通告
    {
     uint seq=this.getNextSequence();
     MSG.CMPP_MSG_TERMINATE t=new MSG.CMPP_MSG_TERMINATE(seq);
     QueueItem q=new QueueItem(seq,(uint)MSG.CMPP_COMMAND_ID.CMPP_TERMINATE,0,0);
     q.setmsgObj(t);
     this.addToOutQueue(q);
    }  
    Thread.Sleep(500);   //等待1000ms,告知服务器
    this._StopMe();
    tcp.Close();

    if(this.onClientSvcStopedHandler!=null)
    {
     ClientQueueStateArgs  arg=new ClientQueueStateArgs(this._outSeqQueue ,this._waitingSeqQueue);
     onClientSvcStopedHandler(this,arg);
    }
    else
    {
     this.defaultClientStopEventHandler();
    }
    Thread.Sleep(500);   //再次主动等待线程结束         
    //此处报告 2个队列中的信息    
   }
   //准备强行结束
   _forcedSubThread(this.Send_Thread);
   Thread.Sleep(500);   //等待1000ms,告知服务器
   _forcedSubThread(this.Recv_Thread );
   Thread.Sleep(500);   //等待1000ms,告知服务器
   _forcedSubThread(this.Deamo_Thread );  
   Thread.Sleep(500);   //等待1000ms,告知服务器
  }
 
  public string getLogInfo()
  {
   string t= this.ErrorInfo;
   this.ErrorInfo=”";
   return(t);  
  }

  public int getQueueItemState(uint seq)  //根据seq寻找发送内部队列的消息对象的状态
  {
   int status=0;       //状态未知
   if(this._outSeqQueue.ContainsKey(seq)) //存在于outSeqQueue中
   {
    if(this._waitingSeqQueue.Contains(seq))
    {
     //正在发送等待返回,状态未定
    }
    else
    {
     //还没有发送
    }
   }
   else
   {
    if(this._waitingSeqQueue.ContainsKey(seq))
    {
     //正等待回应
    }
    else
    {
     //已经发送结束了
    }
   }
   return(status);
  }
  
  public void TestSubmit( string[] nums ,int topI,int topJ)  //发送测试包
  {
   int count=0;
   int total=0;   
   ArrayList pks=new ArrayList( );
   //准备100个包
   for(int i=0;i<10;i++)
   {
    for(int j=0;j<10;j++)
    {
     uint seq=this.getNextSequence(); //准备流水号
     MSG.CMPP_MSG_SUBMIT sndmsg=new MSG.CMPP_MSG_SUBMIT(seq);
     sndmsg.FeeCode =”000001″;
     sndmsg.FeeTerminalId =nums[i];
     sndmsg.FeeType=MSG.FeeType.FEE_TERMINAL_PERITEM; //按条收取
     sndmsg.FeeUserType = 0 ;  //终端用户计费
     sndmsg.Msg_Level=0;
     sndmsg.MSGFormat = (uint)MSG.Msg_Format.UCS2;
     sndmsg.SMS_Content=”test”;
     sndmsg.SrcID=”09880″;         //长号码
     sndmsg.SPID=this.systemID ;
     sndmsg.Svc_Code= “cmcctest”;
     sndmsg.UDHI=0;
     sndmsg.ValIdTime=getValIdTime(DateTime.Now);        //存活时间
     sndmsg.addTerminalID(nums[i]);
     pks.Add( sndmsg.toBytes()) ;   //存入数组
    }
   }
 
   DateTime t1=DateTime.Now ;
   for(int i=0;i< topI;i++)
   {  
    for(int j=0;j<topJ;j++)
    {
     try
     {
      tcp.Send((byte[])pks[i*10+j]);
      count++;
      total++;
     }
     catch (SocketException se)
     {
      this.ErrorInfo =this.ErrorInfo +”\r\n”+”发送错误: “+se.ToString() ;
     }   
     if( count>=16)
     {
      count=0;  //复位
      Thread.Sleep(50);  //暂停20ms
     }
    }
   }
   DateTime t2=DateTime.Now ;
   TimeSpan t= t2-t1;
   this.ErrorInfo =this.ErrorInfo +”\r\n”+”发送: “+total +” 条消息, 总计花费时间:”+ t.TotalMilliseconds +”毫秒” ;
  }  //测试函数////////////////////////////////////////////////供测试移动网络测试
  
  //测试翰数区域///////////////////////////////////////////
  //公用函数 属性区域////////////////////////////////////////
 }
 //*************工具类结束***********************************
 enum MSG_STATE     //CMPP消息在队列中的状态枚举值
 {
  NEW=0,      //加入到队列等待发送出去
  SENDING=1,     //正被某个线程锁定
  SENDED_WAITTING=2,   //发送出去,现在等待resp消息返回
  SENDING_FINISHED=3   //得到回应,一般等待被清理出队列
 }
 
 public class QueueItem   //代表一个存储在缓存队列中的消息,序列号由CMPPClient产生
 {
  uint _sequence;    //消息索引 就是流水号
  uint _msgType;    //消息的类别就是COMMAND_ID,根据此值决定 Object _msgObj的原类型
  int _failedCount=0;   //失败计数,如果失败次数超过3此需要进行清理
  int _msgState;    //当前消息状态,具体为 MSG_STATE的枚举类型
  object _msgObj;    //存放消息对象,具体类型参考 _msgType
  DateTime _inQueueTime;  //消息进入队列的时间,上次消息的发送时间
 
  public int FailedCount
  {
   set
   {
    this._failedCount =value;
   }
   get
   {
    return(this._failedCount);
   }
 
  }
 
  public object getMsgObj()
  {
   return(this._msgObj);
  }
  public void setmsgObj(object inmsg)
  {
   this._msgObj=inmsg;
  }
  public DateTime inQueueTime
  {
   set
   {
    this._inQueueTime =value;
   }
   get
   {
    return(this._inQueueTime);
   }
  }
  public uint MsgType
  {
   get
   {
    return(this._msgType);
   }
  }
  public int MsgState
  {
   get
   {
    return(this._msgState);
   }
   set
   {
    this._msgState =value;
   }
  }
  public uint Sequence
  {
   get
   {
    return(this._sequence);
   }
   set
   {
    this._sequence =value;
   }
  }
  public QueueItem(uint sequence,uint  msgtype ,int faildedcount,int msgstate)
  {
   this._failedCount =faildedcount;
   this._msgState =msgstate;
   this._msgType =msgtype;
   this._sequence=sequence;
  }
  public QueueItem(uint sequence,uint msgtype,int faildedcount,int msgstate,object msgobj)
  {
   this._failedCount =faildedcount;
   this._msgState =msgstate;
   this._msgType =msgtype;
   this._sequence=sequence;
   this.setmsgObj(msgobj);
  }
 }
 
 public class BIConvert  //字节 整形 转换类 网络格式转换为内存格式
 {
  public static byte[] Int2Bytes(uint i)  //转换整形数据网络次序的字节数组
  {
   byte[] t=BitConverter.GetBytes(i) ;
   byte b=t[0];
   t[0]=t[3];
   t[3]=b;
   b=t[1];
   t[1]=t[2];
   t[2]=b;
   return(t);
  }
 
  public static uint Bytes2UInt(byte[] bs,int startIndex) //返回字节数组代表的整数数字,4个数组
  {
   byte[] t=new byte[4];
   for(int i=0;i<4 && i< bs.Length-startIndex ;i++)
   {
    t[i]=bs[startIndex+i];
   } 
   byte b=t[0];
   t[0]=t[3];
   t[3]=b;
   b=t[1];
   t[1]=t[2];
   t[2]=b;
   return(BitConverter.ToUInt32(t,0));
  }
 
  public static uint Bytes2UInt(byte[] bs)  //没有指定起始索引
  {
   return( Bytes2UInt(bs,0));
  }

  public static void  DumpBytes(byte[] bs,string txt)
  {
   System.IO.StreamWriter sw=new System.IO.StreamWriter(txt);
   for(int i=0;i<bs.Length ;i++)
   {
    byte b=bs[i];
    sw.WriteLine(b.ToString(“X”)+” “);
   }
   sw.WriteLine(“—–”+DateTime.Now.ToLocalTime()  );
   sw.Close();
  }

  public static void  DebugString(string  bs,string txt)
  {
   System.IO.StreamWriter sw=new System.IO.StreamWriter(txt);
   sw.WriteLine(bs); 
   sw.WriteLine(“—–”+DateTime.Now.ToLocalTime()  );
   sw.Close();
  }
 }
 
 public class ReportEventArgs : EventArgs   //报告事件携带的数据
 {
  string _smsState;      //发送短信的应答结果,含义与SMPP协议要求中stat字段定义相同 。SP根据该字段确定CMPP_SUBMIT消息的处理状态。
  string _submitTime;      //提交短信的时间,也可根据此时间决定是否重发
  string _doneTime;      //送达目的地的时间
  string _destNum;      //送达的号码
  string _msgID;       //关于那一条消息的报告
  uint _sequence;       //CMPP网关产生的流水号

  UInt64 _msg_id;   //被报告的提交短信的msgID,ISMG在submit_resp返回给SP的

  public string State
  {
   get
   {
    return(this._smsState);
   }
   set
   {
    this._smsState =value;
   }
  }
 
  public uint Sequence
  {
   get
   {
    return(this._sequence );
   }
   set
   {
    this._sequence =value;
   }
  }
 
  public string toUserNum
  {
   get
   {
    return(this._destNum);
   }
   set
   {
    this._destNum =value;
   }
  }
 
  public string MsgID
  {
   get
   {
    return( this._msgID );
   }
   set
   {
    this._msgID =value;
   }
  }
 
  public string SubmitTime
  {
   get
   {
    return(this._submitTime);
   }
   set
   {
    this._submitTime =value;
   }
  }
 
  public string DoneTime
  {
   get
   {
    return(this._doneTime );
   }
   set
   {
    this._doneTime =value;
   }
  }
 
  public ReportEventArgs(byte[] bs)  //从一个字节数组中获得报告
  {
   byte[] temp=new byte[8+7+10+10+21+4];
   for(int i=0;i<temp.Length;i++)
   {
    temp[i]=bs[i];
   }
   init(temp);
  }
 
  public ReportEventArgs(byte[] bs,int startIndex) //起始
  {
   byte[] temp=new byte[8+7+10+10+21+4];//定义长度
   for(int i=0;i<temp.Length;i++)
   {
    temp[i]=bs[startIndex+i];
   }
   init(temp);
  }
 
  public ReportEventArgs(string msgid,string destnum,string smsstate,string submittime,string donetime,uint seq)
  {
   this._msgID =msgid;
   this._destNum =destnum;
   this._smsState =smsstate;
   this._submitTime =submittime;
   this._doneTime =donetime;
   this._sequence =seq;
  }
 
  public DateTime getSubmitTime()
  {
   return(getTime(this._submitTime));
  }
 
  public DateTime getDoneTime()
  {
   return(getTime(this._doneTime));
  }
 
  private DateTime getTime(string time_string)
  {
   int index=0;
   int yy=Convert.ToInt32(“20″+ time_string.Substring(index,2));   
   index+=2;
   int mm=Convert.ToInt32(time_string.Substring(index,2));
   index+=2;
   int dd=Convert.ToInt32(time_string.Substring(index,2));
   index+=2;
   int hh=Convert.ToInt32(time_string.Substring(index,2));
   index+=2;
   int mms=Convert.ToInt32(time_string.Substring(index,2));
   DateTime t=new DateTime(yy,mm,dd,hh,mms,0);   
   return(t);
  }
  private void init(byte[] bs)
  {
   BIConvert.DumpBytes(bs,”c:\\ReportEventArgs.txt”);//保留映像
   int index=0;
   this._msg_id =BitConverter.ToUInt64(bs,index);   //BitConverter.ToUInt64(bs,index);
   this._msgID =(this._msg_id.ToString());
           // BIConvert.DebugString(this._msgID ,”c:\\MSGID.txt”); 
   index +=8;
   this._smsState = Encoding.ASCII.GetString(bs,index,7);
   index+=7;
   this._submitTime = Encoding.ASCII.GetString(bs,index,10);
   index+=10;
   this._doneTime  = Encoding.ASCII.GetString(bs,index,10);
   index+=10;
   this._destNum = Encoding.ASCII.GetString(bs,index,21);
   index+=21;
   this._sequence = BIConvert.Bytes2UInt(bs,index);
  }
 }
 
 public class SMSEventArgs : EventArgs
 {
  UInt64 _msgid;    //8字节的消息标示
  string _destID;   //接受信息的目标ID
  string _svcCode;    //业务代码
  int  _tpPID;    //参考GSM协议
  int  _tpUDHI;   //
  int  _msgFrm;   //消息的编码格式
  string _srcTerminateID;  //源终端ID,如果使报告
  int  _msgLength;   //消息的字节数,并非实际字符串长度
  string _Content;   //消息正文内容
 

  public SMSEventArgs(byte[] bs)
  {
   int msglen=BitConverter.ToInt32(bs,8+21+10+1+1+1+21+1);  //取得消息长度字节长度
   int tempLen=msglen+8+21+10+1+1+1+21+1+1+msglen+8;
   byte[] temp=new byte[tempLen];
   for(int i=0;i<temp.Length ;i++)
   {
    temp[i]=bs[i];
   }
   init(temp);
  }
 
  public SMSEventArgs(byte[] bs,int baseIndex)
  {
   int msglen= (int)bs[MSG.CMPP_MSG_Header.HeaderLength +8+21+10+1+1+1+21+1];  //取得消息长度字节长度
   int tempLen=8+21+10+1+1+1+21+1+1+msglen+8;
   byte[] temp=new byte[tempLen];
   for(int i=0;i<temp.Length ;i++)
   {
    temp[i]=bs[i+baseIndex];
   }
   init(temp);
  }
 
  private void init(byte[] bs)
  {
   BIConvert.DumpBytes(bs,”c:\\SMSEventArgs.txt”);//保留映像

   int index=0;
   this._msgid = BitConverter.ToUInt64(bs,0);
   index+=8;
   this._destID = Encoding.ASCII.GetString(bs,index,_getRealBytesLength(bs,index));
   index+=21;
   this._svcCode = Encoding.ASCII.GetString(bs,index,_getRealBytesLength(bs,index));
   index+=10;
   this._tpPID =(int)bs[index++];
   this._tpUDHI  =(int)bs[index++];
   this._msgFrm = (int)bs[index++];
   this._srcTerminateID =Encoding.ASCII.GetString(bs,index,_getRealBytesLength(bs,index));
   index+=21;
   index++;        //是否是状态报告字节
   this._msgLength = (int)bs[index++];  //取得字节长度
  
   switch ( this._msgFrm )
   {
    case (int)MSG.Msg_Format.ASCII :
     this._Content =Encoding.ASCII.GetString(bs,index,this._msgLength );
     break;
 
    case (int)MSG.Msg_Format.GB2312 :
     this._Content = Encoding.Default.GetString(bs,index,this._msgLength ); 
     break;
 
    case (int)MSG.Msg_Format.UCS2 :
     this._Content = Encoding.BigEndianUnicode.GetString(bs,index,this._msgLength );
     break;
 
    case (int)MSG.Msg_Format.BINARY :
     break;
 
    case (int)MSG.Msg_Format.WRITECARD :
     break;
 
    default:
     break;
 
   }
 
  }
 
  public string toSPNum
  {
   get
   {
    return(this._destID );
   }
  }
 
  public string SrcNum
  {
   get
   {
    return(this._srcTerminateID);
   }
  }
 
  public string Content
  {
   get
   {
    return(this._Content );
   }
  }
  public string SvcCode
  {
   get
   {
    return(this._svcCode);
   }
  }

  public UInt64  MsgID
  {
   get
   {
    return(this._msgid) ;
   }
   //set
   //{
   // this._msgid =value;
   //}
  }

  public string MsgIDString
  {
   get
   {
    return(this._msgid).ToString(); 
   }
  }

  private int  _getRealBytesLength(byte[] bts,int index)
  {
   int i=index;
   for( ;i<bts.Length ;i++)
   {
    if(bts[i]==0)
    {
     break;
    }
   }
   return i-index;
  }
 }
 
 public class TerminateEventArgs:EventArgs
 {
  private uint _seq;
  private MSG.CMPP_MSG_TERMINATE _msg;
 
  public TerminateEventArgs( uint seq)
  {
   this._seq =seq;
  }
 
  public TerminateEventArgs(object msg)
  {  
   this._msg =(MSG.CMPP_MSG_TERMINATE)msg;
   this._seq =this._msg.Sequence ;
  }
 
  public object getMSG()
  {
   return(this._msg);
  }
  
 }
 
 public class TerminateRespEventArgs:EventArgs
 {
  private uint _seq;
  private MSG.CMPP_MSG_TERMINATE_RESP _msg;
 
  public TerminateRespEventArgs(uint seq)
  {
   this._seq =seq;
  }
 
  public TerminateRespEventArgs(object msg)
  {
   this._msg =(MSG.CMPP_MSG_TERMINATE_RESP)msg;
   this._seq =this._msg.Sequence ;
  }
 
  public object getMSG()
  {
   return(this._msg );
  }
 
  public uint Sequence
  {
   set
   {
    this._seq =value;
   }
   get
   {
    return(this._seq);
   }
  }
 }
 public class TestEventArgs: EventArgs
 {
  private uint _seq;
  private MSG.CMPP_MSG_TEST _msg;
 
  public TestEventArgs(uint seq)
  {
   this._seq =seq;
  }
 
  public  TestEventArgs(object msg)
  {
   this._msg =(MSG.CMPP_MSG_TEST)msg;
   this._seq =this._msg.Sequence ;
  }
 
  public object getMSG()
  {
   return(this._msg );
  }
 
  public uint Sequence
  {
   set
   {
    this._seq =value;
   }
   get
   {
    return(this._seq );
   }
  }
 }
 
 public class TestRespEventArgs: EventArgs
 {
  private uint _seq;
  private MSG.CMPP_MSG_TEST_RESP _msg;
 
  public TestRespEventArgs(uint seq)
  {
   this._seq =seq;
  }
  public TestRespEventArgs(object msg)
  {
   this._msg =(MSG.CMPP_MSG_TEST_RESP)msg;
   this._seq =this._msg.Sequence ;
  }
 
  public object getMSG()
  {
   return(this._msg );
  }
 
  public uint Sequence
  {
   set
   {
    this._seq =value;
   }
   get
   {
    return(this._seq);
   }
  }
 }
 
 public class CancelRespEventArgs:EventArgs
 {
  private uint _seq;
  private MSG.CMPP_MSG_CANCEL_RESP _msg;
 
  public CancelRespEventArgs(uint seq)
  {
   this._seq =seq;
  }
  public CancelRespEventArgs(object msg)
  {
   this._msg =(MSG.CMPP_MSG_CANCEL_RESP) msg;
   this._seq =this._msg.Sequence ;
  }
 
  public object getMSG()
  {
   return(this._msg);
  }
 
  public uint Sequence
  {
   set
   {
    this._seq =value;
   }
   get
   {
    return(this._seq );
   }
  }
 }
 
 public class QueryRespEventArgs:EventArgs
 {
  private uint _seq;
  private MSG.CMPP_MSG_QUERY_RESP _msg;
 
  public QueryRespEventArgs(uint seq)
  {
   this._seq =seq;  
  }
 
  public QueryRespEventArgs(object msg)
  {
   this._msg =(MSG.CMPP_MSG_QUERY_RESP)msg;
   this._seq =this._msg.Sequence; 
  }
 
  public object getMSG()
  {
   return(this._msg);
  }
  public uint Sequence
  {
   set
   {
    this._seq =value;
   }
   get
   {
    return(this._seq);
   }
  }
 
 }
 
 public class ConnectRespEventArgs:EventArgs
 {
  private uint _seq;
  private MSG.CMPP_MSG_CONNECT_RESP _msg;
 
  public ConnectRespEventArgs(uint seq)
  {
   this._seq =seq;
  }
 
  public ConnectRespEventArgs(object msg)
  {
   this._msg =(MSG.CMPP_MSG_CONNECT_RESP)msg;
   this._seq =this._msg.Sequence ;
  }
 
  public object getMSG()
  {
   return(this._msg );
  }
 
  public uint Sequence
  {
   set
   {
    this._seq =value;
   }
   get
   {
    return(this._seq );
   }
  }
 }
 
 public class SubmitRespEventArgs:EventArgs
 {
  private uint _seq;
  private MSG.CMPP_MSG_SUBMIT_RESP _msg;  
 
  public SubmitRespEventArgs(uint seq)
  {
   this._seq =seq;   
  }
  public SubmitRespEventArgs(object msg)
  {
   this._msg =(MSG.CMPP_MSG_SUBMIT_RESP)msg;
   this._seq=this._msg.Sequence ;
  }
  public object getMSG()
  {
   return(this._msg );
  }
  public uint Sequence
  {
   set
   {
    this._seq =value;
   }
   get
   {
    return(this._seq );
   }
  }
 }
 
 public class WaitingQueueItemEventArgs:EventArgs
 {
  private uint _seq;
  private object _q;
 
  public WaitingQueueItemEventArgs(uint seq)
  {
   this._seq =seq;
  }
 
  public WaitingQueueItemEventArgs(object q)
  {
   this._q =q;
  }
 
  public uint Sequence
  {
   set
   {
    this._seq =value;
   }
   get
   {
    return(this._seq );
   }
  }
 
  public object getQueueItem()
  {
   return(this._q );
  }
 }

 public class ClientQueueStateArgs  //当CMPP client的服务停止时候,队列的状态参数
 {
  private SortedList _waiting;
  private SortedList _out;

  public ClientQueueStateArgs(SortedList outQueue,SortedList inQueue)
  {
   this._waiting =inQueue;
   this._out =outQueue;
  }

  public SortedList WaitingQueue
  {
   get
   {
    return(this._waiting );
   }
   set
   {
    this._waiting =value;
   }
  }

  public SortedList OutQueue
  {
   get
   {
    return(this._out );
   }
   set
   {
    this._out =value;
   }
  }
 }

 public class StateObject
 {
  public Socket workSocket = null;              // Client socket.
  public const int BufferSize = 1024;            // Size of receive buffer.
  public byte[] buffer = new byte[BufferSize];  // Receive buffer.
  public byte[] result_buf=null;     //接收最终的结果缓冲区  
  public int _msglength=0;      //接收到多少个字节数据
 }


 
 public enum SMSDBQueue_Status  :int
 {
  NEW=0,   //新消息,等待发送
  SENDED=1,  //正在发送,等待回应
  RESP=2,   //送达SMSC,得到msgid
  DELIVRD=3,  //得到报告,状态ok
  EXPIRED=4,  //过期
  DELETED=5,  //已经删除此消息 UNDELIV
  ACCEPTD=6,  // ACCEPTD 状态 未送达 ACCEPTED为中间状态,网关若从短信中心收到后应丢弃,不做任何操作
  UNDELIV=7,  //未送达
  UNKNOWN=8,  //未知
  REJECTD=9   //被弹回
 }

 public class SMSDBQueue
 {
  private uint _sequence=0;      //对应的cmppclient的序列号
  private int _smsdbID=0;       //对应的数据库的发送自动增长ID
  private int _cmpp_msgType;      //cmpp协议的定义的消息类型
  private object _cmpp_msg_object;    //cmpp消息对象,备检索
  private int _currentStatus;      //当前消息体状态
  private DateTime _inQueueTime=DateTime.Now;  //消息产生设定值
  private UInt64 _msgid;       //消息返回的SMSC给出的id遍号

  public uint Sequence
  {
   get
   {
    return(this._sequence );
   }
   set
   {
    this._sequence =value;
   }
  }

  public int SMSDBID
  {
   get
   {
    return(this._smsdbID);
   }
   set
   {
    this._smsdbID =value;
   }
  }

  public int CurrentStatus
  {
   get
   {
    return(this._currentStatus );
   }
   set
   {
    this._currentStatus =value;
   }
  }

  public int CMPPMsgType
  {
   get
   {
    return(this._cmpp_msgType );
   }
   set
   {
    this._cmpp_msgType =value;
   }
  }

  public DateTime InQueueTime
  {
   get
   {
    return(this._inQueueTime );
   }
   set
   {
    this._inQueueTime =value;
   }
  }

  public object MsgObject
  {
   get
   {
    return(this._cmpp_msg_object );
   }
   set
   {
    this._cmpp_msg_object =value;
   }
  }       

  public UInt64 UIMsgID
  {
   get
   {
    return(this._msgid );
   }
   set
   {
    this._msgid =value;
   }
  }

  public string MsgID
  {
   get
   {
    return(this._msgid.ToString ());
   }
   set
   {
    this._msgid =Convert.ToUInt64(value);
   }
  }
 }
 //*************工具类结束***********************************


 //********************接口类,用于连接对外的短信存储系统**********************
 public interface  ISMSStore   //定义一个存储接口
 {
  SMSRec[] getSMSsFromStore();     //从外部存储中获取消息 
  void updateStoreObjec(int storeObjectID,string state); //更新id代表的对象状态,用于监测状态报告
  void updateSMSCMsgID(int storeObjectID,UInt64 msgid);
  bool addSMS2Store(SMSRec sms);       //向store中存储短消息
  string getFeeCode(string svccode);      //根据svccode返回消息的收费,根据移动参数进行设定  
 }

 public class SMSRec     //SMS载数据库中的表达
 {
  private int _RecID;    
  private string _feeUser;  //计费用户
  private int _smsType=0;   //短信类型 0 普通文字短信 1 闪烁短信 2 查询命令短信 3 包月短信
  private string _svccode;  //服务代码
  private string _msg;   //消息
  private string _state;   //消息状态
  private string _feecode;
  private string _spnum;
  private string _toUser;
       
  public SMSRec(int recid,string feeuser,string feecode,string svccode,string msg,string spnum)
  {
   this._RecID =recid;
   this._feeUser  =feeuser;
   this._toUser =feeuser;
   this._svccode =svccode;
   this._msg =msg;
   this._spnum =spnum;
  }

  public SMSRec(int recid,string feeuser,string touser,string feecode,string svccode,string msg,string spnum)
  {
   this._RecID =recid;
   this._feeUser  =feeuser;
   this._toUser =touser;
   this._svccode =svccode;
   this._msg =msg;
   this._spnum  =spnum;
  }
  
  public string SvcCode
  {
   get
   {
    return(this._svccode );
   }
   set
   {
    this._svccode =value;
   }
  }

  public string FeeCode
  {
   get
   {
    return(this._feecode );
   }
   set
   {
    this._feecode =value;
   }
  }

  public string FeeUser
  {
   get
   {
    return(this._feeUser );
   }
   set
   {
    this._feeUser =value;
   }
  }

  private string ToUser
  {
   get
   {
    return(this._toUser);
   }
   set
   {
    this._toUser=value;
   }
  }

  public string SPNum
  {
   get
   {
    return(this._spnum );
   }
   set
   {
    this._spnum =value;
   }
  }

  public string Message
  {
   get
   {
    return(this._msg );
   }
   set
   {
    this._msg =value;
   }
  }


 }
 //****************************** 接口类结束 *********************************

 //*************************定义 处理数据库接口的SMS系统类,该类对外提供CMPP处理功能***********
 //**功能,实现队列监测,处理失败消息、成功消息,处理定时存储更新等抽象功能的组织,将CMPPClient包装提供

 public class SMSSystem
 {
  private ISMSStore dbcls=null;
  private CMPPClient client=null;
  private string pwd;
  private string systemid;
  private string spnum;

  public void setISMSStoreInterface(ISMSStore ismsstore)
  {
   dbcls=ismsstore;
  }

  public SMSSystem(string systemid,string spnum,string password,string cmppserverip,int cmppport)
  {
   client=new CMPPClient();
   client.Init(cmppserverip,cmppport);
   this.spnum =spnum;
   this.systemid =systemid;
   this.pwd =password;
  }

 }


 //********************************处理SMS系统类结束


 namespace MSG //消息类定义
 {
  //*************枚举类型开始***********************************
  public enum CMPP_COMMAND_ID:uint
  {
   CMPP_CONNECT  =1,
   CMPP_CONNECT_RESP =0×80000001,
   CMPP_TERMINATE  =0×00000002,  // 终止连接
   CMPP_TERMINATE_RESP =0×80000002,  // 终止连接应答
   CMPP_SUBMIT   =0×00000004 ,   //提交短信
   CMPP_SUBMIT_RESP =0×80000004,   // 提交短信应答
   CMPP_DELIVER  =0×00000005 ,   //短信下发
   CMPP_DELIVER_RESP =0×80000005,   // 下发短信应答
   CMPP_QUERY   =0×00000006 , //发送短信状态查询
   CMPP_QUERY_RESP  =0×80000006, // 发送短信状态查询应答
   CMPP_CANCEL   =0×00000007, // 删除短信
   CMPP_CANCEL_RESP =0×80000007, // 删除短信应答
   CMPP_ACTIVE_TEST =0×00000008 , //激活测试
   CMPP_ACTIVE_TEST_RESP=0×80000008 // 激活测试应答
  } 
  public enum FeeUserType
  {
   FEE_TERMINAL_ID =0,    //
   FEE_SOURCE_ID =1,
   FEE_SP   =2,
   FEE_NULL  =3
  } 
  public enum Msg_Format
  {
   ASCII  =0,
   WRITECARD =1,
   BINARY  =2,
   UCS2  =8,
   GB2312  =15
  }
  public enum SUBMIT_RESULT
  {
   SUCC    =0,
   MSG_STRUCTURE_ERR =1,
   COMMANID_ERR  =2,
   MSG_SEQUENCE_ERR =3,
   MSG_LENGTH_ERR  =4,
   FEE_CODE_ERR  =5,
   OUT_OF_MSG_LEN_ERR =6,
   SVC_CODE_ERR  =7,
   FLUX_ERR   =8,
   OTHER_ERR   =9
  }
  //*************枚举类型结束***********************************
 
  //*************结构定义开始***********************************
  public struct FeeType
  {
   public static readonly string FEE_TERMINAL_FREE  =”01″;
   public static readonly string FEE_TERMINAL_PERITEM =”02″;
   public static readonly string FEE_TERMINAL_MONTH  =”03″;
   public static readonly string FEE_TERMINAL_TOP  =”04″;
   public static readonly string FEE_TERMINAL_SP  =”05″;
  }
 
  public struct DELIVER_STATE
  {
   public static readonly string DELIVERED  =”DELIVRD”;
   public static readonly string EXPIRED  =”EXPIRED”;
   public static readonly string DELETED  =”DELETED”;
   public static readonly string UNDELIVERABLE =”UNDELIV”;
   public static readonly string ACCEPTED  =”ACCEPTD”;
   public static readonly string UNKNOWN  =”UNKNOWN”;
   public static readonly string REJECTED  =”REJECTD”;
  }
  //*************结构类型结束***********************************
 
  //****************消息类**************************************
  public class CMPP_MSG_Header  //消息头
  { 
   private byte[] initValue=new byte[MSG.CMPP_MSG_Header.HeaderLength];
 
   public CMPP_MSG_Header(CMPP_COMMAND_ID Command_ID) //发送前
   {
    BIConvert.Int2Bytes((uint)Command_ID).CopyTo(initValue,4);
   }
 
   public CMPP_MSG_Header(byte[] bs) //根据受到的字节进行构造 字节序列
   {
    int l=MSG.CMPP_MSG_Header.HeaderLength ;
    for(int i=0;i<l;i++)
    {
     initValue[i]=bs[i];
    }
   }
   public CMPP_MSG_Header(byte[] bs,int baseIndex) //根据受到的字节进行构造 字节序列
   {
    int l=MSG.CMPP_MSG_Header.HeaderLength ;
    for(int i=0;i<l;i++)
    {
     initValue[i]=bs[baseIndex+i];
    }
   }
 
  
 
   public uint MSGLength  //获取此消息头代表的消息的整个长度
   {
    get
    {
     return(BIConvert.Bytes2UInt(initValue,0));
    }
    set
    {
     byte[] t=BIConvert.Int2Bytes(value);
     for(int i=0;i<4;i++)
     {
      initValue[i]=t[i];
     }
    }
   }
 
   public uint Command_ID
   {
    get
    {
     return(BIConvert.Bytes2UInt(initValue,4));
    }
    set
    {
     byte[] t=BIConvert.Int2Bytes(value);
     for(int i=0;i<4;i++)
     {
      initValue[i+4]=t[i];
     }
    }
   }
 
   public uint SequenceId
   {
    get
    {    
     return(BIConvert.Bytes2UInt(initValue,8));
    }
    set
    {
     byte[] t=BIConvert.Int2Bytes(value);
     for(int i=0;i<4;i++)
     {
      initValue[i+4+4]=t[i];
     }
    }
   }
 
   public byte[] toBytes()
   {
    return( initValue ); //将字段转化为字节
   }
 
   public void fromBytes(byte[] bs)
   {
    for(int i=0;i<MSG.CMPP_MSG_Header.HeaderLength;i++)
    {
     initValue[i]=bs[i];
    }    
   }
 
   public static int HeaderLength
   {
    get
    {
     return(4+4+4);
    }
   }
  }
  
  public class CMPP_MSG_CONNECT
  {
   CMPP_MSG_Header header;
   byte[] initValue;
   byte[] body;
   int baseIndex=MSG.CMPP_MSG_Header.HeaderLength ; //消息的起始
   byte ver=0×20;
   byte[] AuthenticatorSource=new Byte[16];   //发送的验证信息
   string _SystemID=”000000″;
   string _Password=”00000000″;
   string _timestamp=”0000000000″;
 
   public CMPP_MSG_CONNECT(uint sequence)
   {
    header=new MSG.CMPP_MSG_Header(MSG.CMPP_COMMAND_ID.CMPP_CONNECT);
    header.SequenceId =sequence;
    header.MSGLength =(uint)(this.BodyLength +MSG.CMPP_MSG_Header.HeaderLength); 
    body=new byte[this.BodyLength];
   }
 
   public CMPP_MSG_CONNECT(byte[] bs)
   { 
    initValue=new byte[bs.Length];
    bs.CopyTo(initValue,0); //进行初始化行为  
    byte[] temp=new byte[ MSG.CMPP_MSG_Header.HeaderLength ];
    for(int i=0;i<temp.Length ;i++)
    {
     temp[i]=bs[i];
    }   
    byte[] body=new Byte[bs.Length - MSG.CMPP_MSG_Header.HeaderLength ];
    for(int i=0;i<body.Length ;i++)
    {
     body[i]=bs[MSG.CMPP_MSG_Header.HeaderLength+i]; //将消息的字节存储
    }   
    header=new MSG.CMPP_MSG_Header(temp);  //构造 消息头
    header.MSGLength = (uint)(this.BodyLength +MSG.CMPP_MSG_Header.HeaderLength );
    header.Command_ID =(uint)MSG.CMPP_COMMAND_ID.CMPP_CONNECT ;
   }
   public int BodyLength
   {
    get
    {
     return(6+16+4+1);
    }
   }
 
   public string SourceAdd
   {    
    set
    {
     _SystemID=value;
     byte[] t=Encoding.ASCII.GetBytes(_SystemID); //转换为字节数组
     t.CopyTo(body,0);      
    }
   }
 
  
   public string Password
   {
    set
    {
     _Password=value;
    }
   }
 
   public string Version
   {
    set
    {
     ver=Convert.ToByte (“0x” + value,16);
    }
   }
 
       
   private static string  getTimestamp() //返回一个时间戳 4 字节
   {
    DateTime msgtime=DateTime.Now;
    string u=msgtime.Month.ToString().PadLeft(2,’0′); 
    u=u+msgtime.Day.ToString().PadLeft(2,’0′); 
    u=u+msgtime.Hour.ToString().PadLeft(2,’0′); 
    u=u+msgtime.Minute.ToString().PadLeft(2,’0′);  
    u=u+msgtime.Second.ToString().PadLeft(2,’0′); 
    return(u);
   } 
   private byte[] getMd5Code()
   {
    MD5 md5= new MD5CryptoServiceProvider(); //创建MD5类别
    byte[] buf=new byte[6+9+_Password.Length+10] ;   
    byte[] s_a=Encoding.ASCII.GetBytes(_SystemID); //Source_ADD 就是企业代码
    byte[] s_0={0,0,0,0,0,0,0,0,0};     //9字节的0,此处当作右补0
    byte[] s_p=Encoding.ASCII.GetBytes(_Password); //密码
    this._timestamp =getTimestamp();    //取得认证码时赋值字符串
    byte[] s_t=Encoding.ASCII.GetBytes(_timestamp); //10位的字符串字节数组
    s_a.CopyTo(buf,0);    //base 0
    s_0.CopyTo(buf,6);    //base 6
    s_p.CopyTo(buf,6+9);   //base 6+9
    s_t.CopyTo(buf,6+9+_Password.Length);  //base 6+9+password.length   
 
    return(md5.ComputeHash(buf,0,buf.Length));
   }   
   private byte[] getSourceAdd()
   {
    return( Encoding.ASCII.GetBytes(this._SystemID ));
   }
   public byte[] ToBytes()   //返回当前对象的字节数组印象
   {
    byte[] reVal=new Byte[MSG.CMPP_MSG_Header.HeaderLength+this.BodyLength];
    header.toBytes().CopyTo(reVal,0);       //消息头
    getSourceAdd().CopyTo(reVal,MSG.CMPP_MSG_Header.HeaderLength);  //源地址 企业代码
    getMd5Code().CopyTo(reVal,MSG.CMPP_MSG_Header.HeaderLength+6);   //认证md5
    reVal[MSG.CMPP_MSG_Header.HeaderLength+6+16]=this.ver;    //版本字节
    BIConvert.Int2Bytes(Convert.ToUInt32(this._timestamp)).CopyTo(reVal, MSG.CMPP_MSG_Header.HeaderLength+6+16+1);  
    return(reVal);
   }
  }
 
  public class CMPP_MSG_CONNECT_RESP
  {
   CMPP_MSG_Header header;
   byte Status;
   byte[] AuthenticatorISMG;
   byte _Version;   
 
   public CMPP_MSG_CONNECT_RESP(byte[] bs)
   {
    byte[] temp_head=new Byte[MSG.CMPP_MSG_Header.HeaderLength ];
    int index=0;
    for(int i=0;i<MSG.CMPP_MSG_Header.HeaderLength ;i++)
    {
     temp_head[i]=bs[index++];
    }        
    header=new MSG.CMPP_MSG_Header(temp_head);   
    Status=bs[index++];      //状态字节
    AuthenticatorISMG=new byte[16];   //回应摘要
    for(int i=0;i<AuthenticatorISMG.Length ;i++)
    {
     AuthenticatorISMG[i]=bs[index++];
    }
    _Version=bs[index++];   
   }
  
   public bool isOk
   {
    get
    {
     return(true);
    }
   }
 
   public string Ver
   {
    get
    {
     return(Convert.ToString(this._Version,16));
    }
   }
 
   public string ISMGREturnAuthCode
   {
    get
    {
     return(Encoding.ASCII.GetString(AuthenticatorISMG));   
    }
   }
 
   public uint Command_ID
   {
    get
    {
     return(header.Command_ID);
    }
    set
    {
     header.Command_ID =value;
    }
   }
 
   public uint Sequence
   {
    get
    {
     return(header.SequenceId);
    }
   }
  }
 
 
  public class CMPP_MSG_TERMINATE
  {  
   CMPP_MSG_Header header;
   public CMPP_MSG_TERMINATE(uint sequence)
   {
    header=new MSG.CMPP_MSG_Header(CMPP.YOURCOMPANY.MSG.CMPP_COMMAND_ID.CMPP_TERMINATE); 
    header.MSGLength  =(uint)MSG.CMPP_MSG_Header.HeaderLength ;
    header.SequenceId =sequence;
   }
   public CMPP_MSG_TERMINATE(byte[] bs)
   {
    header=new MSG.CMPP_MSG_Header(bs);
   }
 
   public byte[] toBytes()
   {
    return(header.toBytes());
   }
 
   public uint Sequence
   {
    get
    {
     return(header.SequenceId );
    }
   }
  }
 
  public class CMPP_MSG_TERMINATE_RESP
  {  
   CMPP_MSG_Header header;
   public CMPP_MSG_TERMINATE_RESP(byte[] bs)
   {
    header=new CMPP_MSG_Header(bs);
   }
   public CMPP_MSG_TERMINATE_RESP(uint sequence)
   {
    header=new MSG.CMPP_MSG_Header(MSG.CMPP_COMMAND_ID.CMPP_TERMINATE_RESP);
    header.MSGLength=(uint)MSG.CMPP_MSG_Header.HeaderLength ;
    header.SequenceId =sequence;
   }
 
   public byte[] toBytes()
   {
    return(header.toBytes());
   }
   public uint Command_ID
   {
    get
    {
     return(header.Command_ID);
    }
    set
    {
     header.Command_ID =value;
    }
   }
 
   public uint Sequence
   {
    get
    {
     return(header.SequenceId);
    }
   }
  }
  
  public class CMPP_MSG_SUBMIT
  {
   CMPP_MSG_Header header;
   int  _isReportOrSMC=1;   //是否需要状态报告
   int _msgTotal =1;    //相同消息的条数
   int _msgNumber =1;    //
   int _msgLevel =0;    //消息级别,却胜0
   string _svcCode=”"; //业务类型
   int _feeUserType=0;    //计费用户类型字段0:对目的终端MSISDN计费;1:对源终端MSISDN计费;2:对SP计费;3:表示本字段无效,对谁计费参见Fee_terminal_Id字段
   string _feeTerminalId=”";  //被计费终端
   int _tpPid=0;
   int _tpUDHI=0;
   uint _msgFmt=0;  //消息格式
   string _msgsrc=”";    //消息来源 即spid
   string _feeType=MSG.FeeType.FEE_TERMINAL_PERITEM  ;  //
   string _feeCode=”";    //资费
   string _valIdTime=”";   //存活期
   string _atTime=”";    //调度时间
   string _srcId=”";    //源号码,就是在手机上显示的号码
   int  _destUsrNum=0;   //接受消息的手机数
   string[] _destTerminalIds=new string[100]; //至多100个号码
   int _msgLengt=(int)MSG.Msg_Format.GB2312;
   string _MsgContent=”";
   UInt64 _MsgID;    //返回的消息ID
 

   public CMPP_MSG_SUBMIT(uint sequence)
   {
    header=new MSG.CMPP_MSG_Header(CMPP.YOURCOMPANY.MSG.CMPP_COMMAND_ID.CMPP_SUBMIT ); 
    header.SequenceId =sequence;
   } 
           
   //属性////////////////////////////////////////////////////
   public string SMS_Content
   {
    set
    {
     this._MsgContent=value;
     byte[] t = Encoding.ASCII.GetBytes(value)  ;
     this._msgLengt=t.Length;
    }
   }
 
   public int SMS_Delivery_Type  //是否要求返回状态确认报告:0:不需要1:需要2:产生SMC话单 (该类型短信仅供网关计费使用,不发送给目的终端)
   {
    set
    {
     _isReportOrSMC=value; 
    }
   }
 
   public int Msg_Level
   {
    set
    {
     this._msgLevel=value;
    }
   }
  
   public string Svc_Code
   {
    set
    {
     this._svcCode=value;
    }
   }
 
   public int FeeUserType
   {
    set
    {
     this._feeUserType=value;
    }
   }
 
   public string FeeTerminalId
   {
    set
    {
     this._feeTerminalId=value;
    }
   }
 
   public int UDHI
   {
    set
    {
     this._tpUDHI=value;
    }
   }
 
   public uint MSGFormat
   {
    set
    {
     this._msgFmt=value;
    }
   }
 
   public string SPID
   {
    set
    {
     this._msgsrc=value;
    }
   }
 
   public string SrcID   //可以此处确定长号码
   {
    set
    {
     this._srcId =value;
    }
   }
 
   public string FeeType
   {
    set
    {
     this._feeType =value.PadLeft(2,’0′);
    }
   }
 
   public string FeeCode
   {
    set
    {
     this._feeCode =value;
    }
   }
 
   public string ValIdTime
   {
    set
    {
     this._valIdTime =value;
    }
   }
 
   public string AtTime
   {
    set
    {
     this._atTime =value;
    }
   }
 
   public UInt64 MsgID
   {
    set
    {
     this._MsgID =value;
    }
    get
    {
     return(this._MsgID);
    }
   }     
   //属性结束//////////////////////////////////////////////
 
   public void addTerminalID(string id)
   {
    if(this._destUsrNum <100)
    {    
     this._destTerminalIds[this._destUsrNum++]=id; 
    }
   }
 
   public byte[] toBytes() //返回字节数印象
   {
    byte[] submitData=new byte[400];
    int index=MSG.CMPP_MSG_Header.HeaderLength ;     //当前包的填充指针
   {//进入填充包的过程
    index=index+8;      //msgid跳过
    submitData[index++]=(byte)this._msgTotal;
    submitData[index++]=(byte)this._msgNumber;
    submitData[index++]=(byte)this._isReportOrSMC;
    submitData[index++]=(byte)this._msgLevel;
    byte[] svccode=Encoding.ASCII.GetBytes(this._svcCode);
    svccode.CopyTo(submitData,index);   //拷贝到目标
    index=index+10;   //index增加
    submitData[index++]=(byte)this._feeUserType;
    byte[] feetid=Encoding.ASCII.GetBytes(this._feeTerminalId);
    feetid.CopyTo(submitData,index);
    index=index+21;
    submitData[index++]=(byte)this._tpPid;
    submitData[index++]=(byte)this._tpUDHI;
    submitData[index++]=(byte)this._msgFmt;
    byte[] spid=Encoding.ASCII.GetBytes(this._msgsrc);
    spid.CopyTo(submitData,index);
    index=index+6;
    byte[] feetype=Encoding.ASCII.GetBytes(this._feeType);
    feetype.CopyTo(submitData,index);
    index=index+2;
    byte[] feecode=Encoding.ASCII.GetBytes(this._feeCode);
    feecode.CopyTo(submitData,index);
    index=index+6;
    //byte[] validtime=Encoding.ASCII.GetBytes(this._valIdTime);
    //validtime.CopyTo (submitData,index);
    index=index+17;
    //byte[] attime=Encoding.ASCII.GetBytes(this._valIdTime);
    //attime.CopyTo (submitData,index);
    index=index+17;
    byte[] srcid=Encoding.ASCII.GetBytes(this._srcId);
    srcid.CopyTo(submitData,index);
    index=index+21;
    submitData[index++]=(byte)this._destUsrNum;
    for(int i=0;i<this._destUsrNum;i++)
    {
     byte[] temp=Encoding.ASCII.GetBytes(this._destTerminalIds[i]);
     temp.CopyTo(submitData,index);
     index=index+21;
    }
    submitData[index++]=(byte)this._msgLengt;   
    byte[] msg=null;
    switch (this._msgFmt)
    {//根据编码类型确定转换字节
     case (uint)MSG.Msg_Format.ASCII :
      msg= Encoding.ASCII.GetBytes(this._MsgContent );
      msg.CopyTo(submitData,index); 
      submitData[index-1]=(byte)msg.Length;   //重新设定长度
      index=index+ msg.Length;      
      break;
 
     case (uint)MSG.Msg_Format.BINARY :
      msg= Encoding.ASCII.GetBytes(this._MsgContent );
      msg.CopyTo(submitData,index);
      submitData[index-1]=(byte)msg.Length;   //重新设定长度
      index=index+ msg.Length;
      break;
 
     case (uint)MSG.Msg_Format.GB2312 : 
      msg=Encoding.Default.GetBytes(this._MsgContent );
      msg.CopyTo(submitData,index);
      submitData[index-1]=(byte)msg.Length;   //重新设定长度
      index=index+msg.Length;       
      break;
 
     case (uint)MSG.Msg_Format.UCS2  :
      msg= Encoding.BigEndianUnicode.GetBytes(this._MsgContent );
      msg.CopyTo(submitData,index);
      submitData[index-1]=(byte)msg.Length;   //重新设定长度
      index=index+msg.Length;
      break;
 
     case (uint)MSG.Msg_Format.WRITECARD :   //写卡操作
      msg= Encoding.ASCII.GetBytes(this._MsgContent );
      msg.CopyTo(submitData,index);
      submitData[index-1]=(byte)msg.Length;   //重新设定长度
      index=index+msg.Length;
      break;
     default:
      msg= Encoding.ASCII.GetBytes(this._MsgContent );
      msg.CopyTo(submitData,index);
      submitData[index-1]=(byte)msg.Length;   //重新设定长度
      index=index+msg.Length;
      break;
    }
    index=index+8;   //8个保留字节
   }   
    header.MSGLength=(uint)index;//根据index的长度决定传输数据字节长度
    byte[] reVal=new byte[index];       
    header.toBytes().CopyTo(reVal,0);    
    for(int i=MSG.CMPP_MSG_Header.HeaderLength ;i<reVal.Length;i++)
    {
     reVal[i]=submitData[i];
    }
    return(reVal);
   }
  }
   
  public class CMPP_MSG_SUBMIT_RESP
  {
   CMPP_MSG_Header header;
   byte[] Msg_Id=new byte[8];  
   byte[] initValue;
 
   public CMPP_MSG_SUBMIT_RESP(byte[] bs)
   {
    initValue=new byte[bs.Length];
    for(int i=0;i<bs.Length ;i++)
    {
     initValue[i]=bs[i];
    }
    init();
   }
 
   private void init()
   {    
    int index=0;
    byte[] temp=new byte[MSG.CMPP_MSG_Header.HeaderLength];    
    for ( int i=0;i<MSG.CMPP_MSG_Header.HeaderLength;i++)
    {
     temp[i]=initValue[i];
     index=i;
    }
    index +=1 ;//指到正确位置
    header=new MSG.CMPP_MSG_Header(temp);
    for(int i=0;i<8;i++)
    {
     Msg_Id[i]=initValue[index+i];     
    }
    BIConvert.DumpBytes(Msg_Id,”C:\\Submit_resp_MsgID.txt”);
   }
 
   public UInt64 Msg_ID
   {
    get
    {

     UInt64 t= BitConverter.ToUInt64(this.Msg_Id,0) ;     
     return(t) ; 
    }
   }

   public string MsgID
   {
    get
    {
     return BitConverter.ToUInt64(this.Msg_Id,0).ToString(); 
    }
   }
  
   public uint Command_ID
   {
    get
    {
     return(header.Command_ID);
    }
    set
    {
     header.Command_ID =value;
    }
   }
 
   public uint Sequence
   {
    get
    {
     return(header.SequenceId);
    }
   }
 
   public bool isOK
   {
    get
    {
     byte b=initValue[MSG.CMPP_MSG_Header.HeaderLength+8];
     if((int)b==0)
     {
      return(true);
     }
     else
     {
      return(false);
     }
    }
   }
  }
 
  public class CMPP_MSG_QUERY
  {
   CMPP_MSG_Header header;
   string _time;
   int _queryType=0;
   string _queryCode; 
   
   public string Time
   {
    set
    {
     _time=value;
    }
   }
 
   public int Query_Type
   {
    set
    {
     _queryType=value;
    }
   }
 
   public string Query_Code
   {
    set
    {
     _queryCode=value;
    }
   }
 
   public CMPP_MSG_QUERY(uint sequence)
   {
    header=new MSG.CMPP_MSG_Header(MSG.CMPP_COMMAND_ID.CMPP_QUERY);
    header.SequenceId =sequence;
   }
 
   public byte[]  toBytes()
   {
    byte[] reVal=new byte[MSG.CMPP_MSG_Header.HeaderLength + 8+1+10+8];
    int index=0;
    header.toBytes().CopyTo(reVal,index); 
    index=index+MSG.CMPP_MSG_Header.HeaderLength ;
    Encoding.ASCII.GetBytes(this._time).CopyTo(reVal,index);//8 Octet String 时间YYYYMMDD(精确至日)
    index=index+8;
    reVal[index++]=Convert.ToByte(this._queryType);
    Encoding.ASCII.GetBytes(this._queryCode).CopyTo(reVal,index);
    return(reVal);
   }
  }
  
  public class CMPP_MSG_QUERY_RESP
  {
   CMPP_MSG_Header header;
   string _time;
   byte _queryType;
   string _queryCode;
   System.UInt32 _MT_TLMsg;
   System.UInt32 _MT_Tlusr;
   System.UInt32 _MT_Scs;
   System.UInt32 _MT_WT;
   System.UInt32 _MT_FL;
   System.UInt32 _MO_Scs;
   System.UInt32 _MO_WT;
   System.UInt32 _MO_FL;
 
   public CMPP_MSG_QUERY_RESP(byte[] bs)
   {
    header=new MSG.CMPP_MSG_Header(bs);
    int index=MSG.CMPP_MSG_Header.HeaderLength ;
    _time=BitConverter.ToString(bs,index,8);
    index=index+8;
    this._queryType =bs[index++];
    this._queryCode=BitConverter.ToString(bs,index,10);
    index=index+10;
    this._MT_TLMsg=BIConvert.Bytes2UInt(bs,index);
    index=index+4;
    this._MT_Tlusr =BIConvert.Bytes2UInt(bs,index);
    index=index+4;
    this._MT_Scs  =BIConvert.Bytes2UInt(bs,index);
    index=index+4;
    this._MT_WT  =BIConvert.Bytes2UInt(bs,index);
    index=index+4;
    this._MT_FL  =BIConvert.Bytes2UInt(bs,index);
    index=index+4;
    this._MO_Scs  =BIConvert.Bytes2UInt(bs,index);
    index=index+4;
    this._MO_WT  =BIConvert.Bytes2UInt(bs,index);
    index=index+4;
    this._MO_FL  =BIConvert.Bytes2UInt(bs,index);    
   }
 
   public string Time
   {
    get
    {
     return(this._time);
    }
   }
 
   public int Qery_Type
   {
    get
    {
     return(this._queryType);
    }
   }
 
   public string QueryCode
   {
    get
    {
     return(this._queryCode);
    }
   }
 
   public uint Sequence
   {
    get
    {
     return(header.SequenceId);
    }
   }
 
   public uint  MT_TLMsg
   {
    get
    {
     return(this._MT_TLMsg);
    }
   }
 
   public uint MT_TLUsr
   {
    get
    {
     return(this._MT_Tlusr);
    }
   }
 
   public uint MT_Src
   {
    get
    {
     return(this._MT_Scs);
    }
   }
 
   public uint MT_WT
   {
    get
    {
     return(this._MT_WT);
    }
   }
 
   public uint MT_FL
   {
    get
    {
     return(this._MT_FL);
    }
   }
 
   public uint MO_Src
   {
    get
    {
     return(this._MO_Scs);
    }
   }
 
   public uint MO_WT
   {
    get
    {
     return(this._MO_WT);
    }
   }
 
   public uint MO_FL
   {
    get
    {
     return(this._MO_FL);
    }
   }
 
   
  }
 
  public class CMPP_MSG_DELIVER
  {
   CMPP_MSG_Header header;
   System.UInt64  _msgid;
   string _destid;
   string _svccode;
   int _tpid;
   int _udhi;
   int _msgfmt;
   string  _srctid;
   bool _isReport;
   int _msglength;
   string _msg;
 
   System.UInt64  _reportForMsgid;
   string _reportState;
   string _submitTime;
   string _doneTime;
   string _reportDesttid;
   int _smscSequence;
 
   public CMPP_MSG_DELIVER(byte[] bs)
   {     
    header=new MSG.CMPP_MSG_Header(bs);
    int index=MSG.CMPP_MSG_Header.HeaderLength;   
    this._msgid   =  BitConverter.ToUInt64(bs,index);
    index+=8;
    this._destid = Encoding.ASCII.GetString(bs,index,21);
    index=index+21;
    this._svccode =Encoding.ASCII.GetString(bs,index,10);
    index=index+10;
    this._tpid =(int) bs[index++];
    this._udhi =(int) bs[index++];
    this._msgfmt=(int) bs[index++];
    this._srctid =Encoding.ASCII.GetString(bs,index,21);
    index+=21;
    if(bs[index++]==1)
    {
     this._isReport =true;
    }
    else
    {
     this._isReport =false;
    }
    this._msglength =(int) bs[index++];
    if(! this._isReport )
    {
     switch(this._msgfmt )
     {
      case (int) MSG.Msg_Format.ASCII :
       this._msg = Encoding.ASCII.GetString(bs,index,this._msglength );
       index+=this._msglength ;
       break;
      case (int)MSG.Msg_Format.BINARY :
       this._msg = Encoding.Default.GetString (bs,index,this._msglength );
       index+=this._msglength ;
       break;
 
      case (int)MSG.Msg_Format.GB2312  :
       this._msg = Encoding.Default.GetString(bs,index,this._msglength );
       index+=this._msglength ;
       break;
 
      case (int)MSG.Msg_Format.UCS2 :
       this._msg = Encoding.BigEndianUnicode.GetString(bs,index,this._msglength );
       index+=this._msglength ;
       break;
 
      default:
       break;
     }
    }
    else
    {//状态报告
     this._reportForMsgid = BitConverter.ToUInt64(bs,index);
     index+=8;
     this._reportState   = BitConverter.ToString(bs,index,7);
     index+=7;
     this._submitTime =  BitConverter.ToString(bs,index,10);
     index+=10;
     this._doneTime  =   BitConverter.ToString(bs,index,10);
     index+=10;
     this._reportDesttid  = BitConverter.ToString(bs,index,21);
     index+=21;
     this._smscSequence   =(int) BIConvert.Bytes2UInt(bs,index );
    }
   }
 
   public bool isReport
   {
    get
    {
     return(_isReport);
    }
   }
 
   public string Msg
   {
    get
    {
     return(this._msg );
    }
   }
 
   public string SrcID
   {
    get
    {
     return(this._srctid);
    }
   }
 
   public string SvcCode
   {
    get
    {
     return(this._svccode);
    }
   }
 
   public string DestID
   {
    get
    {
     return(this._destid );
    }
   }
 
   public UInt64 MsgID   //给应用程序提供序号
   {
    get
    {
     return(this._msgid);
    }
   }
 
   public string StateReport
   {
    get
    {
    {
     return(this._reportState);
    }
    }
   }
 
   public UInt64 ReportMsgID
   {
    get
    {
    {
     return(this._reportForMsgid);
    }
    }
   }
 
   public string SubmitTime
   {
    get
    {
    {
     return(this._submitTime);
    }
    }
   }
   public string DoneTime
   {
    get
    {
    {
     return(this._doneTime);
    }
    }
   }
 
   public string ReportbyDestID
   {
    get
    {
    {
     return(this._reportDesttid);
    }
    }
   }
 
   public int SMSCSequence
   {
    get
    {
     return(this._smscSequence);
    }   
   }

   public int ISMGSequence
   {
    get
    {
     return((int)this.header.SequenceId);
    }
   }
 
   public int MsgBytelen
   {
    get
    {
     return(this._msglength);    //返回deliver包的报告正文长度
    }
   }
  }
  
  public class CMPP_MSG_DELIVER_RESP
  {
   CMPP_MSG_Header header;    
   int _result;
   //byte[] _msgidbytes=new byte[8];
   System.UInt64 _msgid;
  
   public CMPP_MSG_DELIVER_RESP(uint sequence)
   {
    header=new MSG.CMPP_MSG_Header(MSG.CMPP_COMMAND_ID.CMPP_DELIVER_RESP );
    header.SequenceId =sequence;
    header.MSGLength =(uint) MSG.CMPP_MSG_Header.HeaderLength +8+1;
   }
 
   public int Result
   {
    set
    {
     this._result = value;
    }
   }
 
   public UInt64  MsgID
   {
    set
    {
     this._msgid =value;
    }
   }
 
   public byte[] toBytes()
   {
    byte[] reVal=new byte[MSG.CMPP_MSG_Header.HeaderLength + 9];
    int index=0;
    header.toBytes().CopyTo(reVal,index); 
    index=index+MSG.CMPP_MSG_Header.HeaderLength ;
    BitConverter.GetBytes(this._msgid).CopyTo(reVal,index);
    index=index+8;
    reVal[index++]=Convert.ToByte(this._result);   
    return(reVal);
   }
      
  }
 
  public class CMPP_MSG_CANCEL
  {
   CMPP_MSG_Header header;
   byte[] Msg_Id=new byte[8];
   string _msgid;
 
   public CMPP_MSG_CANCEL(uint sequence)
   {
    header=new MSG.CMPP_MSG_Header(MSG.CMPP_COMMAND_ID.CMPP_CANCEL);
    header.SequenceId =sequence;
    header.MSGLength =(uint)( MSG.CMPP_MSG_Header.HeaderLength + 8);
   }
 
   public string MsgID
   {
    set
    {
     this._msgid =value;
    }
   }
 
   public byte[] toBytes()
   {
    byte[] reVal=new byte[MSG.CMPP_MSG_Header.HeaderLength + 8];
    int index=0;
    header.toBytes().CopyTo(reVal,index); 
    index=index+MSG.CMPP_MSG_Header.HeaderLength ;
    Encoding.ASCII.GetBytes(this._msgid).CopyTo(reVal,index);     
    return(reVal);
   }
  }
 
  public class CMPP_MSG_CANCEL_RESP
  {
   CMPP_MSG_Header header;
   bool _Suceeid;
 
   public CMPP_MSG_CANCEL_RESP(byte[] bs)
   {
    header=new MSG.CMPP_MSG_Header(bs);
    if(bs[MSG.CMPP_MSG_Header.HeaderLength]==0 )
    {
     this._Suceeid=false;
    }
    else
    {
     this._Suceeid =true;
    }
   }
 
   public bool isSucc
   {
    get
    {
     return(this._Suceeid);
    }
   }    
 
   public uint Sequence
   {
    get
    {
     return(this.header.SequenceId);
    }
    set
    {
     header.SequenceId =value;
    }
   }
  }
  
  public class CMPP_MSG_TEST
  {
   CMPP_MSG_Header header;
    
   public CMPP_MSG_TEST( uint sequence )
   {
    header=new MSG.CMPP_MSG_Header(MSG.CMPP_COMMAND_ID.CMPP_ACTIVE_TEST);
    header.MSGLength =(uint)MSG.CMPP_MSG_Header.HeaderLength ;
    header.SequenceId =sequence;
   }
 
   public CMPP_MSG_TEST(byte[] bs)
   {
    header=new MSG.CMPP_MSG_Header(bs);
   }
 
   public byte[] toBytes()
   {
    return(header.toBytes());
   }
 
   public uint Sequence
   {
    get
    {
     return(header.SequenceId );
    }
   }
  }
    
  public class CMPP_MSG_TEST_RESP
  {
   CMPP_MSG_Header header; 
 
   public CMPP_MSG_TEST_RESP(uint sequence)
   {
    header=new MSG.CMPP_MSG_Header(MSG.CMPP_COMMAND_ID.CMPP_ACTIVE_TEST_RESP);
    header.MSGLength =(uint)(MSG.CMPP_MSG_Header.HeaderLength+1) ;
    header.SequenceId =sequence;
   }
 
   public CMPP_MSG_TEST_RESP(byte[] bs)
   {
    header=new MSG.CMPP_MSG_Header(bs); 
   }
 
   public uint Sequence
   {
    get
    {
     return(header.SequenceId );
    }
   }
 
   public byte[] toBytes()
   {
    byte[] reVal=new byte[MSG.CMPP_MSG_Header.HeaderLength +1 ];
    header.toBytes().CopyTo(reVal,0);
    return(reVal);
   }
 
  } 
 }
   
}

2004年12月16日

1 生成 菜单=〉配置管理器:改为 Debug

2 web.config中 debug = true

3 找到machine.config这个文件,搜索<processModel 然后把里面的userName=”machine改为userName=”SYSTEM“,然后重新启动一次

4 你的asp.net项目–属性-debug–asp.net debug =true

修改以上几项应该可以解决问题。

 VS.NET中有的时候当你建立一个web应用程序时会有这样的提示,解决的办法,除了最笨的方法--重装VS.NET之外,问题出现的原因及解决办法如下:

1.你的Web服务器使用了固定IP:确定你的“Internet信息服务”中使用的是“默认web站点”并且其属性中的IP地址为“(全部未分配)”,而不是你己指定的ip地址。然后在回到VS.NET中重试,或许可以解决。

2.以上方法不能解决问题时,考虑MSDN中的解决办法,如下:

Visual Studio .NET 无法确定在 Web 服务器计算机上运行的是否为 ASP.NET 1.1 版。该错误可能在几种不同情况下发生。请检查是否属于以下情况:

确保 .NET Framework 1.1 版安装在 Web 服务器计算机上。有关详细信息,请参见 Visual Studio .NET 软件要求。

 
如果 ASP.NET 已安装在 Web 服务器计算机上,但仍然遇到此错误,则可能是配置问题。为了纠正有问题的安装或配置,可以使用名为 aspnet_regiis 的 ASP.NET 实用工具。在类似如下所示的路径中可以找到此命令行实用工具:


C:\WINDOWS\Microsoft.NET\Framework\v1.1.nnnn\

其中 nnnn 表示四位内部版本号。在最高版本号下查找。使用 /i 开关运行该实用工具:

aspnet_regiis /i

提示   您可以从命令的正确目录中直接打开该命令窗口。从 Windows 的“开始”菜单,指向“程序”、“Visual Studio .NET 2003”、“Visual Studio .NET 工具”,然后选择“Visual Studio .NET 命令提示”。在窗口打开后,键入 aspnet_regiis /i。

有关安装组件时必须遵循的顺序的信息,请参见 Visual Studio .NET 无法创建应用程序 。未安装所需的组件。

2004年12月04日

    据说是引起很大反响的一个真实的故事,在没看之前,问大家一个问题:如果你是 文章中的“行人”,你会怎么做?如果你是浪迹天涯,会怎么做?你是花乌鸦,又会 怎么做?请说真话。


【一】

    我的生活一直都一帆风顺。从小到大,我都不知道什么是坎坷,也不知道什么是困境。我读过的小学、中学、大学都是数一数二的名牌,甚至连幼儿园也是最好的。大学毕业以后,我顺利地进入一家外资公司,三年后升任公司市场部经理。这份工作使我的生活质量和生活水平都提升到了一个较高的层次。在很多人眼里,我二十多岁,有车有房,出入高档专卖店,从来不为钱操心,这样的生活无疑是优越和令人羡慕的。但是,我一点也不快乐。

    也许是因为自己的道路太平坦,就象一杯寡淡无味的白开水,总是令我感到无限空虚和不满足。我渴望有不同寻常的经历,渴望自己的生活充满激情,更刺激,更有色彩,总而言之,我不愿这样平凡地过完此生。

    我没完没了地在网上猎奇,去各式各样奇怪的网站看些稀奇古怪的东西。我也常去专门讨论探险活动的论坛,在那儿我有一大帮哥们,我们发贴跟贴,互相肉麻地吹捧、不着边际地胡侃海侃,总希望能侃出一两件惊天动地的事来。

    那天看到浪迹天涯发起五一探险活动时,我惊喜又兴奋,几乎是在他的贴子贴出来的同时,我就报了名。     浪迹天涯是老朋友了,我们常常在论坛里讨论诸如野营装备、探险之类的问题,彼此之间也比较熟悉。这次他联系了车子,准备组织一大帮论坛上的哥们在五一节期间徒步穿越一片原始森林无人区。那片原始森林在三百公里外的雪山附近,方圆几百平方公里,他的计划是穿越雪山脚下最狭窄的地带。由于那里的森林是依山而下,所以地形比较复杂,一路上必须要越过很多起伏的小丘、山涧,还得渡过两条小河。无疑,这是一次很有挑战性的穿越。

    浪迹天涯的这个提议在BBS上引起了热烈的响应,可惜由于条件所限,最后确定参 加这次活动只有我、行人和野山雀三个来自同一城市的网友。我们几个在网上都打过交道,因为大家都是一个地方的人,所以也特别谈得来。接下来的几天,我们四个一直孜孜不倦地反复讨论装备、准备工作和各种细节。几个外地网友也参与了我们的讨论,虽然他们无法参加活动,但还是忍住羡慕的口水,热心地为我们出谋划策。

    那时我发现行人绝对是个悲观的人,他几次提到:虽然我们几个在论坛上都是朋友,但毕竟没有见过面,彼此间缺乏必要的了解。而且大家都是热度很高的理论家,说起来一套一套,可是实际经验一点也没有,全是纸上谈兵。他认为这会产生很多不确定因素,甚至存在一定的危险性。

    我的天!不到二百公里,而且还是直进直出,我们甚至可以不带指北针,光看太阳和树叶就能走完,这也算危险?行人立即被淹没在一片唾沫中。

    我是一个酷爱发白日梦的人。多少次,我幻想自己于千军万马中取敌首级;或有绝顶高强的武功,出生入死,除暴安良……然而现实中的我却不得不中规中距,上班得听老板的旨意,下班后也无所事事,只能看书上网,最多也就是去迪厅蹦腾蹦腾。生活是如此的不堪,可现在仅仅背上背包去穿越一片树林,都还要前怕狼后怕虎!我心中十分不满,而且也很看不惯这个无胆的鼠辈,那天我跟贴:我们带上装备,绕着二环路走七天怎么样?SB!

    如果一次探险活动的一切都是太太平平的,那也就失去了它原本的意义。也许会有一些意外,会有危险,这又算得了什么?我们就是为这个去的。在我的设想中,这应该是一次危机四伏的旅程,种种危险和困难将会接踵而至,而我则沉着应对,用自己的智慧和勇气去解决一切问题。为此,我几乎翻烂了约翰.怀斯曼写的《生存手册》,还专门托朋友买了一把价值两千多元的Cold Steel的“小狗腿”砍刀。     我想当时的我已处于个人英雄主义极度膨胀的高度亢奋中。

【二】

    四月二十日,我们几个在一个闹哄哄的小酒吧里碰了头。     出来迎接我的人给我的第一印象是开朗大方、热情洋溢而且精力旺盛,绝对属于团队中的领袖型人物,这与我想象中的浪迹天涯完全吻合,我毫不费力就叫出了他的名字。然而令我尴尬的是,我很自信地把那个健壮挺拔,浑身黝黑的人当做是野山雀,另一个皮肤雪白、全身虚胖,看起来有点胆小怕事的家伙我却一口咬定是行人!于是只好干笑。     那天的碰头会的主要目的是让大家先见个面,彼此熟悉一下,以便行动时不至于太拘束,这也是行人唯一有价值的提议。短暂的拘谨后,我们的碰头会又恢复了网上那种不着边际、天马行空的气氛。两杯啤酒下肚,野山雀的话多了起来,俨然以户外运动专家自居。他夹七夹八讲了很多,似乎很深奥,在他所提及的很多术语中,我唯一记住的只有“真北”和“磁北”,而且到现在我也不知道是什么意思。反正当时我听得云里雾里,为了掩饰自己什么也不懂,我认真听着,不懂的也不问。看看其他人,都是一脸严肃,听得不住地点头,可他们的眼睛里全是一片茫然。说实话,我并没有类似活动的经验,只有满脑子的《生存手册》和健身房里练出来的小块肌肉,我也不相信其他人会好到哪儿去。至于野山雀,他庞大身躯始终令我有些担心,我隐隐觉得搞不好他还会拖累大家。不过他讲得倒是挺精彩,最终使我们相信他还是具备一定素质的,于是大家不再对他那酒桶般的身材耿耿于怀。但我敢打赌:这几天的爬山涉水至少能让他减二十斤膘。

    那次见面是愉快的,我们彼此之间都留下了较好的印象,这是一个良好的开端。后来的日子,我一直处于热切的期待中,而且从来没有象那样看重一个普通的节日,也许我真的有点迫不及待了。

【三】

    五月一日的清晨,汽车轻快地前进着。一路上,浪迹天涯吹着轻松的口哨,不时和我们开着玩笑;野山雀还没有睡够,独自在后排继续做梦;远离城市,抛下了令人窒息的西装领带,我除了兴奋还是兴奋:目光炯炯,不停地把手掰得噼啪作响,象个职业打手;行人则很舒适地坐在车窗旁看外面的风景,偶尔向我投来一束不解的目光……
终于站在了森林的边沿!

望着那茫茫无际的绿色,我的心情为之一畅。浪迹天涯和野山雀掏出指北针和地图开始讨论从哪里进入,我和行人则站在那里欣赏眼前的景致:依山而上的密林,郁郁葱葱,波峦起伏。远处是洁白的雪山,雪山被一片翠绿包围着,高耸入云。呼吸着清新的空气,我们几乎醉了。 刚进森林,我就迫不及待地抽出了我的小狗腿。它沉重、锋利,重心集中在刀的前端,非常利于劈砍。一刀在手,另外三人垂涎欲滴的神情立现,并且马上变得蚂蚁般渺小,同时我心中诸如万夫莫当、力拔山兮气盖世的豪情有如怒涛狂涌,仿佛想借刀锋一泄而出。我想就算当时有一群熊出现,自己也肯定会毫不迟疑地冲上去将它们一一剁碎。

    然而现实对我是绝情寡义的,因为我很快发现林中只有低矮的灌木和杂草,如果执意要当开山先锋,就只能采取类似鸡啄米的姿势去斩断那些轻易就能跨越的草木,这当然于我的英雄形象十分不符,同时也令我感到万分索然。
后面的时间,小狗腿就一直在我背包里。其间偶然遇到有乱枝挡道时,他们就会象发现新大陆一样,毕恭毕敬地把我推到前面,在“酷!一定要酷!”吵嚷声中,依着他们制定的瞳孔收缩、刀闪、藤断三大步骤挥出小狗腿,完事后还得按要求神情落
寞地吹去刀身上粘的绿色汁液!
    这班衰人幸灾乐祸的神情和鬼脸使我发现自己已经沦为一个笑料,不过对他们的捉弄我还是很配合的,即使随便带把BUCK的折刀也比小狗腿实用得多,谁让我愚昧呢?浪迹天涯是一家规模不小的电脑公司的经理,应该算是IT精英吧,他头脑灵活,遇事果断,待人诚恳热情,也善于与人沟通,很具有领袖的气质,其实我们一直都是把他当做领队的。野山雀是个程序员。走了不到一小时我就看出来,他所吹嘘的自己理论经验和实际经验丰富完全是在胡诌,那厮既白又胖还极端缺乏锻炼,走不了一会就得停下来喘气。猛一眼看上去还觉得他老实可怜,可整人出坏点子全有他。哼!以后我再遇到看上去老实巴交的人,一定要加倍提防。

    胆小怕事的行人倒是游历过许多地方,不过都是坐火车坐飞机去的,徒步旅行之类的事却从没干过。他看起来仿佛挺深沉,话虽不多但还算精辟,就是有点杞人忧天。另外,他皮肤很黑,比炭还黑。     在嬉戏般的路途上,我们一直都走得很轻松,遇到复杂的路况,大家互相帮助,提携而上,我们彼此之间的好感也在逐渐增加,我开始喜欢他们,喜欢这个团体,那时我觉得我们能走更远的路,甚至可以走到世界上的任何一个角落。

……

    林中的景色是别致的,森林仍保持着完好的原始风貌,参天的树木枝繁叶茂,即使此刻外面是阳光普照,林子里也是幽暗深邃,雾气氤氲。这里远离城市的喧嚣,潮湿的空气中充满着草木的清香,我喜欢这里,虽然一路平坦,无险可冒,但我仍然认为不虚此行。

    那天傍晚,我们在一个小水潭边宿营。潭水清澈透底,成群结队的小鱼在其中游弋。为了改善生活,我们冲进水中,把住了四个方向,在动用了刀叉棍棒甚至饭盒等武器下,历时一个多小时,终于弄上来几条小鱼。又经过长达半小时的激烈争论,我、行人、浪迹天涯以压倒性优势战胜了想喝汤的野山雀,小得可怜的鱼迅速被送上了简易烤架。

    吃着前所未有的美味,我们海阔天空地闲聊,谈人生、谈理想、谈女人……没有酒,就猜拳喝潭水。我们时而瞪着眼争得面红耳赤,时而又摊成一排大字学远处的狼叫……     后来的几天几乎都是这样度过的,我们成了无话不谈的哥们,称兄道弟。为此大家都很感谢发起这次活动的浪迹天涯,感谢发明互联网的人,惊叹冥冥中的缘分。如果不是天气转坏,让我们不得不呆在各自的帐篷里听雨声,我们或许已经撮土为香,对着明月结拜成兄弟了。
【四】


    从第三天开始,沿途的树木越来越粗,地上的杂草也变得稀疏,我们已经深入了森林腹地。天气变得很糟糕,始终下着蒙蒙细雨,雪山方向的天空更是阴沉得可怕,云层几乎贴在地面上,不时传来隆隆的雷声。林中溪水的流量明显增大,而且十分浑浊,由此我们推断山上肯定在下暴雨。

然而森林色彩却由此而显得更加动人,空气也更加清新,虽然地面变得泥泞湿滑,虽然浑身都被雨水湿透,但我们全不在意,大家士气高昂,甚至唱起了歌。漫步在雨中的原始森林里,与大自然最真实,最彻底地拥抱,这的确是一种独特的体验,它使我感到前所未有的新奇和快乐。
如果说当时有什么缺憾的话,那就是野山雀在几天的跋涉中体力消耗巨大,这直接导致了他惊人的食欲。他很快就吃光了自己的全部口粮,并且开始蚕食我们的库存。浪迹天涯带的食品口味很好,所以他受损最为严重,他开玩笑说最近两天一听到野山雀叫饿就紧张,不光心里紧,甚至连脚趾都紧抓着地!

不过说归说,大家还是很照顾野山雀的,我们三个都自觉地控制了自己的食量,尽量节省出干粮满足他。我想我们几乎是兄弟了,有了困难自然要互相帮助,况且,也没剩太多的路。 下午,我们到达第一条河。由于暴雨的原因,河水浑浊而湍急,在岸边徘徊了一会儿,浪迹天涯自告奋勇去探路。我们屏住呼吸,盯着浪迹天涯拄着棍子在河里摸索。河水大约齐腰深,很急,他几次险些被冲倒,但终于还是保持住平衡,跌跌撞撞地过了河。看着他在对岸得意地挥手,大家一阵欢呼。

我们随即沿着浪迹天涯的路线下了水,行人在最前面,我在中间,野山雀势大力沉,断后。河水冲得我们摇摇晃晃,大家不得不手拉着手,小心翼翼地前进,不一会儿就走到了河心。

【五】


    我曾无数次地想象,自己是如何的英勇,如何从容地化解可能出现的各种危险。然而,真正的危险并不在我预计的时间和地点出现,它潜伏着,观察着,然后猝然出击!它降临的时候,我毫无准备。

    当时我很清楚地听到背后的野山雀叫了一声,接着被他猛然一拉,我本能地使劲攥紧前面的行人,我们三个徒劳地挣扎了几下,最终还是失去平衡,一齐倒在水中,奔腾的激流顿时把我们冲了出去。

    肩上的背包很快就吸饱了水,变得异常沉重。我不停地试图用脚踩河底,却发现下面是空荡荡的。我的水性很好,当时并没有慌张,我一边盘算着从哪里上岸,一边设法除去背包,减轻负重。

    但是,万万没料到身边的野山雀根本不会游泳,突然间他死命地抱住了我!我用尽 全力挣扎,但他的手象钢箍一样,指甲也深深地抠进我的肉里。我还没来得及换口 气,就被野山雀沉重的身体拖下了水面。

    肺部象是在燃烧,非常地难受。可是我无法摆脱野山雀,也无法解开背包,更无法 浮出水面呼吸。这时体内生出一股强大的力量,强迫我打开口腔呼吸。但我不能, 也不敢,我只能苦苦地抵御着这种巨大的痛苦。我知道,最终我会因无法忍受缺氧 而不由自主地呼吸,大量的水会涌进我的肺,那时,就是终点了。死亡的脚步迅速 *近,我感到十分恐惧……

    不知道当时野山雀有没有想到,要是他松开我,那等于是救了他自己。河并不宽, 我肯定能够把他弄上岸。而他却始终象死猪一样紧抱着我,令我不能动弹,这样我 们只有一起完蛋!我感到十分愤怒,而且从来没有象那样憎恨过一个人。

    混沌中,行人出现在身旁,他艰难地弄断我们的背带,甩掉背包,又竭尽全力把我 俩往上一托。虽然只是短短的一秒钟,但已经足够了。我深深吸了一大口久违了的 空气,立刻恢复了镇定。

    狼狈不堪地爬上岸才发现,我们被河水冲出去近百米。我瘫在岸边,看着湍急的河 水,不知道自己在想什么,也不知道应该想什么,脑子里一片空白。

    不远处,行人和浪迹天涯手忙脚乱地拍打着野山雀的背,伺候他吐水。我本应该过 去帮忙或表示关心的,但我没有动弹,那会儿我根本就不愿意看到野山雀的那张胖 脸。

    天空还是那么阴沉,仍旧下着雨,但对于一个劫后余生的人来说,所有的一切都是 那么的不同,一切都是那么的亲切可爱而且真实。

……     浪迹天涯向我走来的时候表情很阴郁,他闷闷地告诉我一个难以接受的事实:这次 遇险我们总共失去了三个人的装备和食品。

    大家一言不发地注视着浪迹天涯慢慢打开自己的背包,里面是单人帐篷、水壶等等 野外用具,而全部食品就只有几块压缩饼干、十来根火腿肠和两大块巧克力。这点 东西还我们不够吃一顿,可是我们还得再走三天!

    五月的天气虽然已经比较暖和,但浑身湿透的我还是禁不住打起了寒战。
  当晚,我们找了一个干燥的地方扎营,为了节约食品,大家都没有吃东西。最受不 了的是野山雀,他不停地喝了很多水,仍然无法压下饥火。他看上去很痛苦,但是 我们也没有其他办法,只能把唯一的帐篷让给他。

【六】

    第五天早上,雨仍然细细密密地下着。

    早晨的空气潮湿,清新,醒来的后第一个深呼吸就让我精神一振。其实我一直是个 很乐观的人,对我来说,每个早晨都是一个好的开端,通常我都是从宽大的床上一 跃而起,心情舒畅地开始一天的生活。

    而那天我的肚子却不失时机地叫了,我顿时想起自己是刚从树洞里钻出来,想起了 目前的处境,于是我迅速萎顿下来。

    我们面临的情况很糟糕,剩下近60公里的路程,其中大部分是山地,起码得走两到 三天。我们体力消耗肯定会很大,而食物却严重短缺。虽然三天时间饿不死人,但 我们肯定会很惨很惨。未来的这几天将如何度过?谁也说不清,望着无尽的绿野, 我第一次生出厌恶的情绪。

  和行人一起来到野山雀帐篷前,浪迹天涯正一脸不耐烦地在催促他起床。浪迹天涯 无精打采地打着呵欠,情绪似乎比较低落,他甚至仰头对着天空自言自语地嘟囔, 好象是抱怨这该死的雨吧?

    野山雀在帐篷里磨蹭了很久,总说没有穿好衣服。行人开玩笑说我们就要冲进帐篷 时,他却连声阻止,声音也变得惊慌失措。

    我心里摹地闪过一个不祥的念头!为了防止野兽来偷吃宝贵的食物,头天晚上浪迹 天涯把我们唯一的背包交给野山雀,让他带进了帐篷,会不会……浪迹天涯好象也同 时意识到了这一点,他猛然上前,拉开了帐篷,却愕然发现野山雀正衣冠整齐地端 坐在帐篷里,神情极其不自然。

    突然间浪迹天涯就象变了一个人,他的表情一下变得十分冷酷,冷酷得令人不寒而 栗。他盯着野山雀,一字一顿地问道:“我们的干粮呢?”

    野山雀开始支支吾吾地东拉西扯,言语含糊不清,可能他自己都不知道说了些什 么,他的眼神也一直涣散游离,根本就不敢和人对视。

    浪迹天涯没有说话,只是站在那里,锐利的目光就象刀一样,*视着他。野山雀胡 乱翻腾着背包,终究什么也没翻出来。他猛地把手上的东西一扔,象个女人一样哭 了起来,“我吃了!呜呜!我真的是饿得受不了了……”

    我心里一沉,紧跟着怒火腾地从我心头窜起,一个想把野山雀撕成碎片的念头越来 越强烈,我试图克制,但毫无用处,终于我抄起一截枯木棍就往前冲,行人却在后 面死死地把我抱住。我俩正扭作一团时,野山雀的惨叫声响起,声音之凄厉,把我 和行人都吓了一跳。

    “猪!你这个只会吃的猪!” 浪迹天涯一边咬牙切齿地骂着,一边对满地打滚的野 山雀拳打脚踢。浪迹天涯长得很壮实,出手也特别狠,野山雀全无招架之力,被打 得不停地嚎叫。

    看到野山雀挨打,我的气消了大半,但是行人仍不敢放开我,只是不断高声叫浪迹 天涯住手。到了后来,连我都觉得野山雀很惨,于是颓然扔掉木棍,让行人去劝劝 浪迹天涯。

    那时我才发现自己并不完全了解我的这些同伴,野山雀根本不考虑别人,毫无节 制,就象头自私、贪吃的猪。平时看起来有几分儒雅的浪迹天涯此刻的表现也同样 令人吃惊,他英俊的脸几乎扭曲,完全象一头暴怒的猛兽,差点连行人一块揍了。 而行人却在关键时刻表现出成熟和理智,他最终镇住了浪迹天涯,让他停了手。

    再次上路时,队伍里已没有了欢笑,大家各怀心事地走着,气氛很沉闷。野山雀跟 在最后,哼哼唧唧地小声哭泣着,没人愿意搭理他。虽然他被打得鼻青脸肿,可他 的肚子是充实的,我想他也该知足了。只可惜那两大块巧克力,巧克力是野营者的 必备品,它能提供很多热量,本来我们是准备省到最后关头才吃的,结果全到野山 雀一人肚子里去了,除了再给他添点肥膘外起不到任何作用。幸亏他的天良还没有 丧尽,给我们剩下了三块压缩饼干,真不知道我们是否应该为此而感谢他。

    地面经雨水多天的浸泡,变得泥泞不堪,石头也格外湿滑,在往日,我们都是互相 拉扯着前进的,然而那天我和浪迹天涯都没有管野山雀,所以他走得相当艰难,不 多会儿他就上气不接下气,喘息声大得惊人。

野山雀再次摔倒在泥泞中,这次他显得筋疲力尽,没能马上爬起来。浪迹天涯看了他一眼,好象有点幸灾乐祸。我犹豫了一下,但报复心还是占了上风,那时我已连续一整天没吃任何东西,胃酸正象刀一样在割着我的胃,腹部的持续疼痛总让我不能克制地想起野山雀那张蠕动着的嘴。我的器量不算小,但也不大,反正不能这么快原谅他,于是我和浪迹天涯继续向前走,没有理他。

走在前面的行人却折了回来,朝野山雀伸出了手。

我不能不佩服他的大度,早上所发生的事情严重地影响了我们的心情,行人对此也不可能无动于衷,而他在那种情况下还是能向野山雀伸出援手,这多少令我隐隐感到有些惭愧。至于野山雀,他今后完全可以去演戏,至少他已经具备了丰富的生活体验,他在一早上流出了惭愧的泪、疼痛的泪和委屈的泪,现在,他的眼眶里又包着感激的泪水了,死胖子!


【七】
 
 我们一直走的是直线,所以不可避免地要越过一些小丘、溪涧。路上,行人一 直在帮助野山雀,他俩都累得够呛。也许正是这样,才使得行人的体力过量消耗, 才导致了意外的再次发生。

  

那天中午,我们从一个小山涧底部往上爬时,行人没能拉住野山雀,让他摔下 去了。开头我们都没在意,因为那并不高,最多只有一米多点,但是几乎是同时, 野山雀哭爹叫娘的惨叫声传来,我们顿时紧张起来,赶紧跳下去帮忙。

  野山雀倒在一片乱石中,嘴里含糊不清地嚎叫着,满脸涕泗纵横。他的右脚扭 向了一个不可思议的角度,明显是腿骨完全折断了。我最见不得这种场面,浑身上 下顿时一阵酥软。还是行人和浪迹天涯坚强,他们手忙脚乱地把野山雀的脚弄直, 又用树枝固定起来。中间行人不断向野山雀道歉,但我想他肯定没听见,因为我们 扳直他的脚时,他痛得几乎昏了过去。

  野山雀痛苦地呻吟着,我们三个却面对面地发呆。浪迹天涯脸色铁青,一言不 发,我想他和我一样,都陷入了深深的悔恨中。如果我们了解野山雀的底细,就决 不会和他一起出来,如果我们不是那么意气用事的话,如果我们能不计前嫌帮野山 雀一把的话,一切也许都不会发生……可惜后悔起不到任何作用,该发生的还是都发 生了,我们不仅仍然缺乏食物,而且还多了一个天大的累赘。

  后面的几天是我所遇到过的最为艰苦的日子,我们彻底断粮了。其实这情形是 我出发前就设想过的,但是我当时想在绿色的森林里总能够找到食物,我们可以狩 猎、还可以去找能食用的植物……我曾经幼稚地认为自己可以仗着一本《生存手册》 走遍天下,而那时我才知道自己以前的想法是多么乐观、多么愚蠢!没有工具,没 有经验,狩猎是根本不可能的,我们只能寄希望于寻找植物。可惜书上介绍的植物 多半都不是亚洲的。尽管如此,我们还是找到和吃过一些植物,但那滋味也绝不是 我们这些城市人所能忍受的,所有植物无一例外地苦涩和难以下咽,尝过一两次后 我就发誓,即使是饿死都不会再去吃那些鬼东西了。

  而缺粮还不算最糟糕的,我们遇到的最大问题是缺水。以前我们谁也没有想到 过在森林里还会有缺水的问题。

  水虽然在森林里随处可见,但都是一汪汪的死水,里面充满了细菌和寄生虫, 在人迹罕至的森林里喝下这种水无异于自杀,所以我们只敢喝小溪里的活水。不幸 的是小溪并不是随时都有,有的时候我们会连续遇到几条溪流,有时候又会一两天 都看不见一条。我们四个只剩下一只水壶,即便是遇到可以饮用的水也带不走多 少。那时我才认识到我们是如此的缺乏经验,假如我们把水壶这类重要物品随身携 带的话,另外三只水壶本不会丢失,然而我们却没有。

  干渴始终折磨着我们,为此我们想尽了一切办法,每天清晨浪迹天涯和我都要 四处去收集露水,这也解决不了什么问题。发现小溪时,我们都会欣喜若狂地扑过 去又喝又洗,但是终究我们是要离开的。每次离去时我们都把浪迹天涯的水壶装得 满满的,但大家都知道,装得再满也坚持不了多久。

  我们的消耗远远大于吸收,大家的身体虚弱得厉害。尽管我们自己都走不稳, 但还得轮流去抬担架。野山雀太重,我们走得跌跌撞撞,抬不了多久就必须换出一 个人休息。前进的速度也因此而大受影响,每天最多只能走五六公里,还不到前几 天的十分之一。

一切都令人绝望。

  浪迹天涯的脸色越来越阴沉,他几乎不怎么说话了,而且他看着野山雀的眼神 也变得越来越古怪,不知道他在想什么。野山雀的变化最大,他的脸上时刻带着谦 卑和讨好的笑容,总想取悦我们。他从不随便说话,也不主动要求喝水,即使是路 上的颠簸碰了他的脚,他也强忍着痛不出声。他似乎很怕得罪我们,大概是怕我们 扔下他不管吧?

  这期间我们和行人发生了一次激烈的争吵,原因是他背着我们把自己的压缩饼 干分了一半给野山雀。这令我和浪迹天涯感到十分气愤,认为要分也应该先分给我 们。我们吵得声嘶力竭,而且什么样的脏话都说出来了,之后,我们和行人陷入了 冷战。

  也许有很多人,尤其是我的亲人和朋友们都不会相信,我会在短短的几天时间 里变得这么卑琐,但事实就是那样,我不再象平日那么洒脱大方,我开始对抬担架 的轮换时间和次序,对水的分配这类事情斤斤计较。我虽然也不满意自己的这种变 化,但是我太累、太饥渴了,有的时候我简直无法控制住自己。


【八】

  第七天下午。在我们的计划中,这本应该是我们离开森林回家的时候,然而那 时我们还在林子里艰难地挣扎着,谁也不知道什么时候才能离开这该死的森林,绝 望的气氛笼罩着我们。

  雨终于停了,疲惫不堪的我们随便找了个地方,打算在那里过夜。浪迹天涯放 下担架就去找食物,行人出去找水,我留下来看护野山雀。

  不久,浪迹天涯捧着几个翠绿的野果子回来,他告诉我不远处还有很多这种果 子。这真是天大的喜讯!已经饿得七荤八素的我顿时精神振奋,立刻冲了出去。果 然,那里有一片长得很茂盛的树木,上面结满了绿油油的果子。我爬上去就摘,手 拿不了就脱下衣服装。

  野果不大,很硬,象李子一样,我想它一定会很可口。但是我还是不能完全放 心,于是我停下来弄开一只野果闻了一下,它的气味不怎么难闻,甚至还有一丝清 香,我顺势把它的汁液涂在手臂上,又开始疯狂地采摘起来。

  这是《生存手册》上介绍的一种简易鉴别法:首先切开未知毒性的植物嗅闻, 如果没有刺激性气味,就可以将它的汁液涂在皮肤上,再无明显反应,则可试吃微 量植物,五六小时后仍然没有反应才能食用。

  然而还没到五分钟,我的左臂就传来一阵剧烈的刺痛,抬手一看,整个手臂都 红肿了。当时我的心情真无法用语言来形容,就象是沙漠里的迷途客,在快要渴死 的时候猛然发现绿洲就在前方,连滚带爬地扑过去却发现那不过是海市蜃楼……我失 望到了极点,整个身体仿佛一下失去了支撑。

  良久,我才没精打采地往回走。满地散落的毒果显得是那样得水灵,饱满,我 心里一阵恶心,但我连把它们踩碎的力气都没有了。

……   远远看到营地一片混乱,确切地说,只有行人一个人手忙脚乱。

  野山雀撑在地上大口大口地呕吐,行人在一边替他拍背,又趁他呕吐的间隙朝他嘴里灌水,浪迹天涯抄着手站在一旁,冷漠地看着他们。
  我曾经专门与浪迹天涯讨论过《生存手册》,知道他对这本书也是烂熟的,所以我丝毫没有担心他们会中毒。然而,不该发生,不可能发生的事还是发生了。上下打量浪迹天涯,他身上没有一处红肿。我猛然抬头,瞪着浪迹天涯,他也正盯着我,他的目光依然锐利,带着一丝理所当然和满不在乎。实际上,我对这个快把我们拖垮了的野山雀已经没有任何好感,对于他终于栽在自己的嘴上,我也只能感到遗憾。虽然我心里觉得浪迹天涯的做法很不对,但我当时认为我们的这个团体已经到了崩溃的边缘,不值得再为野山雀弄得四分五裂。

最终,我选择了沉默。

野山雀不停地吐,最后连胆汁都吐了出来。不久,他开始发烧,面色潮红,不断地胡言乱语。行人十分焦急,但也只能一遍遍地给他冷敷,这根本解决不了任何问题。夜里,野山雀陷入了深度昏迷。


【九】

第八天清晨,我和浪迹天涯一起出去采集露水。 空气清新的早晨对我来说也不再是好的开端,我反倒觉得每一个早晨都是恶梦的开始,我也不知道自己从什么时候开始变得这么悲观。野山雀摔断腿以来的几天,我们顶多只走了20公里,我感到自己的生理和心理承受力都已经到了极限,好象随时都有倒毙在路边的可能,然而还有30多公里坎坷的道路在等着我们。30公里,如果是公路,踩几脚油门就到了,就算是走路也用不了几小时,可是对于我们来说,那段路起码得走五天,五天后我还活着吗?巨大的生存危机使得我脑子里邪恶的念头一个接一个。对于自己的这种变化,我既沮丧又无能为力,也许魔鬼已经悄悄地占据了我的心灵。

我拖着沉重的脚步走着,身边的浪迹天涯也显得心事重重。一天前发生的事让我对他产生了新的看法,具体的我也说不清,反正他总不会是什么善男信女吧?
“花乌鸦,你觉得我这个人怎么样?”浪迹天涯一边问,一边乱摇着一棵小树,任由树叶上的露珠洒落在自己的身上。我没料到他会突然这么直截了当地问我,但 我也没感到特别意外,回答道:“不好说。”

  “如果我告诉你昨天我没有给野山雀吃那果子,你相信么?”我一楞,心想这个 可能性倒是很大的。

  “我的确没有叫他吃,昨天我把果子拿回营地,放下后就出去找水了,等我回 来才发现野山雀已经那样了。”浪迹天涯漫不经心地说。

  尽管这种可能性是存在的,但是我也只能相信一半,事实究竟是怎么样的只有 老天才知道。不过,我还是宁愿相信他的这种说法,我早就觉得,野山雀迟早要栽 在自己的那张臭嘴上,于是我说:“真对不起,昨天我还以为是你让他吃的呢。”   浪迹天涯淡淡地笑了一下,说:“其实我心里倒还真这么想过,哎!如果换了 是你,你会怎么办?”

  突如其来的问题让我措手不及,我一下子不知道该怎么回答,义正辞严地说我 绝对不会?可是几分钟前我还在设想,如果野山雀就这么毒发身亡,或者凭空消失 就好了,那我们就可以轻装前进,或许还能走出去……但是我也不能说我会,毕竟我 只是在心里设想,况且我还得给自己留点脸面。

  浪迹天涯一直在很仔细地揣摩着我的表情,不知道他是否看出了我心里的想 法,我尽量不流露出任何表情,但还是发现他最终表现出成竹在胸,一切都尽在掌 握的神情,这使我很恼火,所幸前面出现的小溪适时地中断了我们的交谈。


【十】

  下午,我们跌跌撞撞地来到了第二条河边,浑浊的河水象脱缰之马一样奔流而 下,发出震耳欲聋的巨响,狭窄的河面上涌起一个个的漩涡。我们被眼前的景象惊 呆了!但浪迹天涯似乎并不在意,他把担架一扔就扑倒在地上睡起觉来。担架上的 野山雀一骨碌滚落在地,一头撞在块石头上,额头上马上鼓了一个大包。抬前面的 行人一个踉跄,险些摔倒。当他发现是怎么回事后,顿时呼地挺直身子,脸涨得通 红,他紧握青筋暴起的拳头,怒视着正在地上呼呼大睡的浪迹天涯,但看得出,他 在竭力控制自己的情绪。

  我对眼前发生的一切都漠不关心,连续四天没有吃任何东西,我浑身上下没有 半点力气,当时唯一想做的就是赶快睡觉,也只有睡着了才能忘记饥饿和疲乏。醒 来后看看四周,浪迹天涯坐在一旁,正望着河水出神。我坐起来,发现自己的肚子 仍然很空,但没有丝毫饿的感觉,我的精神稍微好了点。这时行人过来催促我们准 备过河,浪迹天涯用一种很奇怪的眼神看了他一眼,没有动弹。我心里隐隐约约感 觉到会发生点什么事,也坐着没有动。行人很敏感,他来回看看我们,最后面向着 我们坐了下来。

  我们三个就那么坐着,用探索的目光互相研究着,都没有说话。最后,还是浪 迹天涯首先打破了沉默。

  “先不讨论怎么过河的问题,刚才我算了一下,剩下的路大概有30公里,不算 远。但是以我们现在的速度,却要走五到六天,”他说,“到现在为止,我们已经有 整整四天没吃东西,再也不可能坚持那么长的时间。”

  我已经猜到了他想说什么,侧头看看野山雀,他就躺在不远处的担架里,双目 紧闭,显然还处于昏迷中。我知道此时他什么也听不见,但我的呼吸还是不由自主 地急促起来。

浪迹天涯接着说,“但是如果没有负重的话,依我们现在的身体状况,一天大约能 走十多公里,也就是说两天多时间我们就可以走出去。”他的话条理分明,语气中 没带任何感情色彩。

  虽然我曾多次希望野山雀自动消失或者死掉,但那终归是压抑在自己心底的一 个龌龊的想法而已。现在野山雀还活着,还躺在一边!而我们却堂而皇之地讨论着 是否抛弃他。浪迹天涯甚至没有提及他的名字,仅仅使用了“负重”这个词。“不 行!我们绝不能抛弃同伴,不管是在哪种情况下。”行人小声但又很坚决地说。

  “我同意!我也有过和你一样的想法,所以这些天我一直在坚持着。但是一个 人的能力是有限度的,我们总得面对现实吧?你看看现在的情况,带着他我们根本 出不去。”浪迹天涯一指旁边的河,河水怒涛奔腾,“看这条河!比上条河宽了多 少?急了多少?别说带他出去,我们自己过去都成问题!”

  “这是你的借口吧?我们都会游泳,刚才我已经想好了,我们可以用木筏把野 山雀漂过去!”行人一下激动起来,“现在野山雀有伤,又中了毒,扔下他他怎么 办?如果是你受了伤,你希望我们扔下你吗?!”

  浪迹天涯的声音一下子变得激昂起来,就象在演说,“我不会因为个人的利益 而影响集体,我拿得出壮士断腕的气魄!如果影响集体的人是我,我也能牺牲掉自 己。”马上,他又换成推心置腹的口气,“况且,我们也不是要真正扔下野山雀,一 出林子,我们可以马上带人再回来接他啊。”

  ……

  浪迹天涯能言善辩,行人根本无法驳倒他,于是他把无奈的目光转向我,问 道:“花乌鸦,你的意见呢?”

  “对!我们各占一票,就看花乌鸦的意见了。”浪迹天涯立即附和道。

 那真是一个艰难的选择。我知道,如果丢下野山雀,就算我们能回来救他,他生还的机率还是等于零,虽然我很讨厌这个胖子,但那毕竟是个活生生的人啊!

 “花乌鸦,我知道你很为难,但是在这种情况下你必须得做出选择,”浪迹天涯对我说,见我仍然举棋不定,他又补充道,“如果你不能正确决定,我们只能一齐死在这里。”

  想到死,我有些不寒而栗。几天前,我曾与死神擦肩而过,人在最后时刻的那 种绝望和恐惧在我心里留下了巨大的阴影,我还发现自己并不象幻想中那么勇敢无畏。我害怕死,也不想这样死掉,我有亲人朋友,有不错的工作,我还有大把的将来……终于我心一横,低声着对行人说,“你……和我们一块走吧。”

行人眼里期待的光芒一下子暗淡下来。

【十一】

收拾行装准备出发时,行人在一直在旁边默默地注视着我们,他决定留下来陪伴野山雀。我们反复地劝说,几乎磨破了嘴皮,得到的始终是一个坚决的“不”字。

其实我们并没有什么可收拾的,无非是勒紧皮带,系好鞋带之类,但我们一直磨蹭着,拖延着,希望行人能改变主意。最后,我们彻底失望了。

“那你怎么办?”临走时我忍不住问行人。

“我等水退下去再想办法,只要不放弃,总会有机会的。”他坚决地说。 那一刻,我感到在他的面前自己就象一粒微不足道的尘埃,我无法找到适合的文字来形容当时的场面。以前我看到文学作品中对这种场面的描写时,心里都颇不以为然,觉得俗,特俗,而轮到我来描述的时候,我才发现自己的语言是那么贫瘠,文字是那么苍白无力。

不知道是幻觉还是心理作用,我甚至看见行人全身仿佛都罩在圣洁的光圈里。强烈的对比使我们的内心完全失去了平衡,同时生出巨大的失落感。一贯争强好胜的浪迹天涯显然不习惯处于这种劣势,他悻悻地说:“那你还需要我们回来找你么?”行人的表情顿时象雕塑一样凝固了。

良久,我看见他眼框里慢慢涌出晶莹的泪花,那一定是伤心到极点的泪水。他饱含着热泪,用难以置信的目光看着我们,仿佛盯着两个素不相识的人。

他的眼睛里透出失望,那是对他曾经看作兄弟的人的失望,是对我们心灵的肮脏和人性的彻底泯灭的失望!  即使是我们做出了那样的选择,他也能够理解。他是善良的,他始终认为世界是美好的,每个人的内心其实也是善良的。然而我们却残忍地在他的心口上戳了一刀。当一个人的希望完全破灭时,他的心里会是怎样的痛?

那时我觉得用尽世上最恶毒的词汇来形容我们都不过分,我们慌乱地躲避着他的目光,甚至不敢直视他的眼睛,我们无地自容,更无法面对他,只能落荒而逃。

【十二】

该死的雨又下起来。

我们泅渡过河,象丧家之犬一样仓惶奔窜。那是厄梦一样的路途,饥饿,干渴,四肢极度疲惫,身体虚弱到了极点,最可怕的是我的内心如同荒漠般空虚。我俩没日没夜地走着,最后,我们几乎是爬出了森林。远远看见一个山民向我们走来,我心里一阵轻松,紧跟着失去了知觉。

  ……

醒来时我发现自己躺在医院的病床上,浪迹天涯已不知去向。尽管当地没有专门从事营救的机构,但是他们还是很快组织了一支由一百多名当地群众组成的搜索队,冒雨进入森林进行地毯式搜索。一周时间过去了,搜索队沿着我们的来路仔细地搜索到那条小河,没有任何迹象表明行人和野山雀过了河。队长告诉我:那条河的水位仍然很高,行人带着野山雀根本无法过河,他们唯一的选择只能是沿着河朝下游走,但是起码得走一两个月才能走去。他俩没有食品,一个极度疲惫,另一个完全没有行动能力,以那种状况想走出森林是根本不可能的。

这个事实将对我的一生产生巨大的影响,我不愿也不能接受它,所以我还是固执地等候着。搜索队继续沿着河的两岸向下搜索,又过了一周,还是没有任何消息。他俩什么也没留下,就这么消失了。那时我开始相信这世上有奇迹的存在,回城后我反复拨打行人和野山雀的电话,尽管我再也没有脸面对他们,但是我还是希望能听到他们的声音,确定他们还活着。然而,他们的手机永远处于关机状态。最后的一线希望也破灭了!我想,他们真的回不来了。通过移动公司的朋友查到了行人的地址。连续几天,我一直在他家附近徘徊。那些天总有一对中年夫妇频繁出入,他们显得很憔悴,神情中显露出焦急和担忧,也许是他们就是行人的父母吧。对于行人的父母来说,自己的儿子发生了什么事,是生是死?他们一无所知,他们唯一知道的是儿子带着行囊外出,然后一去不归。我很想做点什么,我觉得自己有义务告诉他们事实的真相,然后跪在他们面前,向他们忏悔,尽一切可能去补偿他们。但我始终犹豫着,心乱如麻。我时时刻刻都沉浸在内疚和悔恨中,白天我总是精神恍惚,夜里不断地做着噩梦,我的心里象是始终压着一块千斤巨石,不能有片刻轻松。我很痛苦,但又不敢找人倾诉,所有的一切都只能郁积在我的内心深处。除了这件事的另一当事人浪迹天涯,我想不出还有谁能够和我交流这件事的感受。我想他现在大概也很不好受,和他聊聊或许能有一些共鸣和鼓励,或许能有勇气去面对行人和野山雀的亲人们,或许能让自己的心灵得到安宁。

 拨通了浪迹天涯的手机,IT精英正在开会。听出是我,他似乎感到很突然,但他还是立刻镇定下来,“那是我们当时的唯一选择,对个人来说,也是最正确的选择,我不认为有什么错……”我不耐烦地打断他,告诉他行人和野山雀不可能活着回来了。他略微迟疑了一下,继续说“我们能活着回来也很不容易,所以得好好地生活下去啊!我承认我们的选择伤害了其他人,但是凡事总得朝前看,总不能永远耿耿于怀,背一辈子心理上和经济上的包袱吧?听我的,当这事没发生,忘了它吧……”

  我心底突然涌起一阵莫名的火气,歇斯底里地破口大骂“你这个王八蛋!”电话那边喋喋不休的声音嘎然而止,良久的沉默后,听筒里传来一个平静的声音,“你也一样。”

  …… 【后】

  漫无目的地穿行在人流熙熙攘攘的大街上,我的心却飞回那片遥远的森林,森林仍旧美丽、静寂,那里长眠着两个年轻的生命,我甚至能听到他们发出的叹息声。   那是我心灵的一次穿越,之后我发现,我的心是残缺的。


> >   一,“新红资”
> >
> >   位于北京东四的九条66号。沿东四九条胡同向东摸黑走150米,
> > 见一黑瓦朱门宅第,没有任何标志,门前只停了一辆七十年代的老红旗车,推开大
> > 门,是一个精致的小四合院,弥漫着政治僵尸的神秘气息,厢房是酒吧,沙发全是
> > 从中南海更新下来的前苏联式, 单人沙发都可以合坐两头北极熊,所有的沙发都
> > 城磨出白色毛边,据说上面曾坐过毛臀、邓臀及江臀。北屋是吃饭的正房,高悬周
> > 南五个斗字:新红资——取“新红色资本家”之意。全是中南海前政要的家厨掌
> > 勺,如,邓小平家红椒鳝丝,杨尚昆家酸辣豆苗,刘少奇家爆炒牛柳,另有刘姥姥
> > 进大观园吃的第一道菜,叫曹雪芹茄条,此菜有一种糊味,奇难吃,谁吃谁是刘姥
> > 姥。 
> >
> >   注意事项:1,此处要预订,否则不得入内,吃客九成是外国驻
> > 华使馆人士、跨国公司驻华高等白人,外国传媒驻京记者。
> >
> >   2,菜价偏贵,需多带现钱,不能用信用卡,但估计可用假钞。
> >   3,自备佐餐小姐。新红资服务员模样可人,但不出街。
> >   二,“四合院”
> >    位于紫禁城以东50米之遥的东华门95号。一楼是一个西餐为主的
> > 古朴大厅,一进去要先抢左手边一个双人座,因为桌边就是紫禁城的东华门,从窗
> > 子望出去,晚上黑呼呼的城门楼子特象文明古国那么回事,不管多张狂的女孩,只
> > 要是初来,领到这座位一坐,一准能镇住。二楼是一个小酒吧,只有六七人的座
> > 位,窗外可看见故宫角楼上挂着的铃铛——月光下很象男人的老二。
> >   只消往此一坐,从顺治阳萎出家到康熙太子乱伦,从道光扒灰到
> > 珍妃叫床,多少往事涌上心头,不由你不大发思古之幽情。一楼以下,有一个三十
> > 余平米的地下油画展厅——常人只要能看明白的作品此处一般不展,这是另类艺术
> > 家的“耶路撒冷”。 
> >   注意事项:1,来此附庸风雅前要先温习一下英文。经理是一个
> > 白种美国人,长得有点《北京人在纽约》里被姜文爆打的那个“戴维”,但其汉语
> > 水平仅限于,“你好,请付账,不打折”等几句。
> >
> >   2,有亲美情结者最宜前往,有义和团遗风者则建议在家歇息
> > 吧。大厨和老板均是美籍华人,“911”之后对客人谈及中美友谊常常双眼红肿,
> > 谈及拉灯关灯之事则咬牙不已。足令反美人士食欲萎靡。
> >   3,老外太多,且多是中国通,讽刺他们时要注意选用各省方言
> > 俚语。  
> >   三,“紫滕庐”
> >    从东华门西行,可于三更半夜里穿过故宫午门广场——世界
> > “三高”来中国扯嗓子骗美金的地方,环顾周遭,高耸的红墙,阴森的牌楼,天角
> > 的残月,夜栖的寒鸦,真是一个亲嘴儿的好地方。一路走到西华门,远远望见街边
> > 有一猩红角旗在灯光中懒散地飘来荡去,上面大书一字:茶。走进《紫滕庐》,满
> > 目迎来的是主人从中国各地收集的古代家俱,上来一个村姑模样的小姐,把扇子在
> > 你面前“哗”地一摊开,上面写着菜谱,皆为精致小炒,虽不可大吃,但来一壶当
> > 年的碧螺春,一壶绍兴老酒,温起来加上姜丝话梅,就在这些古旧的屏风间与桌椅
> > 上喝将起来,浅斟低语,说些体已的轻薄话,真是妙哉。
> >   
> >   注意事项:1,进门以后,对屋内的茶和各种字画要尽量不懂装
> > 懂,据说,世界上本没有懂,装懂装久了,也就懂了。
> >   2,此庐主为台湾人士,庐内宜谈风月,不谈风云。
> >    四,“后海银锭桥酒吧”
> >    此吧最绝之处,是没有任何名字,而且也无标志,老板姓白,
> > 特“个”——即使酒吧全空着,看你不入眼或你敢不预约就来,
> > 就算你是李嘉诚的小舅子,也一律“没地儿”。这吧是木质旧式建
> > 筑,斜傍古老的银锭石桥,向南一排木窗,正对着后海的枯树冷月,
> > 一湖寒水让人直想到老舍自沉,在哥几个为老舍的名义干了四、五杯
> > 之后,才想起老舍死的不是在这整个搞错了。举杯望去,
> > 月光下的什刹海、后海浸淫在银色的寒辉,宋庆龄故居,郭沫若故
> > 居,叶剑英故居,沿着湖边错落地分布,
> > 更远处是恭王府和辅仁大学旧址。在此处喝酒,准能喝出一种莫明其
> > 妙的破落贵族情怀,“什么什么三里屯?告诉你吧,
> > 那是农民扎堆的地儿”。 
> >   注意事项:1,此处不可摆谱。连店小二也是个爷,瞅你不顺
> > 眼,怎么叫也不理你,拉起他问究竟,他一乐:对不起,咱耳朵有点背。
> >
> >   2,“方便”不方便,地儿忒小,另一个选择是,走个七、八十
> > 米到胡同区的公共厕所,但是,根据建筑师的设计,入厕者只能面北迎风而尿,冬
> > 日里热气腾腾地尿一场下来,得打五、六个激灵,建议改喝红酒,减少新陈代谢次
> > 数。
> >
> >   
> >   五,“羊房胡同十一号”
> >    没有任何招牌,只是在院门边能勉强辩认出一行歪歪扭扭的红
> > 字:羊房胡同十一号,顺着院门走进去,你就能吃到京城最有名的宫庭菜——“厉
> > 家菜”了,当然,如果你没有提前预定座位,对不起,咽口唾沫您请回吧。
> >   在这个小四合院里,最初每天对外只做一桌菜,只供十来个人
> > 吃,吃客一律收每位200元,现在另辟一个偏房,加了两小桌,但一晚上也最多够
> > 二十个人吃。主人厉老爷子——前清华大学建筑系毕业生,八十有二的厉善鳞教授
> > 选择在吃客埋头苦干时悄然踱步过来,
> > 突然用中英等国方言如数家珍,原来,厉家菜是老爷子的祖父——西
> > 太后的内务府大臣厉顺庆爱吃的家常菜,经几代厉家人前赴后继地边吃边琢磨(你
> > 明白大清是怎么亡的了吧),形成今天的厉家菜。
> >   从客人观赏的照片看,几乎所有的发达国家和一部分发展中国家
> > 的驻华大使均领夫人来此就餐。克林顿访华时,美使馆本已定好总统来吃厉家菜,
> > 但江主席临时为克林顿摆了个家宴,结果厉家菜就与克林顿失之交臂,提起这事,
> > 厉老爷子不胜唏嘘。 
> >   注意事项:1,厉家菜不太好吃但有颇特色,不可不去,不可
> > 多去。
> >   2,厉家是旗人且为正宗遗老遗少,因此就餐时一言一行要注意
> > 民族团结,不能渲染大汉族沙文主义,也不可用“杨州十日”,“嘉定三屠”为
> > 由,吃完嘴一抹拒绝付帐。