Wininet协议栈的一个缺陷

来源:互联网 发布:淘宝上靠谱的手机店 编辑:程序博客网 时间:2024/04/30 05:50
前段时间在为某个项目定位一个问题时,发现一个问题:
问题背景:
  业务在WM平台上开发,客户端与服务器之间传输采用HTTP协议,采用Wininet库进行的封装,由于业务的需要,在某些场合下需要采用wap接入点,在某些情况下,需要采用net接入点接入。
问题出现的情况:
  GPRS拨号采用系统自带的ConnectionManager进行管理,调用的是ConnMgrEstablishConnectionSync函数进行同步拨号操作,在网络接入点进行切换时,需要调用ConnMgrEstablishConnectionSync函数重新拨号,每次切换时,拨号都能成功,但是网络接入点切换重新拨号成功后,首次HTTP请求高概率出现超时现象,超时时间从几秒到3分钟左右,用户体验极差。
分析过程:

1.最初怀疑切换时,前一个没有完全关闭,仔细分析了ConnMgrReleaseConnection函数, 确认有可能,这个函数只是通知系统关闭连,改为RAS相关函数(这 是系统底层拨号函数,没有延迟)。调用RasHangUp函数确 认关闭连。 

2. 采用上述方案后,问题依旧,说明不是旧的未完全 关闭问题。增加了新的检查函数,检查新的状态,确认新的完全正 常情况下,超时问题依旧存在。排除了方面的问题。

3.分析UCWeb切换网络,很正常,通过手机上抓包,发现没有直接的HTTP协议包,只有TCP包,通过对TCP包 进行分析,里面传输的内容其实也是HTTP协 议的内容。推测是其采用socket来模拟的HTTP协议栈。
根据UCWeb的 情况,在我们的客户端添加了socket测试代码。 测试时机和上面相同。在网络接入点切换时。经过测试,发现网络切换时,无论哪种情况,都能连接成功。说明socket在网络切换时没有任何问题。

4. 进一步测试,每次网络切 换时,先通过socket网络进 行测试,确保成功之后,然后再进行HTTP测 试,发现即使socket发送收数据成功,HTTP问 题依旧,大概可以推断出Wininet库确实 有一些BUG,在处理这种网 络更新状况时,有其重 要缺陷。

问题解决办法:

  可能是断网或者切换网络后wininet库还在使用断网前的socket资 源引起,所以我们的解决方法就是在外围替wininet去做这些释放资源的事情。在切换网络后主动去释放socket资源,释放的方法就是调用WSACleanup(),问 题的关键是调用一次WSACleanup()还不行,因为WINSOCKET库 可能做了一些与COM组件类似的引用计数机制,我们需要不停的调用WSACleanup()直到这个函数返回WSANOTINITIALISED这个值为止。按程序逻辑来讲WSACleanup与WSAStartup一一对应,而实际测试中发现一般都是至少调用了2到3次WSACleanup()后 才返回WSANOTINITIALISED值,所以我们可以猜测一个应用程序或者DLL在使用wininet库的时候wininet库都会调用一次WSAStartup,从 而导致WINCSOCKET库的引用计数加1,而我们开发的应用中在多处使用了wininet库,所以要把socket资源清除干净则至少需要调用2-3次WSACleanup()才 行,清空完后我们就可以重新调用WSAStartup进行WINSOCKET库初始化了。