快速业务通道

自己写个IIS玩-协议解析篇

作者 佚名技术 来源 NET编程 浏览 发布时间 2012-05-20

这里不是说用System.Web.Hosting.ApplicationHost和System.Net.HttpListener做的那种web server ,而是直接用socket api做一个简单的能收发HTTP包的网络服务器,当然也不会完全实现RFC 2616,主要 学习探索用。

我们先来看HTTP协议解析部分,做一个HTTP协议栈-HttpStatck,大概看一下HTTP协议基础,

1、消息头和消息体中间用两个\r\n(0x0d0x0a)来分割,

2、消息头之间用\r\n分割,

3、消息头的个数不定,但有最大数,

4、消息体的大小根据Content-Length头来确定,

5、消息头的名字和值用英文半角冒号分割

6、消息头的第一行用来标识协议是request还是response,及协议的版本,请求的方法,应答码,应 答描述

协议了解了,协议栈就好写了,如果我们能一次读取一个完整的包,那我们把整个包读出来,解析成 字符串,然后用IndexOf,Split等函数很快的就能解析出一个个都HttpRequest和HttpResponse,但是真是 的网络中,你可能只能解析到半个半个多包,没准连消息头的第一行都分两次才能接受到,甚至像一个中 文字符也有可能会收两次才能包才能解析成字符串。我们要想提高效率,尽量避免把bytes解析成字符串 ,另外我们只解析出header给上层应用就行了,body的话暴露成一个Stream就行了,因为你不知道Body的 格式,由应用去做处理吧,asp.net也是这样的,有对应的InputStream和OutStream。

下面是具体的性能方面的分析。

1、在Stack收到异步读取的网络包后,首先继续调用BeginReceive方法,然后再解析收到的包,这是 为了防止在解析包的时候出错,或者线程挂起而造成无法接受剩下的包,当然每次尽量多读取一些字节, 读取次数多也会降低性能,buffer可以设置的稍微大一些,这个可能要经过具体平台的测试才能确定最合 适的值。这点有不同意见,说不要在刚收到异步读取回调后就先BeginReceive,应该把包收完再 BeginReceive,否则如果本次没收完包,剩下的包只能在其它的IOCP线程里接收,影响性能,这个我不确 认,但是一次接受完缓冲区的所有数据是可以做到的,用Socket.IOControl(FIONREAD, null, outValue) 或者socket.Available可以获取接受缓冲区有多少数据,然后把这些数据收完;但是微软反对使用这些方 法去探察socket的接受数据大小,因为执行这个方法系统需要内部使用锁锁定数据计算这个值,降低 socket效率。关于接受包这里的最佳实践,欢迎大家讨论。

2、按理说收到包后先放队列里,再调用解析包方法,解析包的方法顺序从队列里取包解析,但解析包 和接受包可以都在一个线程里,没有必要引入单独的解析包线程,最后还是考虑不使用队列,每次直接把 收到的字节数组进行解析。原则是我们尽量让一个线程只适用本线程的私有数据,而不去用全局共享的数 据,如果要使用别的线程的数据,就给那个线程发个消息,让那个线程自己去处理自己线程的数据,而不 要直接操作不属于自己的数据,那样的话那个数据就得用加锁之类的线程同步了。线程模型的确定很重要 。

3、按理说解析网络包推荐用Encoding.UTF8.GetDecoder().GetChars()方法,该方法会维持utf8解析 状态,在收到不能解析成一个完整的unicode字符的包的字节数组的时候它可以保存剩下的半截儿包,和 下次收到的包一起解析,而不会造成包丢失。但是该方法的参数只能传入一个char数组,然后我们有可能 把多个char数组进行内存拷贝,这就浪费了性能,所以不考虑了。如果该方法能把解析出来的char数组自 动填充到一个字节环形链表里,我们就可以考虑用它。我们尽量使用.NET自己提供的功能,但是如果不满 足我们的需求的时候,我们就得自己实现去,当然可以反射.NET程序集,借鉴他的做法。

4、我们应该尽量避免把收到的字节数组解析成字符串,然后再按包的规则进行解析,因为把字节

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号