新疆软件开发

本站首页 软件开发 成功案例 公司新闻 公司简介 客服中心 软件技术 网站建设
  您现在的位置: 新疆二域软件开发公司 >> 开发语言 >> 文章正文

网络编程中怎样得知一次数据已经收完?

     两年前用.net 2.0做了一个反向代理服务器,在这两年时间里,不断修改BUG以及优化性能,使得可用性大大提高。近来碰到一个功能需求,实在无法找出有效的解决办法,只好上来请教各位高人。
    先说说反向代理的工作机理吧。
1、客户端通过浏览器访问反向代理的时候,会发出一个HTTP请求,反向代理收到这个TCP连接的时候,建立一个新的会话用于处理这个请求(BeginAccept、EndAccept);
2、会话对象建立一个从客户端接收数据的委托,开始异步读取数据(BeginRead);
3、取得数据时,进入异步读取的回调函数中,开始处理数据(EndRead);
4、检查反向代理与服务器的连接是否已建立,如果没有建立,那么需要先建立连接(ConnectServer),并建立服务器的异步读取委托(BeginRead);
5、把数据异步写入服务器(BeginWrite);
6、重新建立客户端异步读取委托(BeginRead),回到3;
7、收到服务器返回数据时,处理后,异步写入客户端(BeginWrite);
8、重新建立服务器异步读取委托(BeginRead),回到7;

所有的数据传输,都使用异步来完成,而只需要在3和7处为业务编写数据处理代码即可。
实际上,对于反向代理来说,只需要处理客户端发来的数据就可以了,需要把HTTP的HOST头替换为真实服务器,而对于服务器响应的数据,只需要原样发送给客户端就可以了。

在步骤3中,我们只知道当前收到了客户端发来的数据,而不知道这个数据是不是Http请求头,或者是完整的Http请求头。幸好,对于反向代理来说,不需要关心是否是完整的Http请求头,只需要检查是否是Http请求头,如果是,就修改Host即可。在这里,我假设Http请求的第一个数据包肯定是独立的数据包,不会“粘”在TCP连接中上一次数据的后面,这样就可以直接使用Http协议规定的格式来检查这个数据包是否Http请求头了。虽然这个假设没有什么依据,但它确实非常有效。

程序就这样工作了两年,没有什么问题。

但接下来,问题就出现了,有一个需求,要求能够把服务器返回的页面中的某个字符串替换为指定的字符串。比如我用反向代理指向博客园,我就需要把博客园页面中所有使用了绝对路径的连接修改为指向反向代理服务器的连接。这就要求在步骤7这里处理数据,把数据转为字符串,然后替换链接,然后才发往客户端。

但步骤7每次收到的数据只是一个片段,而不是整个页面的HTML。即使我们再次假设Http响应的第一个数据包是独立的数据包,也只能识别哪些是响应头,哪些是数据体而已。也想过每一段数据转为这一段的字符串进行处理,但是,如果刚好某个字符被网络层拆分到两个TCP数据包里怎么办?还有,想博客园这样使用了gzip的,如果不接受完整个页面的数据,是无法解压的;就算这两种情况都不存在,而网络层刚好在超链接的地方拆分数据包怎么办?

因此,最保守的做法就是拿到整个页面数据再开始处理。也想过Http响应头那里有个Content-Length指明内容长度的,但实际中,很多响应根本就不到这个段。

我查看过HttpListener类和HttpListenerRequest类,尝试从中发现它是如何接受完一次请求(响应)的,可惜这两个类调用了大量NativeAPI,就无法得知了。

还有浏览器,它又是如何得知某次响应是否已经完成的呢?

还请各位高人多多指教!

这个代理已经放到codeplex上,大家有兴趣可以看看:http://www.codeplex.com/XProxy/

作者:新生命 | 文章来源:cnblogs | 更新时间:2008-3-10 17:27:31

  • 上一篇文章:

  • 下一篇文章:

  • 相关文章:
    使用Response.Redirect时ry失效 -asp.net中
    复制SQL 数据库时的问题
    怎样的情况下 可以更新数据
    如何使用高效数据检索优化SQL Server应用程序性能
    软件技术
    · 开发语言
    · Java技术
    · .Net技术
    · 数据库开发
    最新文章  
    ·搜集整理的asp.net的验证方
    ·各种FOR循环结构的整理
    ·软件项目开发中应该考虑那
    ·搜集整理的javascript sel
    ·软件开发中项目经理有那些
    ·学习如何在Lambda表达式进
    ·C++基础知识:结构体数据的
    ·C#实现短信发送程序的例子
    ·sun最近修补了一部分java的
    ·rss定制的另外一种实现方式
    ·delphi实现利用arp欺骗来实
    ·基础学习:基于WF的流程框
    ·网络编程中怎样得知一次数
    ·如何逆序输出单链表?
    ·软件开发过程中的性能设计
    关于我们 | 软件开发 | 下载试用 | 客服中心 | 联系我们 | 友情链接 | 网站地图 | 新疆电子地图 | RSS订阅
    版权所有 © 2016 新疆二域软件开发网 www.k8w.net All Rights Reserved 新ICP备14003571号
    新疆软件开发总机:0991-4842803、4811639.
    客服QQ:596589785 ;地址:新疆乌鲁木齐北京中路华联大厦A-5C 邮编:830000