您,知道上看到你做过C#用USBplc与仪表通信信的程序,不知道您的问题解决没,能否向您学习一下?

下次自动登录
现在的位置:
    安晓辉,2014年CSDN博文大赛编程语言组冠军(小组赛文章、决赛文章)、CSDN Qt论坛的版主(http://bbs.csdn.net→移动开发→Qt)。他于1998年保送入西安交大教改班,2002年毕业进入西安大唐电信从事售后技术支持工作,2005年3月离职,始习编程之术。在此期间,有个人文集收录于各大文学站点与论坛,部分散文、小说、书评见诸杂志与报纸。国内第一本BBS原创文集《指尖的飞翔》(兵马俑BBS原创文学精选)作者之一。网络文学选集《竹林听海》作者之一。2005年4月加盟西安信利软件科技有限公司,参野狐禅,走开发路。
    2008年见Qt而倾心,用之于GUI、网络服务器、嵌入式开发,带领团队成功开发出基于 Qt 的互联网电视机顶盒。2012年移植 Qt Embedded 4.5.2 到 Android平台并应用于智能机顶盒项目。著有《Qt on Android 核心编程》和《Qt Quick核心编程》。
CSDN:请和大家介绍下你和目前所从事的工作。
安晓辉:我始终觉得自己的身份是一个程序员,是手艺人,我觉得靠技术吃饭是纯洁、高尚、值得尊敬的,有诗为证:闲来就写青山卖,不使人间造业钱。
我从技术支持转做程序员,做到现在,已经有将近十年。一路走来,项目经理、部门经理、项目总监,很多角色都干过,现在入伙朋友的公司,算是最小的合伙人。公司在做的事情还不能说,没做出来呢,做出来了再说。不过我们正在招人,Android、iOS、Java,感兴趣的朋友可以联系我(邮箱:)。
CSDN:你是如何走上软件开发之路的?
安晓辉:其实当时我转行做开发,是形势所逼,觉得自己干不了别的。写小说出版不了养活不了自己吧,搞销售又没有脸皮和嘴皮,还能干什么……干技术活儿吧,于是就决定做开发了。当时还有一个考虑,觉得软件开发是有创造性的工作,应该和写小说有差不多的乐趣。现在看来,确实有很多东西是相通的。这一点已故的文坛外高手王小波已经证实:他本人既是一流的小说家,又是一流的程序员!
犹记得我毕业那会儿通信行业很火,大中华(大唐、中兴、华为)很流行,我随着滚滚人潮就进了大唐电信,去做技术支持。干了两年,觉得自己要废掉了,整天东奔西跑插拔程控交换机、换板卡、跳线、更新版本,没有挑战。另外老出差,也不是个事儿,就想转行,不打算再做技术支持了。回到西安后,没能在公司内部转研发,我就辞职了。
大学学过PASCAL,可是很少有软件公司用这个,读了几天Java,觉得不对胃口,就去学C语言,经典的《the C Programming Language》,很对胃口(关键书薄薄的一本,感觉比较好征服)。大学时宿舍有个哥们儿从教改班转到了计算机系,擅长C,指针指针指针的满嘴跑,很高深的样子,有点儿印象,这也是我选择C的一个原因。
花了一个星期,粗读了一遍书,我就开始颠颠地跑着找工作了,目标就是软件开发。当时也不会干别的,做技术支持时程控交换机里的软件是公司的牛人们做的,我觉得这也是个不错的行当,带着憧憬就奔它去了。
理想是美好的,现实是残酷的。对于我这种半道出家的野和尚,就看了几天书,居然敢于跑到要求熟悉这个精通那个的公司去应聘,也是逼不得已。我记得花了一个多月的时间还没找到工作,不断被鄙视吧。唯一的收获就是C的笔试题做了好多,到最后终于觉得可以顺利通过一部分公司的笔试关卡了。后来面试华为,过了三面,因为没有经验,推荐我去慧通,我嫌慧通不是嫡系,就没去。整整行囊,拍拍灰尘,继续找吧。
人品总是会爆发的,只要你多坚持那么两天。再后来比较幸运,遇到了信利的谢总胜落,愿意把我招入麾下,我就这么在西安信利软件科技有限公司开始了我的软件开发之旅。
时间如箭飞逝,已经快10年了。
CSDN:通过你的简介了解到,你就读于具有深厚理工科传统的老牌名校西安交大,却是国内第一本BBS原创文集《指尖的飞翔》(兵马俑BBS原创文学精选)作者之一,也是网络文学选集《竹林听海》作者之一,能简单介绍你涉猎文学写小说的情况?
安晓辉:上大学的时候,已经丧失了学习的兴趣和动力,整日无所事事。彼时网络又刚刚兴起,痞子蔡的《第一次的亲密接触》打开了网络文学的窗户,大家都觉得网络上写小说这种事儿,会码字就成,碰巧计算机扫盲扫过了,会码字,于是就在兵马俑BBS上混起来了,做了几个文学版的斑竹。当时榕树下、红袖添香、西陆文学、网易文学论坛、故乡、天涯舞文弄墨等都还挺有人气,也混了一阵子,还拿了一届西陆文学的十大明星写手,不过水平有限,到现在基本不写了,而当时曾经擦肩而过的一些写手,如今很多都是文学界的宠儿了。
CSDN:如今走上技术之路,平时写的都是技术博文,接下来还会再提起笔?或有其他一些规划吗?
安晓辉:其实我对写小说还是情有独钟。当年红袖添香文学大赛有个哥们儿写了一长篇武侠,献给自己的女儿,据说都是在把女儿哄睡之后写的。小说写得特别好,我印象深刻。我有女儿时我还想,也要为女儿写一部武侠小说,可惜到现在还没开始动笔……武侠小说技术性太强(主要是武斗场面金古梁温已基本写尽很难出新),我是干不来了。最近在考虑以程序员为背景的小说,也许过阵子会写,也许没几天又忘了。
CSDN:你对文学用情颇深,你对技术又有着怎样的情感?
安晓辉:人的生活应该有多个支点,技术和文学是我的两个支点。我个性内敛,闷头干活的事情我喜欢,靠自己就靠得住的事情我喜欢,技术恰巧就是这类事情。我一直不觉得自己对技术有多痴迷,可我媳妇说他就害怕我写程序,因为写起来什么都不顾,这让她觉得压力很大。所以前一阵子我辞掉一个公司的总监职位时,她就表示特别的担心,因为看起来是要再干开发的节奏嘛。现在看来,技术已经是我的立身之本了,我身上也已经被打上了深深的烙印,到驾校都有同学说我一看就是搞开发的……
CSDN:成功者总是在不断的学习,每个人都有自己的学习之法,你的一路以来是如何学习的?
安晓辉:软件开发会经常接触新东西,必须有足够的好奇心和兴趣,才能不断的学习进步。
至于如何学习,每个人都有自己的模式,我受现行教育体制荼毒比较深,学一门技术时,遵循的是看书、实践、再看书、总结这样一个模式。
在实际工作中,我有一个基本的理念,那就是:用到一分,你就往广里多学一分,往深里多学一分。这样时间长了,自然会不断丰富自己,脱胎换骨。
回忆过往,我高三以来一直没好好学习(对不起父母对不起毛主席啊),能进交大的教改班那是因为高一高二的底子好混了个保送名额。大学的时候基本上就徘徊在被淘汰的边缘(教改班实行末位淘汰),泡BBS(兵马俑),玩游戏(仙剑、轩辕剑、星际争霸、三国志、英雄无敌等等),踢球……就这么过了四年。所以谈到学习,真是非常惭愧。但我觉得大学生活也没白过是吧,我现在的看法是:你知道怎么学习,那什么时候学都不晚。不是说朝闻道夕死可矣吗。
因为大学没怎么学,什么操作系统、信号原理、模电数电、计算机组成原理、数据结构等等,都不知道考试怎么及格的,后来又干了两年技术支持,对于软件开发,实在是知之甚少啊。
八小时之内是现在,八小时之外是将来。什么意思呢,你懂得。
我其实还是一个比较爱钻研的人,毕竟初中、高中的各种奥数、奥物、奥化竞赛都拿过奖;另外我也是一个心里存不住疑问的人,所以我不但刚开始干软件开发的时候业余时间老是买各种技术书看,后来干熟练了,依然抽时间学习技术。这已然成了习惯。当你工作中用到一项技术,可能只是用其一点,那还有与这点关联的很多点,那这门技术必然还有很多相关的技术,用心的话,会想了解更多,于是,以点带面,就会持续不断地学下去。好好学习,天天向上么,这时候才发现这不是一句空话。
如果你发现了自己的学习模式,愿意学并且能坚持,我觉得没什么能阻挡你征服软件世界的脚步。每当我遇到一个问题,常常会茶饭不思,吃了也是味同爵蜡,我脑子就离不开这个问题了,直到有一个答案,很多时候我都是梦里还在思考某条路线到底能否走通某个BUG能否解决,也有不少次半夜醒来的时候。人家女孩子午夜梦回是看了《午夜凶铃》,我们干开发的,有时候半夜突然坐起来是因为不小心想到自己把雷埋在哪里了。
都说IT这行日新月异,那确实,还真没哪个行当可堪比拟。对开发者来讲,自然是需要不断学习的。但我觉得更重要的一点是:发现自己的学习模式。一旦你能够用模式来指导你的学习,有意识地践行、改进你的学习模式,那年龄我觉得也不是问题,到40岁,到50岁,依然可以跟得上技术的发展。
<font color="#08年,当时如日中天的诺基亚公司宣布以1.53亿美元收购奇趣科技(Trolltech),并更名为Qt Software。这次收购一度被业界视作诺基亚意在加快移动设备和桌面应用的跨平台软件战略部署,加速推出互联网服务业务。但世事无常,随着诺基亚宣布放弃Symbian系统,以及IOS/Android系统的快速崛起,2011年3月,Qt的商业授权和技术支持业务被Digia收购,2012年8月,Digia宣布完成对全部Qt技术平台和知识产权的收购。
CSDN:作为一款跨平台图形界面软件,Qt开发工具可实现在多操作系统以及移动设备之间一致的跨平台用户体验,你觉得被收购后的Qt至今发展如何?
安晓辉:发展得还不错,在嵌入式和很多行业都有更好的表现,目前又支持了Android 、 iOS等移动平台,作为跨平台的解决方案,始终是最强悍的。
具体情况,在我的《Qt on Android核心编程》一中也有提到,摘录如下:
Qt 被 70 多个行业中数以千计的主要企业所使用,内部使用 Qt 的数百万计的设备和应用,你每天都会使用。
Qt 强有力地支持着来自 70 多个行业中的主要企业开发了数以百万计的产品,也是财富 500 强企业里前10个企业中的5个所选择的开发技术。 Qt 的完整框架功能(包括直观的 C++ 库、工具和 Qt Quick UI技术)使它成为汽车、手机制造商、工业自动化、消费电子产品、石油和天然气、国防和各种各样的其他领域内顶级玩家的首选技术。
CSDN:每一个工具都有适合的使用场景,Qt也不例外,对于开发者来说,是否选用一种技术,要看这个技术和他的需求是否契合。Qt适合的应用场景有哪些?
安晓辉:Qt特别适合跨平台开发,比如你要支持Windows、Mac OS X、Linux、Android、iOS等等平台,那Qt绝对是值得考虑的技术方案。
比如办公软件,要跨平台,支持Windows、Mac OS X、Linux、Android、iOS等,就可以选用Qt。又比如用于企业办公的网络会议系统,也需要同时支持桌面和移动平台,Qt也是很棒的解决方案。又比如一些行业软件,医疗、工业自动化、自动控制等,都有很多使用Qt的。当然你也可以使用它做游戏,“吃药了”这款游戏就是用Qt做的,还有很多其它的游戏也选择了Qt。
CSDN:Qt支持的平台包括Windows、Mac、Linux等桌面操作系统,QNX、VxWorks、Embedded Linux等嵌入式平台,还包括Android、iOS、WP/Windows Runtime三大移动操作系统,和Java跨平台相比有什么区别?前者的优势是什么?
安晓辉:Java在做web端应用时很有优势,跨平台也威力强大。但是目前的移动端,客户端应用,如果说你在Android上用Java,没有问题,因为Android使用Java作为基础语言构建了针对Android的一套UI框架,但是你在iOS上使用Java来做应用,在Windows Phone上使用Java来做应用,还有其它的一些平台,都是非常吃力的,没有好的解决方案。
而Qt的跨平台,在桌面应用开发,在移动端应用开发,所有平台都是一致的体验,它针对各个平台编写平台相关的QPA插件,直接与各个平台融合在一起,最终既不损失性能又跨平台,对开发者来讲,一次编写,多次编译,到处运行,这实在是太迷人了!
CSDN:日前,你出了《Qt on Android 核心编程》一书,能否谈下写这本书的缘由?期间有什么难忘的事?
安晓辉:因为我有写小说的梦,也写过不少未发表的小说,对写作其实是有情结的。我想有一本自己的书,但其实没想到会是技术书。
2008年在西安信利软件使用Qt开发机顶盒产品接触 Qt,一见倾心,她优雅从容,非常好看。之前也用过MFC、WTL、Win32等等框架,但仅仅是用而已。我用Qt做嵌入式开发,工作之外我也想研究她,看看她到底是什么回事儿,从外到里,一层一层剥剥看,所以就去读了源码,慢慢就对Qt有了较为深入的了解,形成了有问题看帮助,帮助不行看源码的习惯。
我觉得一个人技术做到一定程度,会愿意与他人分享,不介意把自己辛苦得来的技能和经验讲给他人来听。这是一种自发的行为吧,也算是一种修炼。知识这玩意儿是为数不多的越分享越多、越碰撞越好的东西。
13年底时我恢复了在CSDN的博客更新,其实这个时候我工作已经很少用Qt了,但Qt刚好出了支持Android的版本,我就想研究它。Qt还出了Qt Quick这个迷人的小姑娘,我也想研究它。于是不断地在博客上记录我的学习历程,我知道的都讲出来给大家看,不作保留。
后来电子工业出版社博文视点的策划编辑高红霞老师联系我,问我愿不愿意出书,那当然愿意啊,我有出书的情结嘛。说干就干了,我们一个电话没打过,事情就敲定了,我开始挑灯夜战,天天晚上都写,不是一点就是两点。不写的时候也在琢磨怎么写。周末也搭上了。连女儿我也很少陪她玩儿了。总之我全身心地投入了这件事情当中,也没在意老婆说的“万一卖不好岂不白辛苦”这种问题,我喜欢,我愿意这么干,我就这么干了。老婆善解人意,支持我,女儿小小年纪也支持我,这是最令我开心的事儿。
《Qt on Android核心编程》这本书就这么出来了,我人也瘦了十来斤,不过我要说的是,做了,爱了,享受了这个过程,无怨无悔。
在写《Qt on Android核心编程》的时候,我发现Qt Quick这个框架无论如何不能包含在里面了,而这么好的东西如果我不把她展示出来,那就太暴殄天物了。于是我跟高老师讲我还要做一本书,Qt Quick的,而且目前国内没有同主题的书,于是我就做选题做大纲,于是又通过了,事儿就这么成了,于是我马不停蹄又投入了新的写作。于是几个月后《Qt Quick核心编程》出来了。
请容许我讲讲这两本书吧。
《Qt on Android核心编程》主要分两部分,一部分讲述Qt核心的概念,比如信号与槽、元对象系统、网络、Qt Widgets等等,非常适合Qt初学和进阶;另一部分讲解Qt在Android上的开发主题,比如触摸、手势、传感器、JNI扩展等等,适合对使用Qt开发Android应用的感兴趣的朋友。总之这本书既可以作为Qt入门参考,也可以作为Qt移动开发的入门参考。
《Qt Quick核心编程》是专门讲述Qt Quick技术的,从QML语言、Qt Quick基本元素、Model-View、动画、多媒体、网络、Android主题……该讲的都讲了,不该讲的也讲了,总之我觉得它是业内第一本系统讲述Qt Quick的书,是填补空白之作,对于初学 Qt Quick(QML)的开发人员和想进阶的开发者都有很好的参考、借鉴意义。
CSDN:当Qt跨界牵手Android,移动开发会有什么不同?
安晓辉:有这么几点,我觉得非常重要。
1. 跨平台,之前说过了,你为Android开发的应用,稍作改动,就可以支持iOS和其它平台,想想就兴奋嘛。你只要学了Qt,就拥有了全平台的神器。
2. 开发的便利性,比方说你开发Android应用,需要模拟器,而AVD又慢得要死要活的。Qt就不同了,你直接可以在桌面环境下调试你的应用逻辑、甚至是界面,非常方便。Android就不行,因为界面是必须依赖Android系统。
3. 丰富、成熟、强大的类库,比如网络处理的类库,以http为例,天生是异步的,很好用。而Android提供的Http类库,比较难用,想异步,就得配上线程,不友好么,这点从我写的一篇介绍AsyncHttpClient的博文的点击量就可以看出来,大家都在寻找更好用的Android网络类库。Qt还有很多其它的类库也很强大,看我的《Qt on Android核心编程》就知道了。
4. 经验的延续性,比如你用过Qt开发桌面软件,用它开发Android等移动软件,你的经验一脉相承,没有陡峭的学习曲线。而就算是Java开发人员,要开发Android应用,也要重新学习Android的UI类库。
CSDN:初学者如何借助Qt开发Android应用?
安晓辉:只要针对Android的环境搭建起来了,其它的事情和桌面开发差不多,很方便。
安晓辉老师也是半路出家学编程,经历了一个痛苦过程,如今十年过去,一路从程序员、小组长、项目经理、部门经理就这么走着……今年他完成了两本书的写作、换了工作了,新工作也告别写代码……作为一名老程序员,在面对开发群里经常有学生问面试、择业等问题时,有感而发特开辟了《漫谈程序员》专栏,以幽默的笔调深受网友们的喜爱,由于文章诙谐指数高入云霄,在这里我们也请安老师以一个比较正式的口吻来分享,让我们来一起关注程序员成长。
CSDN:作为十年的程序员,你是如何看待程序员这一角色的?
安晓辉:程序员,就是手艺人的角色,吃的是技术饭。他当然有很多的酸甜苦辣咸,与其他行业并无不同。关键是我们自己的心态,你喜欢,你就有乐趣,如果你纯粹是把它当作一个挣钱糊口的手段,那可能就会慢慢厌倦这种高强度高更新频率的工作,要么麻木要么转行。
其实程序员没有比其它人苦逼多少。你说夜班出租车司机苦逼不,天天熬夜……你说建筑工人苦逼不,累死个人还被小市民鄙视……你说明星苦逼不,结婚了都不敢说,酒店开房还要被抓……你说国家领导人苦逼不,该颐养天年的时候还得四处奔波,还说不定哪天就被揪斗了……关键是心态,所谓此心安处是吾乡,每一行都有它的苦乐忧愁,花开富贵一季红,竹生平凡千日青,放平心态,一切都会不同。
CSDN:你也是中途踏入软件开发之路,程序员的门槛几何?与此同时,你认为普通程序员和优秀程序员的不同之处在哪里?
安晓辉:程序员没什么门槛,但是从普通到优秀,从优秀到卓越,这里面各有很长的路要走,对很多人来说,穷其一生也不一定能走完这中间的旅程。
关于普通和优秀的差别,从做事结果上看,优秀程序员做出来的软件可能有更好的易用性、健壮性、安全性、灵活性;从行为上看,优秀程序员会更积极一些,自我成就欲望强一些,最终表现在解决问题的思路、手段、能力等更强一些。
CSDN:一个程序员该如何学习技术以及选择技术方向?
安晓辉:对多数人来讲,你所做的事情决定你要学习的技术以及你将来会走的技术方向。当然有相对的一面,有些人,是先选技术后选事情,根据技术选要做的事情。但不管哪种,到最后,我个人观点,具体的技术都不再重要。重要的是,解决问题的能力。因为程序员的职责其实不是编写程序,而是解决问题。
如果非要讲如何学习技术,那还是奉行“实践出真知”吧。
至于选择技术方向,虽然说技术无高低,但还是要选择有发展潜力的吧,有些没落的,走下坡路的,就不要选择了,比如MFC之类的。需要说明一点的是,很多技术都有其特定的应用场景,我们在选择某一个技术方向时,实际上也选择了你工作的方向。这点可能会给将来的就业带来很大的影响,所以决定要学一门技术时,还是要了解一下它能解决什么问题,在什么行业得到了什么样的应用。
CSDN:有一定的技术后的准程序员们怎么找工作?以及有哪些职业风险?
安晓辉:这个话题比较大,我在漫谈程序员系列中也有谈及,感兴趣的可以移步阅读。
其实干什么都是有风险的,对于开发人员来讲,最大的风险是什么呢?选错一门技术?干错一个项目?做错一个产品?跟错一个老板?……也许都不是,也许是没有在合适的年龄找到合适的妹纸……
对于开发人员来讲,最大的风险是:在职业规划上没有延续性地乱跳槽。
有人跳槽为了涨工资,不跳不涨么。一年都能换几次,也不管工作内容、技术路线什么的。这其实也无可厚非,是吧。龙生九子,个个不同。理解万岁。桥归桥,路归路。
我是比较迟钝的人,到了 30 多岁才第一次正式地来审视“怎样找工作、找什么工作”这个问题,可能是年龄大了吧,觉得不能再玩从零开始的游戏了。有人早慧,可能大学没毕业就明白了这个道理。真的,我有一同学,毕业时放着微软不去,坚定地找嵌入式的机会,真给他找着了,并且干得风生水起……还有个小盆友,小学时就说长大了要当校长,原因呢,是因为他的老师老打他手心,他当了校长就可以直接开掉这个老师……
当年我在参加一家公司的面试时对面试官说:要在两到三年内做到不可替代。结果被拒了……你懂的,单位都讨厌这个。可是作为开发人员,这是你时刻要牢记在心的:培养自己的稀缺性。
为什么这么说呢?物以希为贵么。如果你很牛X,干的活儿很重要,别人又替代不了,你自然受重视是吧。
CSDN:你做过五六年的项目经理,你对好产品的理解是什么?
安晓辉:说说我早前的经历吧,工作上回到老东家,是因为老板对我说要做产品,做一个视频相关的产品,具体是什么还不清楚。那时我虽然还有点儿糊里糊涂,听过很多道理,还没过好这一生。可毕竟已经不是懵懂少年,多少有了些自己的看法。觉得做产品比较靠谱,比外包靠谱,比外企有更大的可能性,没准一下子红了呢?风水轮流转,明年到我家,也许就可以鲜衣怒马走天涯……
这是我当年的一个认识吧:
“有产品做,就不要做外包;有独担一面的机会,就不要去做外企或者大公司的螺丝钉。”
当然很多人与我见解不同,理解并支持你们!王小波是罗素的信徒,罗素说,参差多态乃幸福之本源。本来么,求同存异,不能视见解与己不合的人为异端,那是法*西斯。工作中其实也是一样的。
吭哧吭哧干到了 2014 年,从 08 年到 2014 年,发生了很多变化,老婆孩子什么的都有了,人生有几个六年呢……有了白头发了……
如今,再来说一下我对好产品的理解,大概是这样的:
解决用户痛点
所处行业前景光明
产品有延续性,可持续性发展
好产品加上靠谱的公司,基本上就是比较靠谱的工作了,甚至可以做成事业。
总的来说,能解决用户痛点的产品就具备了好产品的基本条件。如果还能给企业带来效益,那就是真正的好产品了。这就是好产品的两面。
CSDN:怎么判断公司靠谱呢?
安晓辉:我有一些经验,用来鉴别不太靠谱的公司或工作:
只关注你过往能力和项目的匹配度
只想用你已有的技术能力解决公司遇到的问题
面试你的人对公司产品没有热情,自己都不了解公司的产品远景,也不了解公司的远景,说不出个一二三
没有新产品,招你就是维护性开发
如果新公司靠谱,有实力(有一帮牛人、有资本投入)把这个产品做好,那是最好的了。
对于如何了解一家公司呢。我认为互联网搜索、熟人打听、公司网站、招聘要求等都是途径。还有一个就是面试,一定要牢记,面试是双向的,不但是公司选择你考问你,也是你最好的了解这个公司的机会,有时机就问一些思考过的问题:为什么自己要离开现在的公司、自己想干什么、将来的路怎样规划等。
我在面试一些应聘者时,通常在最后会留机会让他们问问题,经常遇到有些求职者说我没什么问题……这么好的机会都放过了,一般这种情况,这个人我就不再考虑了……
CSDN:对于那些正在大学的准程序员和初级程序员,你最想对他们说什么?
安晓辉:假如一句话来概括的话:
不畏浮云遮望眼,风物长宜放眼量。
另外,作为开发人员,我们需要了解自己的能力边界,清楚自己能干什么不能干什么,多多发挥、打磨自己的长处。所谓自知者明自胜者强,有些短处倾其一生也是无法改变的,天生的,没必要在意。而有些长处经过打磨会越来越好,如果你不去发掘、培养它,那它也可能慢慢萎缩掉。
还有非常重要的一点,开发人员需要在软件开发之外建立另外的一个兴趣。人生需要多个支点,多样的生活会更加有趣。
来源:CSDN
【上篇】【下篇】
您可能还会对这些文章感兴趣!
百度站内搜索
同分类最新文章C#编写一个USB接口通信的程序
[问题点数:100分,结帖人Mither]
C#编写一个USB接口通信的程序
[问题点数:100分,结帖人Mither]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
相关帖子推荐:
2010年12月 C++ Builder大版内专家分月排行榜第二2010年11月 C++ Builder大版内专家分月排行榜第二2010年7月 C++ Builder大版内专家分月排行榜第二2010年6月 C++ Builder大版内专家分月排行榜第二2010年4月 C++ Builder大版内专家分月排行榜第二
2011年4月 C++ Builder大版内专家分月排行榜第三2010年8月 C++ Builder大版内专家分月排行榜第三2010年2月 C++ Builder大版内专家分月排行榜第三2009年12月 C++ Builder大版内专家分月排行榜第三
2009年2月 .NET技术大版内专家分月排行榜第三
本帖子已过去太久远了,不再提供回复功能。物联网原理与应用技.._百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
&&&#165;1.00
喜欢此文档的还喜欢
物联网原理与应用技..
阅读已结束,如果下载本文需要使用
想免费下载本文?
把文档贴到Blog、BBS或个人站等:
普通尺寸(450*500pix)
较大尺寸(630*500pix)
你可能喜欢条形码数据采集器(不是扫描枪)如何与c#程序通讯呢?
[问题点数:20分,结帖人luby]
条形码数据采集器(不是扫描枪)如何与c#程序通讯呢?
[问题点数:20分,结帖人luby]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
相关帖子推荐:
本帖子已过去太久远了,不再提供回复功能。当前位置:
使用C#制作《邮件特快专递》
使用C#制作《邮件特快专递》
发布日期: 17:42
浏览次数:36308次
标  签:网络与通信
文章评分:5.0
操  作:
称号:未设置简介:...
文章概要:
Foxmail 新版中有一个《邮件特快专递》的功能。起先搞不懂如何用,后来知道要在“工具->系统选项”那边设置“本地 DNS 服务器的IP地址”。
  觉得这个新功能蛮好用的。不需要通过SMTP代理,可以直接通过本地往邮箱所在的邮件交换器发送邮件。在暑假一开始想在 VC++ 中实现这个功能。用 IRIS 截包后,发现程序中有 mx8.263.net 发送邮箱,不知道这个是什么东西,所以作罢。后来才想到这个就是 263.net 的MX记录主机,原来特快专递的原理就是往这个主机上发送数据就行。
Foxmail 新版中有一个《邮件特快专递》的功能。起先搞不懂如何用,后来知道要在“工具-&系统选项”那边设置“本地 DNS 服务器的IP地址”。
觉得这个新功能蛮好用的。不需要通过SMTP代理,可以直接通过本地往邮箱所在的邮件交换器发送邮件。在暑假一开始想在 VC++ 中实现这个功能。用 IRIS 截包后,发现程序中有 mx8.263.net 发送邮箱,不知道这个是什么东西,所以作罢。后来才想到这个就是 263.net 的MX记录主机,原来特快专递的原理就是往这个主机上发送数据就行。
运行 nslookup 程序:
  set type=mx
  263.net
  有了,有了,得到结果:
  Non-authoritative answer:
  263.net MX preference = 10, mail exchanger = mx06.263.net
  263.net MX preference = 10, mail exchanger = mx08.263.net
  263.net MX preference = 10, mail exchanger = mx09.263.net
  263.net MX preference = 10, mail exchanger = mx11.263.net
  263.net MX preference = 10, mail exchanger = mx12.263.net
  263.net MX preference = 40, mail exchanger = mx03.263.net
  263.net MX preference = 10, mail exchanger = mx01.263.net
没有错了。就是这个了。后来因为不知道怎么实现 nslookup 的功能,就放弃了,学了半个多月的C#。后来偶然在网上查找到了一些相关的文档。几次实验。把我的开发过程拿过来分享,我第一次写教程性文档。所以不规范之处,请大家包涵。本文涉及的域名、邮箱及IP均为真实的。
二、DNS协议原理
我认为,要想成为一个好的网络软件程序员,必须得读懂RFC文档。因为本文是面向大多广泛程序爱好者,所以我尽量从细节上写,如果高手的话,可以跳过此部分。
DNS协议的相关RFC文档:
RFC1034-《DOMAIN NAMES - CONCEPTS AND FACILITIES》
  RFC1035-《DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION》
网上的计算机用形如 220.162.75.1 这样称为IP地址的数字串来标识一台计算机。而如果每次访问一台计算机都是通过输入这样的东东来访问,那不就太可怕了?以是出了DNS这样的好东东,用要指示其绑定的IP地址,当我们在浏览器内输入
时,浏览器不知道网页该到哪里取,于是就向设定好的DNS服务器查询这个域名。DNS服务器会先寻找自己的记录库,如果没有发现就转向上一级DNS服务器进行查询(转发请求)。把找到后的IP告知你的浏览器。这里边浏览器查询的记录类型是A记录。RFC1035文档第11页中定义有16种记录类型,而常见的有A(地址)记录、CNAME(别名)记录、MX(邮件交换)记录。我们本篇要关心的是MX记录。
查询的过程一般是:客户向DNS服务器的53端口发送UDP报文,DNS服务器收到后进行处理,并把结果记录仍以UDP报文的形式返回过来。
此UDP报文的一般格式:&
+---------------------+
+---------------------+
| 向服务器提出的查询部分
+---------------------+
| 服务器回复的资源记录
+---------------------+
| 权威的资源记录
+---------------------+
| 格外的资源记录
+---------------------+
除了报文头是固定的12字节外,其他每一部分的长度均为不定字节数。
我们在这边关心的是报文头、问题、回答这三个部分。
其中报文头的格式:&
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|AA|TC|RD|RA|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
好家伙,是什么鬼画符!
其中最上边是位的数字标识,0-15(注意,后边的10-15写成上下的形式了,一开始我楞没看懂)。
接下来是:
ID:占16位,2个字节。此报文的编号,由客户端指定。DNS回复时带上此标识,以指示处理的对应请应请求。
QR:占1位,1/8字节。0代表查询,1代表DNS回复
Opcode:占4位,1/2字节。指示查询种类:0:标准查询;1:反向查询;2:服务器状态查询;3-15:未使用。
AA:占1位,1/8字节。是否权威回复。
TC:占1位,1/8字节。因为一个UDP报文为512字节,所以该位指示是否截掉超过的部分。
RD:占1位,1/8字节。此位在查询中指定,回复时相同。设置为1指示服务器进行递归查询。
RA:占1位,1/8字节。由DNS回复返回指定,说明DNS服务器是否支持递归查询。
Z:占3位,3/8字节。保留字段,必须设置为0。
RCODE:占4位,1/2字节。由回复时指定的返回码:0:无差错;1:格式错;2:DNS出错;3:域名不存在;4:DNS不支持这类查询;5:DNS拒绝查询;6-15:保留字段。 
QDCOUNT:占16位,2字节。一个无符号数指示查询记录的个数。
ANCOUNT:占16位,2字节。一个无符号数指明回复记录的个数。
NSCOUNT:占16位,2字节。一个无符号数指明权威记录的个数。
ARCOUNT:占16位,2字节。一个无符号数指明格外记录的个数。
其中每个查询的资源记录格式:&
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
QNAME:不定长,表示要查询的域名。(两边的方框用 / 来表示不定长)
QTYPE:2字节,根据RFC1035及nslookup的帮助文档,我定义以下枚举类型:
enum QueryType //查询的资源记录类型。
A=0x01, //指定计算机 IP 地址。
NS=0x02, //指定用于命名区域的 DNS 名称服务器。
MD=0x03, //指定邮件接收站(此类型已经过时了,使用MX代替)
MF=0x04, //指定邮件中转站(此类型已经过时了,使用MX代替)
CNAME=0x05, //指定用于别名的规范名称。
SOA=0x06, //指定用于 DNS 区域的“起始授权机构”。
MB=0x07, //指定邮箱域名。
MG=0x08, //指定邮件组成员。
MR=0x09, //指定邮件重命名域名。
NULL=0x0A, //指定空的资源记录
WKS=0x0B, //描述已知服务。
PTR=0x0C, //如果查询是 IP 地址,则指定计算机名;否则指定指向其它信息的指针。
HINFO=0x0D, //指定计算机 CPU 以及操作系统类型。
MINFO=0x0E, //指定邮箱或邮件列表信息。
MX=0x0F, //指定邮件交换器。
TXT=0x10, //指定文本信息。
UINFO=0x64, //指定用户信息。
UID=0x65, //指定用户标识符。
GID=0x66, //指定组名的组标识符。
ANY=0xFF //指定所有数据类型。
QTYPE:2字节。 根据RFC1035及nslookup的帮助文档,
我定义以下枚举类型:
enum QueryClass //指定信息的协议组。
IN=0x01, //指定 Internet 类别。
CSNET=0x02, //指定 CSNET 类别。(已过时)
CHAOS=0x03, //指定 Chaos 类别。
HESIOD=0x04,//指定 MIT Athena Hesiod 类别。
ANY=0xFF //指定任何以前列出的通配符。
QTYPE中的A,MX,CNAME为常用,QCLASS中的IN为常用。   其中每个回复的记录格式:&
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
NAME:回复查询的域名,不定长。
TYPE:回复的类型。2字节,与查询同义。指示RDATA中的资源记录类型。
CLASS:回复的类。2字节,与查询同义。指示RDATA中的资源记录类。
TTL:生存时间。4字节,指示RDATA中的资源记录在缓存的生存时间。
RDLENGTH:长度。2字节,指示RDATA块的长度。
RDATA:资源记录。不定义,依TYPE的不同,此记录的格示不同,通常一个MX记录是由一个2字节的指示该邮件交换器的优先级值及不定长的邮件交换器名组成的。
这边述说一下名称的组合形式。名称由多个标识序列组成,每一个标识序列的首字节说明该标识符的长度,接着用是ASCII码表示字符,多个序列之后由字节0表示名字结束。其中某一个标识序列的首字符的长度若是0xC0的话,表示下一字节指示不是标识符序列,而是指示接下部分在本接收包内的偏移位置。
比如  以.分开bbs、zzsy、com三个部分。每个部分的长度为3、4、3
在DNS报文中的形式就如 3 b b s 4 z z s y 3 c o m 0
假如在包内的第12个字节位置存在有 4 z z s y 3 c o m 0 这样的名称了。
那此时有可能为:3 b b s 4 z z s y 0xC0 0x0C 这样的形式。
三、DNS协议实例讲解
说了这么多理论屁话,可能头都有两个大了吧。还是用一个实例的方法来说明吧。我选用著名的网络截包及协议分析工具IRIS 4.05,您可以从我的站点上下载:
  /data/Iris405Full.rar
运行Iris,点击菜单的Filters 选 Port标签页 运用 53 端口后点确定。点击Iris工具栏上的绿色运行图标进行监听。在 Windows 中运行 nslookup 程序。
输入以下命令:
   set type=mx
然后返回nslookup程序。再输入命令:
   .cn MX preference = 20, mail exchanger = mx5.
   .cn MX preference = 10, mail exchanger = mta-v1.
这样的两个MX资源记录。此时的Iris截包如图:
当前的图示显示出的包是第二个报文,即从DNS回复过来的报文。第1个报文是查询报文,比回复报文简单多了。因此如果分析得懂回复报文,查询报文相信聪明如你一样可以轻松搞定。
图中显示的红色部分的数据为DNS报文包,上边的数据内容分别为MAC协义包、PPP协议包,IPv4协议包及UDP协议包。这些包不在本文范围内,不关注。
(插说一些废话:点选Iris左侧树中显示的条目,在右边的数据包中不一定正确反映,这点我一开始不知道,点中一个资源后按其错误的指示分析,分析了半天,也不知所言。我对包的分析是在此次写这个程序中学会的,以前大二时网络课没有好好去听我们学院那个少有的工程师兼教授的网络课,也怪我们系,咋不叫一个漂亮的MM过来教,那我会非常专心地听的:)。言归正传)
为了说明的方便,我把包中经色的DNS协议部分处理一下,如下图:
其中红色部分为包头,蓝色为查询部分,绿色为回复的第一条资源记录,金色为回复的第二条资源记录。其他的没有划起来的就权威记录、额外记录,不要分析考虑。
红色部分:
第0字节,第1字节 00 03 标识一个ID。
第2字节,第3字字 81 80 化成二进制形式 00 0000
QR(0)为1表示是回复报文。
Opcode(2-5)为0表示标准查询。
AA(6)为0表示非权威查询。
TC(7)为0表示不超过512字节的包不截断。
RD(8)为1表示nslookup程序指示DNS进行递归查询。
RA(9)为1表示DNS支持递归查询。
Z(10-12)保留字段
RCODE(13-16)为0表示查询无查错
第4字节,第5字节 00 01 表示查询的资源记录数为1
第6字节,第7字节 00 02 表示回复的资源记录数为2
第8字节,第9字节 00 06 表示权威的资源记录数为6
第10字节,第11字节 00 04 表示额外的资源记录数为4
接着到达了蓝色部分,查询的资源记录部分:
一开始是查询的域名。
开始 05 表示后边的五个字节是序列字符,把 79 61 68 6F 6F 转为ASCII码为yahoo
到达 03 表示后边的三个字节是序列字符,把 63 6F 6D 转为ASCII码为com
到达 02 表示后边的二个字节是序列字符,把 63 6E 转为ASCII码为cn
到达 00 表示结束。
整个串起来,用.连接,即为:.cn
接下来的两个字节 00 0F 表示查询类型为15,即为MX记录查询。
再接下来两个字节 00 01 表示查询类为1,即为Internet连接。
Iris包中的第一个包中的DNS报文只包含红线及蓝线,分析方法相同。不再赘述。
绿色部分,回复的第一个资源记录部分:
一开始为查询的域名,
首字节C0表示压缩,接下来的位为偏移字节位。
接下来是0C表示跳到整个包中的第12个字节上,即为蓝色的第一个字节。
然后接着与上边的分析相同,得到域名为.cn
然后返回,到下一个字节
绿色包中的3-4字节 00 0F 表示查询类型为15,即为MX记录查询。
再接下来的5-6字节 00 01 表示查询类为1,即为Internet连接。
再接下来的7-10字节 00 00 05 95 化为十进制等于1429秒。即缓存时间为23分49秒。
接着11-12字节 00 16 指示本资源记录的数据部分为22字节。即剩下来的字节数。
从13字节开始的22字节为MX记录的数据部分。此部分的格式为两字节的邮件交换器优先级值,不定长的邮件交换器名。
第13-14字节 00 14 表示优先级值为20
接着从15开始是邮件交换器名部分,依蓝色的域名分析方法,得到mx5.(此段所说字节均是绿色块中的相对位置,而非整个DNS包的绝对位置)
金色那块的方析方法与绿色的大同小异,但是有一点不同的是,看金色包的邮件交换器名部分。
从包的绝对位置,第78位(图中标紫色78的那里)开始是邮件交换器名。我们进行分析,得到mta-v1.b此时接下来是0XC0表示压缩,再接下来的偏移是0x0C又跳到包的12字节上,得到.cn。整个合起来就是第二资源记录的邮件交换器名:mta-v1.
这样的结果与nslookup运行结果:
   .cn MX preference = 20, mail exchanger = mx5.
   .cn MX preference = 10, mail exchanger = mta-v1.
希望此节能帮助网络爱好者学会包的分析方法。下边我们现行DNS中MX记录查询的编程要点分析。
四、DNS查询MX记录编程要点分析
Foxmail 5.0 的邮件特快专递有一个很垃圾的地方是无法自动获得本地ISP的DNS服务器,还需要用户的手工输入,我想是因为API的局限或是foxmail开发组没有想到方法或是其他的不为我知的缘故吧。不 管他,在C#中利用WMI,很容易的:
ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection moc = mc.GetInstances();
//枚举当前机子上的所有网卡
foreach(ManagementObject mo in moc)
if((bool)mo["ipEnabled"])
dnses = (string[]) mo["DNSServerSearchOrder"];
if (dnses!=null)
dnsServer=dnses[0]; //使用第一个找到的DNS服务器。
当然,您不会忘记在 项目-&添加引用 中加入对System.Management的引用吧?把这个放在DnsQuery类的静态构造函数中。 还有一个自定义的MxRecord结构,用于存放一个MX资源记录的信息。
struct MxRecord
//查询的域名
public QueryType queryT //查询类型
public QueryClass queryC //查询类
public TimeSpan liveT //生存时间
public int dataL //资源部分的长度,
//即指示邮件服务器的优先级及名称的那部分资源的字节数。
p //优先级值,其值越小越优先.
//邮件交换器名
把两个字节组成一个INT16型的整数无法用到BitConverter类,因为与DNS服务器的端位法不同。所以来是用 && 的方法进行位移。
其他的就不多说了,在程序的DnsQuery类中,我做了详细的代码注释,如果您有一些开发经验的话,应该很容易看得懂的,如果有疑问的话,欢迎联系我。我在精力及能力许可的范围内帮您解答。 
五、分析Foxmail的特快专递发送数据
1、运行ipconfig/all
把得到的Dns Servers的第一个IP地址记录下来。
2、还是运行Iris.设置Filters为SMTP,25端口。运行以便监听。
3、运行Foxmail5.0,在 工具 -& 系统设置 内的“邮件特快专递”标签页设定域名服务器1为刚刚的IP地址。
点“撰写”,用文本文件的格式编写。
主题:你好dreamchild,冒昧打饶
尊敬的dreamchild先生:
这是一封邮件。
附件:(添加 mm.gif 及 说明.txt 两个文件。为了保证此教程的完整性,把这两个额外的东东也放进包内了。)
4、完成后停止Iris,点其菜单栏的 Decode 得到以下内容:
220 Welcome to coremail System(With Anti-Spam) 2.1 for 263(040326)
HELO dreamchild
250 mta6.x263.net
MAIL FROM: &&
354 End data with .
Date: Thu, 9 Sep :35 +0800
From: "=?gb2312?B?w87Qobqi?=" &&
To: "dreamchild"
Subject: =?gb2312?B?xOO6w2RyZWFtY2hpbGSjrMOww8G08sjE?=
X-mailer: Foxmail 5.0 [cn]
Mime-Version: 1.0
Content-Type: multipart/
boundary="=====001_Dragon_====="
This is a multi-part message in MIME format.
--=====001_Dragon_=====
Content-Type: text/
charset="gb2312"
Content-Transfer-Encoding: base64
1/C+tLXEZHJlYW1jaGlsZM/Iyfqjug0KoaGhodXiysfSu7fi08q8/qGjDQo=
--=====001_Dragon_=====
Content-Type: image/
name="MM.GIF"
Content-Transfer-Encoding: base64
Content-Disposition:
filename="MM.GIF"
R0lGODlheAB4AIddABwNCixIjJtjkLO8iZux0NK
2xpVJT9XayJWNuDA0Vt5Xh+Sw7dLc7p6Fh3mD
(这边省略去关于一陀 MM.gif 文件内容的Base64编码)
w75UTdHFHwD/1Ex6cBSs0jHpKaySFXI4XCwAEhPkRsUSBQQAOw==
--=====001_Dragon_=====
Content-Type: application/octet-
name="=?gb2312?B?y7XD9y50eHQ=?="
Content-Transfer-Encoding: base64
Content-Disposition:
filename="=?gb2312?B?y7XD9y50eHQ=?="
1eK49k1Nv8mwrrK7v8mwrqGjDQo=
--=====001_Dragon_=====--
250 Ok: queued as 7CDA613A26E
这边涉及到的就是SMTP协议了,其中文版的RFC821文档参见: 
/data/rfc821.doc
因为是中文版的,所以大家花些时间看,这边就不再赘述原理了。只列出状态标识:
   211 系统状态或系统帮助响应
   214 帮助信息
   220 服务就绪
   221 服务关闭传输信道
   250 要求的邮件操作完成
   251 用户非本地,将转发向
   354 开始邮件输入,以.结束
   421 服务未就绪,关闭传输信道(当必须关闭时,此应答可以作为对任何命令的响应)
   450 要求的邮件操作未完成,邮箱不可用(例如,邮箱忙)
   451 放弃要求的操作;处理过程中出错
   452 系统存储不足,要求的操作未执行
   500 格式错误,命令不可识别(此错误也包括命令行过长)
   501 参数格式错误
   502 命令不可实现
   503 错误的命令序列
   504 命令参数不可实现
   550 要求的邮件操作未完成,邮箱不可用(例如,邮箱未找到,或不可访问)
   551 用户非本地,请尝试
   552 过量的存储分配,要求的操作未执行
   553 邮箱名不可用,要求的操作未执行(例如邮箱格式错误)
   554 操作失败&&&&&
可以从此看出,与一般的通过SMTP代理不同的是少了SMTP服务器的指定及其验证的用户名跟密码。
描述一下整个过程:
首先通过前述的方法得到263.net的一个邮件交换器,然后连到这个交换器上。然后连到此服务器的25端口上,服务器返回220。  
然后依次指示用户名,发送邮箱(人),接收邮箱(人)。接收写入邮件的数据。
数据分为邮件头及邮件的正文两部分。
邮件头包含:时间,发送邮箱(人),接收邮箱(人),主题,发信程序,MIME版本号,邮件内容的类型及分割符。
当中有一些用BASE64编码的字符串就是原来的中文汉字,其实,我们在制作无SMTP代理邮件发送程序时可以直接写成中文的。
这边就讲一下邮件内容的类型及分割符,其他的很容易理解的。
这边的邮件内容类型是 multipart/ 说明是由多种格式混合成的。
分隔符,是用于分隔邮件内容部分与各个附件。用boundary关键字及键值来定义。
比如本例用=====001_Dragon_=====来表示,这边有一个细节问题,键值最好要用"引起来,并不要出现空格。举个例子,如果你用boundary======001_Dragon_=====来表示的话,那FOXMAIl5.0将无法正确对邮件进行处理,邮件的内容部分被当成整个BASE64乱码文本,然而我登陆到263.net的网站去收信可以看到邮件被正常转化。
而邮件的内容部分是通过两个减号--再连上分隔符来分隔各部分的。
邮件主体从第一个--=====001_Dragon_=====开始,到第二个-
=====001_Dragon_=====为内容的第一部分
Content-Type: text/
charset="gb2312" Content-Transfer-Encoding: base64
这两句说明了其类型及内容的字符集和编码。
在这边是指定的是base64,然后一个空行,再加上“尊敬的dreamchild先生:\r\n    这是一封邮件。”这个字符串的BASE64编码构成邮件的正文部分。
实际上,我们可以指定 Content-Transfer-Encoding:8bit然后就可以在正文部分用上原本表示了。
接下来是隔开的附件1部分,多了一个Content-Disposition:以说明这部分是附件,以及相关的文件名filename="MM.GIF"。
附件内容部分是把文件读成一个字节数组,然后把字节数组转为base64编码的字符串。这边的是mm.gif这个文件内容。
第三部分是附件2 测试.txt 文件,测试.txt 又被foxmail处理成base64格式了,可以用原文表示的。
最后完了之后,用“回车换行加一个.号再一个回车换行”表示Data部分的结束。
如若正确过发送到达服务器,那就返回一个250状态。
然后用Quit命令跟服务器3166
六、邮件发送程序编程要点分析
我们先定义一个邮件结构,以描述邮件的各个属性。
public struct MailContent //邮件的内容
//收件人地址
//收件人姓名
//发件人地址
pu//发件人姓名
//文本内容
public bool useA //是否使用附件
public string [] attachmentL //附件列表
接着从各控件中取值,赋给这个结构的实例。其中取值过程中包括判断邮箱格式是否正确,我们用正则表达式来判断。如下:
Regex.IsMatch(邮箱字符串, @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$")
如果返回的值为假的话,就用错误提示器提示。赋值完后,就开创一个工作线程进行邮件的发送。线程一开始先通过当地DNS取得邮箱域名部分的邮件交换器列表。然后取得其最小优先级值的交换器用于以后的发送。 比如取得这个邮箱的域名263.net的一个优先级值为10的MX记录mx12.263.net,然后就是连到服务器发送命令及接收返回信息。以下列出一些代码:
关于创建Sock套接字:
TcpClient sock = new TcpClient();
NetworkStream netS
sock.NoDelay = //不使用延时算法,以加快小数据包的发送。
sock.ReceiveTimeout = 10000; //接收超时为10秒。
sock.Connect(server,port);
netStream = sock.GetStream();
Socket的Nagle算法将降低小数据报的发送速度,而系统默认是使用Nagle算法。所以设置NoDelay为true关掉它,以加快小数据的发送。
关于Send方法:
byte [] sendArray = Encoding.Default.GetBytes(sendString);
netStream.Write(sendArray,0,sendArray.Length);
先把字符串转为字节数组再发送出去
关于Receive方法:
const int MaxReceiveSize = 1460;
byte [] buffer=new byte[MaxReceiveSize];
length = netStream.Read(buffer, 0, MaxReceiveSize);
if (length == 0)
receiveString = Encoding.Default.GetString(buffer, 0, length);
根据“在SOCK_STREAM方式下,如果单次发送数据超过1460,系统将分成多个数据报传送,在对方接受到的将是一个数据流,应用程序需要增加断帧的判断。当然可以采用修改注册表的方式改变1460的大小,但MicrcoSoft认为1460是最佳效率的参数,不建议修改。”
这边设置一次接收1460字节,但其实返回码用不了这么多字节,这个是以前我在写基于HTTP网络程序时写的接收函数一部分,保留了这个方法。接收到后就再转回字符串返回。
send = "Date: {$time}\r\n"
+ "From: {$fromname} &{$from}&\r\n"
+ "To: {$toname} &{$to}&\r\n"
+ "Subject: {$title}\r\n"
+ "X-mailer: NoSmtpSender [蔡晓晖 制作]\r\n"
+ "MIME_Version:1.0\r\n"
+ "Content-type:multipart/Boundary=\"{$splitline}\"\r\n"
+ "\r\n" //头部结束,开始正文部分。
+ "--{$splitline}\r\n" //内容部分。
+ "Content-type:text/Charset=gb2312\r\n"
+ "Content-Transfer-Encoding:8bit\r\n"
+ "{$body}\r\n"
attachment = "";
attachment += "--{$splitline}\r\n";
attachment += "Content-Type:application/octet-Name={$filename}\r\n";
attachment += "Content-Disposition:FileName={$filename}\r\n";
attachment += "Content-Transfer-Encoding:Base64\r\n";
attachment += "\r\n";
//先进行替换,以防加上附件内容后替换耗时。
attachment = attachment.Replace("{$splitline}",splitLine);
attachment = attachment.Replace("{$filename}",file.Name);
attachment += Convert.ToBase64String(fileBytes,0,length);
attachment += "\r\n\r\n";
按上一节的分析,把格式给列出来,然后依次替换{$变量名}就OK了,其中time变量名的获得方法:
   DateTime.Now.ToString("R").Replace("GMT","中国标准时间")
我不知道是不是VS2003的BUG,用"R"参数输出当前时间的RFC格式的格林威治时间,没有把本土化时间自动转换,比如现在的中国时间9点,它没有减去8小时。而只是直接在当前时间后边加上 GMT”。于是我们就把“GMT”改“中国标准时间”了以校时。
按一问一答的方式与邮件交换器“交流”,如果其间有错的话,就把错误的信息保存下来,然后 如果整个发送过程没有错的话就可以:
   netStream.Close();
   sock.Close();
程序的界面截图:
七、最后的话
非常感谢您很有耐心地看完我的啰嗦。我花了四个通宵(其实是早上睡觉)时间编写软件及教程的辛苦值得了。这份软件算我暑假学习半个月C#后的一份比较好的成品吧。我是从大二开始学习真正的编程,用了九个月的VB及写了一年又三个月的C++/MFC程序。现在在学C#。感觉有C++的基础入门C#挺容易的。
本文件的邮件附件的发送方法参照罗前辈()的C++源码,不然可能又要多发上一天去思考了。在此感谢罗老师的无私。
写完这个东东后,再过四天,我的暑假就结束了,下个学期是大四了。很迷惘的一个学年,我想在毕业后能到上海找到一份好工作。我想请业内的前辈指引我一下,以我现在的水平要跨过上海大软件公司的门槛还要爬多高?我在这剩下一年内会更加努力去超越的
您可以任意地传播本软件、源码及相关文档,但请保留完整性。
如若用于商业用途需经我的同意。
我的联系方式:
通讯地址:漳州师范学院082信箱(363000)
姓名:蔡晓晖
希望我们能交个朋友。
如果一年内有问题需要我解答的话,请到上的【信息技术】版块发贴询问。
我会在精力及能力许可范围内帮您解答的。
Programmed by 蔡晓晖
最多还可以输入100字
【VIP年会员制套餐】
【C/C++软件工程师实战能力集训大纲】
VC知识库发布了C/C++业界的“本草纲目”
【牛人都在千人一号群! 加群三步走!!!】
第一步:请必须加VC知识库QQ: 为好友;
第二步:请必须关注本站微博:
第三步:申请加入群:.(必须将关注微博截屏发到QQ方可通过!)
【最新2013:】
全部100% VC++源码提供: E-Form++全新大型SCADA & HMI解决方案源码、CAD解决方案源码、Gis解决方案源码 、电力石油化工仿真与图形建模解决方案源码、大量其他高级制图VC++源码下载!
【 新视频发布】
o o o o o o o o o o
在VC环境中除了我们所常用的Dialog、Menu和Bitmap等标准资源类型之外,它还支持自定义资源类型(Custom Resource),我们自定义的资源类型能做些什么呢?呵呵,用处多多。...
在VC环境中除了我们所常用的Dialog、Menu和Bitmap等标准资源类型之外,它还支持自定义资源类型(Custom Resource),我们自定义的资源类型能做些什么呢?呵呵,用处多多。...
本文介绍了套接字编程的基本知识。...

我要回帖

更多关于 plc与仪表通信 的文章

 

随机推荐