C# 委托知识总结

如果你足够强大,你就不会把幸福押在别人身上,你会自己创造幸福或者给别人带来幸福。而变得强大的途径就是学习,就是读书,学一切东西,读任何想读的书。 爱你让我变得更强。。 继续读一些专业文章了。不保证都是原创,但是保证每篇技术文章的质量。也会注明来源,标准就是浅显易懂。但不简单。 原文来自:贺臣感谢原作者的好文章。 1.什么是委托,为什么要使用委托 我正在埋头苦写程序,突然想喝水,但是又不想自己去掉杯水而打断自己的思路,于是我就想让女朋友去给我倒水。她去给我倒水,首先我得让她知道我想让她干什么,通知她之后我可以继续写自己的程序,而倒水的工作就交给了她。这样的过程就相当于一个委托。 在程序过程中,当程序正在处理某个事件的时候,我需要另外的程序代码去辅助处理一些事情,于是委托另一个程序模块去处理,而委托就可以达到这种目的,我可以利用委托通知另外的程序模块,该去调用哪个函数方法。委托其实就起到了这样一个作用,将函数签名传递到了另一个函数中。或许这样讲还是有些模糊,看看后面的具体实例。 2.委托的定义 delegate int Add(int num1,int num2); delegate void ConvertNum(string result); 上面是定义两个委托的例子,其实很简单。声明一个委托使用delegate关键字,上面分别是定义的带返回值的委托和不带返回值的委托, 两个委托都有传递参数,当然也可以不传递参数。其实委托也是一个类,委托派生为System.MulticastDelegate,而System.MulticastDelegate 又继承System.Delegate,如果你知道这个也就明白委托其实是一个特殊的类。 委托的简单实用例子 public delegate string TeaDelegate(string spText); public class DelegateSource { public void TestDelegate() { Operator op = new Operator(); TeaDelegate tea = new TeaDelegate(op.GetTea); Console.WriteLine("去给我倒杯水"); Console.WriteLine(); string result=tea("去给我倒杯水"); Thread.Sleep(5000); Console.WriteLine(result); Console.WriteLine(); } } public class Operator { /// /// 确定是否还有水 /// private bool flag = true; public string GetTea(string spText) { if (spText == "去给我倒杯水") { if (flag) { return "老公,茶来了"; } else { return "老公,没有水了"; } } return "等待......."; } } 输出结果 上面使用最普通的一种方式来定义了一个委托的使用,这个例子虽然很简单,但是能够很形象的描述委托的使用。 3.委托的三种形式 (1).推断 推断委托例子 public delegate string TeaDelegate(string spText); public class DelegateSource { public void TestDelegate() { Operator op = new Operator(); TeaDelegate tea = op.GetTea; Console.WriteLine("去给我倒杯水"); Console.WriteLine(); string result=tea("去给我倒杯水"); Thread.Sleep(5000); Console.WriteLine(result); Console.WriteLine(); } } public class Operator { /// /// 确定是否还有水 /// private bool flag = true; public string GetTea(string spText) { if (spText == "去给我倒杯水") { if (flag) { return "老公,茶来了"; } else { return "老公,没有水了"; } } return "等待......."; } } 在委托定义的例子中我们看到委托的使用方法是在委托实例化的时候指定的[new DelegateName(FunctionName)],这里可能表述不是太但是代码应该看得白了。 而委托的推断,并没有new 委托这个步骤,而是直接将Function 指定给委托。 ...

2012-09-16 · 4 min · bystander

WCF读书笔记(2)

信道形状(Channel Shape) 用来表述不同的消息交换模式对消息交换双方信道(信息交换的管道)的不同要求,有什么IOutputChannel IReplyChannel IDuplexChannel之类的。。 对于IReplyChannel,服务器返回一个RequestContext类型,作为请求和回复之间的一道桥梁,可以获取也可以返回消息。 会话信道(Session Channel) 从状态保持的角度,信道可以分为两种类型,Datagram Channel和Session Channel,前者不和客户端绑定,后者可以识别客户端。 对于WCF的信道层来说,信道管理器在客户端和服务端扮演不同的角色。服务端的信道管理器用于监听来自客户端的请求,而客户端的信道仅仅是单纯创建用于请求发送和回复接收的信道,因此服务端的消息管理器又称为信道监听器(Channel Listener),客户端的信道管理器则称之为信道工厂(Channel Factory) 绑定元素(Binding Element) 构成一个绑定对象的元素,绑定实现了通信的所有细节,通过创建信道栈实现对消息的交换,系统绑定是指服务于某种类型场景的绑定元素的有序集合。 包括什么BaseHttpBinding之类的。 一个程序集包括元数据,中间语言代码,和资源。程序集已经加载,将一直保存在内存中,直到应用程序域卸载。最好摒弃添加服务引用的服务调用方式,而是直接将包含服务契约的程序集部署到客户端。客户端以直接创建代理的方式进行调用。 WCF可以看成是适配器,是CLR类型和XML两个不同世界的纽带。 依赖倒置原则:即抽象不应该依赖细节,细节应该依赖于抽象;即要针对接口编程,不要对实现编程。高层模块不应该依赖低层模块。两个都应该依赖抽象。 契约关心的是我能做到。而不在于我如何做到。 封送(Marshaling) 解决跨应用程序域对象访问的问题,需要采用一种特别的机制,那就是封送。分为按值封送和按引用封送 按值封送实现了跨应用程序域的数据共享 按引用封送则实现了跨应用程序域的远程调用。 如果一个程序员频繁的使用复制粘贴编程。那就意味着设计需要重构

2012-09-06 · 1 min · bystander

使用Microsoft Web Deploy技术自动部署

 在前段时间使用WCF的时候。部署到服务器上一直不得要领。出现各种问题。最终搞定。原文图很多,我给个摘要,大家还是原文看。因为原文写于2010年。自动部署工具已经更新至第3版。所以有些按钮得好好找找。不过相信对大家都不是难事。 本篇文章将提供一个循序渐进的教程,教你如何在一台Web服务期上安装和启用Web Deploy。接着我们演示如何使用Visual Studio通过Web Deploy直接(将文件)发布到服务器上,以及如何使用Visual Studio创建自动部署你的应用程序的安装包。 Web Deploy—为什么你会喜欢它 部署一个Web应用程序或站点包含好几个步骤。您通常需要: 1. 拷贝文件和文件夹; 2. 提供数据库结构,或许还要生成一些数据库数据; 3. 在文件和文件夹上设置相应的读写和安全访问控制列表; 4. 安装和配置SSL认证; 5. 部署其它杂七杂八的依赖项(事件日志,GAC库,COM对象等等)。 手工执行上面的步骤又累又慢又危险(因为手工部署总是容易出错)。使用自动化流程,可以让你在一台服务器上快速维护和部署应用程序,减少出错的几率,并极大加快你在应用程序上的改动放到作业服务器上的周期。 去原文看看吧。使用Microsoft Web Deploy技术自动部署

2012-09-04 · 1 min · bystander

SQLServer启用xp_cmdshell

忘了当时是执行哪条命令的时候需要启动xp_cmdshell了。。反正是必须用的。。 默认情况下,sql server安装完后,xp_cmdshell是禁用的(可能是安全考虑),如果要使用它,可按以下步骤 -- 允许配置高级选项 EXEC sp_configure 'show advanced options', 1 GO -- 重新配置 RECONFIGURE GO -- 启用xp_cmdshell EXEC sp_configure 'xp_cmdshell', 1 GO --重新配置 RECONFIGURE GO --执行想要的xp_cmdshell语句 Exec xp_cmdshell 'query user' GO --用完后,要记得将xp_cmdshell禁用(出于安全考虑) -- 允许配置高级选项 EXEC sp_configure 'show advanced options', 1 GO -- 重新配置 RECONFIGURE GO -- 禁用xp_cmdshell EXEC sp_configure 'xp_cmdshell', 0 GO --重新配置 RECONFIGURE GO

2012-07-11 · 1 min · bystander

C# 线程优秀文章汇总

最近在看线程的东西,整理一些文档以便学习。分享。 刚刚 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操纵一个线程 C#多线程学习(三) 生产者和消费者 C#多线程学习(四) 多线程的自动管理(线程池) C#多线程学习(五) 多线程的自动管理(定时器) C#多线程学习(六) 互斥对象 C# 实现多线程的同步方法详解 JimmyZheng C# 温故而知新: 线程篇(一) Thread C# 温故而知新: 线程篇(二) 线程池和异步线程 zhoufoxcn C#多线程编程(1):线程的启动 多线程编程(2):线程的同步 多线程编程(3):线程池ThreadPool 多线程编程(4):多线程与UI操作 一个简单的C#多线程间同步的例子 老赵 浅谈线程池(上):线程池的作用及CLR线程池 浅谈线程池(中):独立线程池的作用及IO线程池 浅谈线程池(下):相关试验及注意事项 bloodish C# Tip – 如何优雅的控制线程状态 Autumoon 白话多线程

2012-07-11 · 1 min · bystander

《Effective C#》Item 9:区别和认识四个判等函数

 .Net有四个判等函数?不少人看到这个标题,会对此感到怀疑。事实上确是如此,.Net提供了ReferenceEquals、静态Equals,具体类型的Equals以及==操作符这四个判等函数。但是这四个函数之间有细微的关系,改变其中一个函数的实现会影响到其他函数的操作结果。 首先要说的是Object.ReferenceEquals和Object.Equals这两个静态函数,对于它们俩来说,是不需要进行重写的,因为它们已经完成它们所要得做的操作。 对于Object.ReferenceEquals这个静态函数,函数形式如下: public static bool ReferenceEquals( object left, object right ); 这个函数就是判断两个引用类型对象是否指向同一个地址。有此说明后,就确定了它的使用范围,即只能对于引用类型操作。那么对于任何值类型数据操作,即使是与自身的判别,都会返回false。这主要因为在调用此函数的时候,值类型数据要进行装箱操作,也就是对于如下的形式来说。 int n = 10; Object.ReferenceEquals( n, n ); 这是因为对于n这个数据装箱两次,而每次装箱后的地址有不同,而造成Object.ReferenceEquals( n, n )的结果永远为false。 对于第一个判等函数来说,没有什么好扩展的,因为本身已经很好地完成了它所要做的。 对于第二个Object.Equals这个静态函数,其形式如下: public static bool Equals( object left, object right ); 按照书中对它的分析,其大致函数代码如下: public static void Equals( object left, object right ) { // Check object identity if( left == right ) return true; // both null references handled above if( ( left == null ) || ( right == null ) ) return false; return left.Equals( right ); } 可以说,Object.Equals这个函数完成判等操作,需要经过三个步骤, 第一步是需要根据对象所属类型的==操作符的执行结果; 第二步是判别是否为null,也是和第一步一样,需要根据类型的==操作符的执行结果; 最后一步要使用到类型的Equals函数的执行结果。 也就是说这个静态函数的返回结果,要取决于后面要提到的两个判等函数。类型是否提供相应的判等函数,成为这个函数返回结果的重要因素。 那么对于Object.Equals这个静态方法来说,虽说接受参数的类型也属于引用类型,但是不同于Object.ReferenceEquals函数,对于如下的代码,能得出正确的结果。 int n = 10; Debug.WriteLine( string.Format( "{0}", Object.Equals( n, n ) ) ); Debug.WriteLine( string.Format( "{0}", Object.Equals( n, 10 ) ) ); 这是因为在此函数中要用到具体类型的两个判等函数,不过就函数本身而言,该做的判断都做了,因此不需要去重载添加复杂的操作。 为了更好的述说剩下两个函数,先解释一下等价的意义。对于等价的意义,就是自反、对称以及传递。 所谓自反,即a == a; 而对称,是a == b,则b == a; 传递是 a == b,b == c,则 a == c; 理解等价的意义后,那么在实现类型的判等函数也要满足这个等价规则。 对于可以重载的两个判等函数,首先来介绍的是类型的Equals函数,其大致形式如下: public override bool Equals( object right ); 那么对于一个类型的Equals要做些什么操作呢,一般来说大致如下: public class KeyData { private int nData; public int Data { get{ return nData;} set{ nData = value; } } public override bool Equals( object right ) { //Check null if( right == null ) return false; //check reference equality if( object.ReferenceEquals( this, right ) ) return true; //check type if( this.GetType() != right.GetType() ) return false; //convert to current type KeyData rightASKeyData = right as KeyData; //check members value return this.Data == rightASKeyData.Data; } } ...

2012-07-05 · 2 min · bystander

各种内存卡介绍

闪存卡(Flash Card)是利用闪存(Flash Memory)技术达到存储电子信息的存储器,一般应用在数码相机,掌上电脑,MP3等小型数码产品中作为存储介质,所以样子小巧,有如一张卡片,所以称之为闪存卡。 根据不同的生产厂商和不同的应用,闪存卡大概有Compact Flash(CF卡)、MultiMediaCard(MMC卡)、Secure Digital(SD卡)、Memory Stick(记忆棒)等。 SD卡 SD卡全称为Secure Digital卡,SD卡标准的面世相对而言比CF要晚,根据MMC为基础所开发的Secure Digital(SD),其改进主要是在增添了版权保护的功能,提高了传输速度和增加了写保护机制等,其主要引脚的定义与MMC卡并没有太大的区别。SD具有较高的兼容性,较小的体积和不错的数据传输速度,成为了当今的时尚数码相机和部分可拍照手机的标准配置。SD接口是当今世界上被采用得最多的闪存卡接口,市面上主流的PDA,数码相机,MP3的闪存卡,烧录卡接口大多为SD卡,也使SD卡取代了CF卡成为了当今最常见得存储卡。如图: MiniSD MiniSD是SD卡的一大改进,体积只有21.5x20x1.4mm,比普通SD卡足足节省了60%的空间,通过转接卡还能保证MiniSD在正常的SD插槽上的使用。如图: Micro SD(TF卡) TF卡又称T-Flash卡,也叫Micro SD卡,体积只有11×15×1mm,面积为MiniSD的一半 MMC卡 MMC卡全称为Multi Media Card,由SanDisk与Siemens AG/InfineonTechnologies AG所联合开发,且于1997年11月发表,Size:24mm x 32mm x 1.4mm,重量2g。MMC卡的兼容性方面不及SD卡的好,数据传输速度受到硬件的限制,不适合作高速的数据传输。如图: RSMMC RSMMC是Reduced-Size MMC的缩写,小型化的MMC卡,传说专门为智能手机设置。改良后的产品叫做MMCmobile 什么是CF卡? CF格式由来已久,被SanDisk公司在1994年首次制造出来。CF卡的全称是Compact Flash,Compact意指“小型的,轻便的”,CF大小为43mm x 36mm x 3.3mm,50 Pins。如图 MS卡 Memory Stick,索尼推出的存储产品。貌似是独树一帜,不多介绍。 参考: http://www.allmemorycards.com/sd.htm http://baike.baidu.com/view/26952.htm http://nds.cngba.com/nds_bd/2007122122100.shtml

2012-06-30 · 1 min · bystander

对不起,我等不了你了

 这不是我写的,这篇文章也不是讲爱情的,来自XuTuo的方式,大学生活。人生理想。不错的文章。收藏分享之。 很多事很多人你觉得对你很重要,会在你的一生中留下不可磨灭的印记,却总在你的渐行渐远中云淡风轻。 大一的时候不写高考,因为年少轻狂中带有那么点不可一世的自尊心。大三的时候写不出高考,因为想再提起时已经变成愈加模糊与苍白,甚至还有点可笑。那时候的你已经开始忙着考研或者找工作,忙着褪去象牙塔里那张不老的脸,忙着一个人或者两个人的未来。 后来觉得有必要在这个稚嫩的末尾画上一个走向成熟的句号,在夏天还没到来的时候。 两年前你迷茫着要走上那条路,两年后你迷茫着这条路会走向哪里。 学生生涯是一个很美好的时刻,当然这种美好往往得等失去了才知道珍惜。就像记忆中的高中班主任总是苦口婆心地告诉我们,拼一拼,过了这一个月,你们就解放了。年幼的人有种向往年长人的生活的冲动,这种原始的冲动就像小时候注册QQ的时候总喜欢把年龄放大到十八岁,好像花季雨季里总会有那么些纯纯的爱恋等着我们。而直到了那个季节才发现原来小说里都是骗人的,这里除了长个不停的青春痘还有做不完的作业与考不完的试,爱情是战乱里的奢侈品,珍贵且易碎。 一群刚考完试的高考生们疯狂地撕掉课本,然后撒向天空大吼说:“我终于解放了!”接下去的几天里他们不停地聚会,不停地唱K,不停地喝酒,不停地网路短信暧昧,然后接下来是高中“革命一辈”的“生离死别”。 说着一生一世的誓言走上两条反方向的路,我喜欢那个时候忽明忽暗的爱恋,喜欢就是喜欢,不喜欢就是不喜欢,表白的那个男生可能以后会考上一所名牌大学,毕业后能当上国家公务员,家里供有着一套以及一套以上的房子让他结婚。但不喜欢就是不喜欢,因为他胖,他油性皮肤,他的校服一个礼拜都没洗,还有,他的字不好看。 接着他们如愿以偿地上了老师口中的“由你玩四年”。这是一个很不负责任的谎言,并且被我们尊重的老师屡用不止,就好像你在吃一根玉米,你啃到第三排的时候已经吃不下了,然后一个人告诉你说越往后越好吃,逼你不得不继续往下吃,然而你却逐渐感到反胃,旁边的人说一开始不习惯,慢慢地就会好了,你相信了,硬着头皮往下吃,直到吃完最后一颗时你才发现这根玉米原来压根就烂了,你吐了三天拉了三天后却忘记了自己当初吃玉米的缘由,只剩下一堆无尽的怨言。 银行卡里的生活费准时的打来,人民币上毛爷爷微笑的脸使你渐渐淡忘了家中父母的样貌,你终于有了支配财富的能力以满足你的愿望,这像是一种迟来的报复般让你有种快感,然而当这种权利到手时你却感到一种迷茫与不真实。小时候的你一直暗下决心说等长大了有钱了就要买一大堆零食,结果现在如愿了,但面对超市柜台前满满的零食,你却如何也抬不起兴趣。 生活像是一场黑色幽默的电影,越往后越是笑得想哭出来。 周围的同学渐渐都恋爱了,有几对是新结连理,有几对则是异地的革命伉俪。你开始也心动了,心猿意马地看着校道上那一双双白花花的大腿,你的下半身逐渐代替了上半身的思考能力,你只是不想一个人过了,这样的生活让你感到孤单,无趣,甚至还有那么一点的自卑。高中时你曾经喜欢过一个女生,每当她走过你们班级的窗前你的心跳都会加速得快要蹦出来,那种奇妙的感觉让你喜欢着又害怕着,她就像你心目中的女神一样。那天晚上你终于下了好大的决心发了条短信给她,“在干吗?”“没啊,你呢?”你们有一搭没一搭地聊到了深夜却都心照不宣地不捅破内心的青春情怀。暧昧总是美好的,你以前老是不懂什么叫“人生若只如初见。”现在你渐渐懂了,以后你会更懂。 大学的爱情却让你逐渐感到些许恶心与廉价,前些天你看上一个不错的女生,找了人打听到了她的电话号码,头一句便问她:“你有男朋友吗?”她说,有。之后你便不再回复了。你开始忙了起来,因为你必须马不停蹄地找到下一个猎物。什么时候你失去了等待和耐心爱一个人的能力,你说不上来,在行色匆匆中搪塞着,晚了就找不到对象了。 大学的第一个新年里几个同学在老师家聚会,大家寒暄着暖场,讲着那个陌生地域的生活,有人说得眉飞色舞,有人说得黯然神伤,但却没有人知道明天会怎样。 父母们不再会催你赶紧读书了,你终于有了足够的时间玩游戏,看电视。无论你做什么他们都会一脸慈爱地看着你,有时甚至你自己都过意不去,你觉得是不是他们还会像以前帮你报个补习班或者训练营,结果没有。他们只是老了,累了,你终于考上了他们曾经仰望着的大学,他们感到很欣慰,惟愿你一切安好。 大学却依然在继续着,高考后的第二个夏天来临时你开始有些许羡慕地看着那群刚刚高考完的准大学生们,你听他们喊着你喊过的口号,过着你过过的生活,经历着你的曾经。你喜欢他们那种充满希望的眼神里闪烁着的光,只是你的眼角边不知什么时候多了条皱纹。 你开始得打算自己要往哪个方向发展了,这一年里你旷了将近四分之一的课,每天睡了有十个小时的觉,你交了两个女友,却还不到三个月的时间,到了大一结束的时候你才勉强能念出自己专业的全名,却仍不知道这个专业到底教的是什么。父母们常在你耳边旁敲侧击地说着一些称之为“现实”事情,比如谁谁家的女儿嫁了个好人家,谁谁家的孩子考上公务员后待遇很好。你烦了,爹妈不高兴了,他们会说你已经二十岁了,你则说你的事自己会处理好,但事实上你却依旧迷茫:未来在哪里? 跨入大二前你曾暗下决心要好好学习,就如打仗前的誓师般悲壮。然而在坚持了两个礼拜后却又开始了之前的生活循环,在新的一年里的慢慢发现了身边的人慢慢变了,有的人依旧每天叫上你一起去喝酒玩乐,有的人则一早上就出去,直到晚上才回来,他抱着书,你抱着酒瓶。你们的生活从这里开始分离开来,多年之后你会后悔,但却忘了当初是谁拿起那把剪子分道扬镳。 大二的那个圣诞节里你度过了大学的第三次失恋,你听了一天的《圣诞结》并骂着甩你的女生现实,势力。然而你的舍友却在同一天表白成功了,他和你一样,没有背景,没有一个可以拼的爹,你们曾经在同一条起跑线上,然后现在却互相看不到彼此的身影。你在网上刷了一天的微博看到了那么一句话:“永远不要低估一个女生和你同甘共苦的决心。”你冷冷一笑,关了电脑,却没看到下本句写的:“一个女生最怕的,是在你身上看不到希望。” 大二上学期的春节来临时父母还为你的回来准备着大鱼大肉,貌似什么都没变,但貌似什么都变了一点,就像你的压岁钱不知怎么就少了,几个小外甥甚至还嚷着:“舅舅,给我红包!” 过了这个年你戏谑着自己走在奔三的路上,在回学校的时候父母到车站送你,你突然发现他们的脚步什么时候变慢了,你已经走了好远他们怎么都跟不上,那一刻你突然感到一种前所未有的孤独,就好像曾经可以依靠的肩膀都不在了。 这个春天你觉得怎么过得那么快,你说你已经不打游戏了,不打牌了,也不常和朋友出去玩了,你说你制定了一个计划,但为什么日子还是过得那么快,白天转眼就是黑夜。 就像又到了一年的高考时。 我等不了你了,少年。

2012-06-27 · 1 min · bystander

c#温故而知新: 线程篇

上次的C#温故而知新:Stream篇 已经完结了,这次,JimmyZheng 开始更新线程了,转发收藏,持续更新,当然你也可以直接去看JimmyZheng的文章,欢迎学习交流 c#温故而知新: 线程篇(一):Thread c#温故而知新: 线程篇(二):线程池和异步线程

2012-06-24 · 1 min · bystander

GET和POST有什么区别?及为什么网上的多数答案都是错的。

今天突然看到很多好的技术文章,转载收藏备用分享。 如果有人问你,GET和POST,有什么区别?你会如何回答? 我的经历 前几天有人问我这个问题。我说GET是用于获取数据的,POST,一般用于将数据发给服务器之用。 这个答案好像并不是他想要的。于是他继续追问有没有别的区别?我说这就是个名字而已,如果服务器支持,他完全可以把GET改个名字叫GET2。他反问道,那就是单纯的名字上的区别喽?我想了想,我觉得如果说再具体的区别,只能去看RFC文档了,还要取决于服务器(指Apache,IIS****)的具体实现。但我不得不承认,我的确没有仔细看过HTTP的RFC文档。于是我说,我对HTTP协议不太熟悉。这个问题也就结束了。 最普遍的答案 回来之后寻思了很久,他到底是想问我什么?我一直就觉得GET和POST没有什么除了语义之外的区别,自打我开始学习Web编程开始就是这么理解的。 可能很多人都已经猜到了,他要的答案是: 1. GET使用URL或Cookie传参。而POST将数据放在BODY中。 2. GET的URL会有长度上的限制,则POST的数据则可以非常大。 3. POST比GET安全,因为数据在地址栏上不可见。 但是很不幸,**这些区别全是错误的,**更不幸的是,这个答案还是Google搜索的头版头条,然而我根本没想着这些是答案,因为在我看来他们都是错的。我来一一解释一下。 GET和POST与数据如何传递没有关系 GET和POST是由HTTP协议定义的。在HTTP协议中,Method和Data(URL, Body, Header)是正交的两个概念,也就是说,使用哪个Method与应用层的数据如何传输是没有相互关系的。 HTTP没有要求,如果Method是POST数据就要放在BODY中。也没有要求,如果Method是GET,数据(参数)就一定要放在URL中而不能放在BODY中。 那么,网上流传甚广的这个说法是从何而来的呢?我在HTML标准中,找到了相似的描述。这和网上流传的说法一致。但是这只是HTML标准对HTTP协议的用法的约定。怎么能当成GET和POST的区别呢? 而且,现代的Web Server都是支持GET中包含BODY这样的请求。虽然这种请求不可能从浏览器发出,但是现在的Web Server又不是只给浏览器用,已经完全地超出了HTML服务器的范畴了。 知道这个有什么用?我不想解释了,有时候就得自己痛一次才记得住。 HTTP协议对GET和POST都没有对长度的限制 HTTP协议明确地指出了,HTTP头和Body都没有长度的要求。而对于URL长度上的限制,有两方面的原因造成: 1. 浏览器。据说早期的浏览器会对URL长度做限制。据说IE对URL长度会限制在2048个字符内(流传很广,而且无数同事都表示认同)。但我自己试了一下,我构造了90K的URL通过IE9访问live.com,是正常的。网上的东西,哪怕是Wikipedia上的,也不能信。 2. 服务器。URL长了,对服务器处理也是一种负担。原本一个会话就没有多少数据,现在如果有人恶意地构造几个几M大小的URL,并不停地访问你的服务器。服务器的最大并发数显然会下降。另一种攻击方式是,把告诉服务器Content-Length是一个很大的数,然后只给服务器发一点儿数据,嘿嘿,服务器你就傻等着去吧。哪怕你有超时设置,这种故意的次次访问超时也能让服务器吃不了兜着走。有鉴于此,多数服务器出于安全啦、稳定啦方面的考虑,会给URL长度加限制。但是这个限制是针对所有HTTP请求的,与GET、POST没有关系。 安全不安全和GET、POST没有关系 我觉得这真是中国特色。我讲个小段子,大家应该可以体会出这个说法多么的可笑。 觉得POST数据比GET数据安全的人会说 _ “防君子不防小人;中国小白多,能防小白用户就行了。”_ _ “哼,”我不以为然,“那你怎么不说,_URL__参数都Encode__过了,或是Base64__一下,小白也看不懂啊。” 那人反驳道,_“_Encode__太简单了,聪明点儿的小白很容易就可以Decode__并修改掉。” 我笑道,_“五十步笑百步耳,再聪明点儿的小白还会截包并重发呢,_Opera__就有这功能。” 那人阴险地祭出神器——最终解释权,说,“这个不算小白。” 我日啊。 最后一点儿感想 我之前一直做Windows桌面应用,对Web开发无甚了解,直到一年多前转做服务器端开发,才开始接触到HTTP。(注意,我说的是HTTP,不是HTML。服务器开放接口是基于REST理念设计的,使用的协议是HTTP,但是传输的内容不是HTML。这不是Web Server,而是一个Web Service) 所以我对于GET和POST的理解,是纯粹地来源于HTTP协议。他们只有一点根本区别,简单点儿说,一个用于获取数据,一个用于修改数据。具体的请参考RFC文档。 如果一个人一开始就做Web开发,很可能把HTML对HTTP协议的使用方式,当成HTTP协议的唯一的合理使用方式。从而犯了以偏概全的错误。 可能有人会觉得我钻牛角尖。我只是不喜欢模棱两可,不喜欢边界不清、概念不明,不喜欢“拿来主义”,也不喜欢被其它喜欢钻牛角尖的人奚落得无地自容。 “知之为知之,不知为不知,是知也。” 原文链接:http://www.cnblogs.com/nankezhishi/archive/2012/06/09/2542968.html

2012-06-19 · 1 min · bystander