热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

网络编程中如何得知一次请求(或响应)的数据已接收完

两年前用.net2.0做了一个反向代理服务器,在这两年时间里,不断修改BUG以及优化性能,使得可用性大大提高。近来碰到一个功能需求,实在无法找出有效的解决办法,只好上来请教各位高人。
    两年前用.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/

还有,不要忘了给我的问题提个解决思路^_^
谢谢!

QQ:99363590
E-Mail:nnhy#vip.qq.com
QQ群: 10193406
推荐阅读
  • 本文详细介绍了如何利用go-zero框架从需求分析到最终部署至Kubernetes的全过程,特别聚焦于微服务架构中的网关设计与实现。项目采用了go-zero及其生态组件,涵盖了从API设计到RPC调用,再到生产环境下的监控与维护等多方面内容。 ... [详细]
  • 远程访问用户 Kindle通过电子书实现控制
    介绍自2007年以来,亚马逊已售出数千万台Kindle,令人印象深刻。但这也意味着数以千万计的人可能会因为这些Kindle中的软件漏洞而被黑客入侵。他 ... [详细]
  • 理解HTTP状态码及其应用
    本文详细解析了HTTP状态码的分类及常见代码的意义,帮助开发者和用户更好地理解和解决网络请求中遇到的问题。 ... [详细]
  • django项目中使用手机号登录
    本文使用聚合数据的短信接口,需要先获取到申请接口的appkey和模板id项目目录下创建ubtils文件夹,定义返回随机验证码和调取短信接口的函数function.py文件se ... [详细]
  • 深入理解SAP Fiori及其核心概念
    本文详细介绍了SAP Fiori的基本概念、发展历程、核心特性、应用类型、运行环境以及开发工具等,旨在帮助读者全面了解SAP Fiori的技术框架和应用场景。 ... [详细]
  • 探讨了使用 JavaScript IIFE(立即执行函数表达式)动态加载 YouTube 脚本时遇到的问题,并提供了可能的解决方案。 ... [详细]
  • 匠心|传统_2021年度总结 | 葡萄城软件开发技术回顾(上)
    匠心|传统_2021年度总结 | 葡萄城软件开发技术回顾(上) ... [详细]
  • 本文详细介绍了Python的multiprocessing模块,该模块不仅支持本地并发操作,还支持远程操作。通过使用multiprocessing模块,开发者可以利用多核处理器的优势,提高程序的执行效率。 ... [详细]
  • C#爬虫Fiddler插件开发自动生成代码
    哈喽^_^一般我们在编写网页爬虫的时候经常会使用到Fiddler这个工具来分析http包,而且通常并不是分析一个包就够了的,所以为了把更多的时间放在分析http包上,自动化生成 ... [详细]
  • 本文详细介绍了Java编程语言中的关键字及其用途,包括53个关键字和2个保留字。文章不仅解释了每个关键字的基本功能,还提供了实际应用场景中的使用示例。 ... [详细]
  • 本文介绍了FTP(文件传输协议)的基础知识,包括其定义、如何通过TCP建立控制和数据连接,以及主动模式与被动模式的区别。FTP作为一种重要的文件传输协议,在互联网数据交换中扮演着关键角色。 ... [详细]
  • 本文探讨了在使用 ClickOnce 部署方式时遇到的自动更新失败问题,包括本地安装与服务器安装的不同表现,并提供了详细的解决方案。 ... [详细]
  • 提升接口测试效率的关键:用例与工具的综合应用
    本文将探讨如何通过有效的接口测试用例设计和工具选择,显著提高接口测试的效率和质量。 ... [详细]
  • 深入解析Keras中的ImageDataGenerator参数
    本文详细探讨了Keras库中ImageDataGenerator类的各项参数及其功能,旨在帮助读者更好地理解和应用数据增强技术,提高模型训练效果。 ... [详细]
  • 图神经网络模型综述
    本文综述了图神经网络(Graph Neural Networks, GNN)的发展,从传统的数据存储模型转向图和动态模型,探讨了模型中的显性和隐性结构,并详细介绍了GNN的关键组件及其应用。 ... [详细]
author-avatar
手机用户2502937497
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有