上一篇   Qt实现Rasdial宽带拨号  讲解了下最简单的宽带拨号方式。但是在实际项目开发中,发现,这种做法是不好的。效率低,有时拨号失败。而且上一回。我们是采用异步拨号来实现,这个做法是不行的。我们需要实现同步拨号。 那么我们应该借助api函数:

DWORD   WaitForSingleObject( HANDLE   hHandle, DWORD  dwMilliseconds);

以下是百度百科的解释,更详细的可以参考msdn

hHandle[in]对象句柄。可以指定一系列的对象,如Event、Job、Memory resource notification、Mutex、Process、Semaphore、Thread、Waitable timer等。

dwMilliseconds[in]定时时间间隔,单位为milliseconds(毫秒).如果指定一个非零值,函数处于等待状态直到hHandle标记的对象被触发,或者时间到了。如果dwMilliseconds为0,对象没有被触发信号,函数不会进入一个等待状态,它总是立即返回。如果dwMilliseconds为INFINITE,对象被触发信号后,函数才会返回。
利用这个函数,我们可以实现同步拨号。但是这样做还不够,我们不能让这个可能耗时的操作来影响我们的gui线程。所以,我们需要把它放到单独一条线程运行。在这个线程里面实现断网和拨号。拨号后通知主线程就可以了。但是,我们需要检测拨号成功了没有。 好。进入第二个问题。
怎么判断当前网络是否运行连接成功? 第一做法就是查msdn。。然后找到了这个函数
[cpp] view plaincopy
  1. BOOL InternetGetConnectedStateEx(
  2. LPDWORD lpdwFlags,
  3. LPTSTR lpszConnectionName,
  4. DWORD dwNameLen,
  5. DWORD dwReserved
  6. );

具体的依然参考msdn library。我们这里只说下怎么判断宽带连接是否连接成功。按照msdn的说法。我们这样写就可以了。 bool ret = InternetGetConnectedStateExA (0, “宽带连接”, 0, 0) .  只要判断下ret的bool值就可以了。用了几次后,我发现这样做根本就不靠谱呀。在企业开发中,有种比较常用的判断网络是否连接成功的方法是通过访问指定的外网和内网。公司的服务器上单独开一个接口用来判断。。捧着学习的态度,我决定用用别的api来解决。依然是借助api。这次我直接搜索RasDial。。结果,让我惊讶了下;。。真的有这个函数。通过这个函数可以直接拨号。为了追求效率,我决定放弃调用cmd命令,毕竟效率不高。我们来看下

[cpp] view plaincopy
  1. DWORD RasDial(
  2. LPRASDIALEXTENSIONS lpRasDialExtensions,
  3. LPCTSTR lpszPhonebook,
  4. LPRASDIALPARAMS lpRasDialParams,
  5. DWORD dwNotifierType,
  6. LPVOID lpvNotifier,
  7. LPHRASCONN lphRasConn
  8. );

老话,具体的请看msdn。总觉得这些api什么的,msdn已经讲解的很好了。这里给出qt如何使用这个函数。添加头文件

#include <ras.h>   记得添加lib  #pragma comment(lib, "Rasapi32.lib");
[cpp] view plaincopy
  1. bool MRasdial::reConnect()
  2. {
  3. // 重新拨号函数
  4. RASDIALPARAMS rasParam;
  5. ZeroMemory(&rasParam, sizeof(RASDIALPARAMS));
  6. rasParam.dwSize = sizeof (RASDIALPARAMS);
  7. wcscpy(rasParam.szEntryName,L"ADSL" );
  8. wchar_t userName[100] = L"", userPass[100] = L"";
  9. m_UserName.toWCharArray(userName);
  10. m_UserPass.toWCharArray(userPass);
  11. wcscpy(rasParam.szUserName , userName);
  12. wcscpy(rasParam.szPassword , userPass);
  13. HRASCONN handle = NULL; // 注意,记得初始化。
  14. int res = RasDial(0,0, &rasParam, 0, 0, &handle);
  15. if (res != ERROR_SUCCESS) {
  16. qDebug()<<"dial error:"<< res;
  17. // 出错 采用断开连接的方法尝试再次连接
  18. // 前提需要保障用户账号名和密码是正确的
  19. RasHangUp (handle);
  20. return false; // 返回错误 待会再连接
  21. }
  22. qDebug()<<"dial is over";
  23. return true;
  24. }

这边注意一个细节,我是怎么处理拨号出错的。为了防止宽带拨号处于宽带拨号中,我们需要借助 RasHangUp(HRASCONN handle); 来断开连接。。好了。现在回到第二个问题,该怎么判断网络连接状态。这个需要借助 RasEnumConnections 函数来枚举出当前连接的句柄信息。使用代码例子如下:

[cpp] view plaincopy
  1. bool MRasdial::isADSLConnect()
  2. {
  3. // 通过枚举获取当前连接的ADSL的句柄
  4. RASCONN rasconnArr[20]; // 存放多个结构体
  5. DWORD dwRasConSize =  20* sizeof(RASCONN);
  6. DWORD dwRasConCount = 0;
  7. rasconnArr[0].dwSize = sizeof (RASCONN);
  8. if (!RasEnumConnections(rasconnArr, &dwRasConSize, &dwRasConCount)) {
  9. for (int i =0; i< (int)dwRasConCount; ++i) {
  10. if (wcscmp(rasconnArr[i].szEntryName, L"ADSL") == 0) {
  11. return true;
  12. }
  13. }
  14. }
  15. return false;
  16. }

这里我就是要判断当前连接是否有ADSL这个用户名。 这种做法就可以更好的判断当前用户名为ADSL的宽带账号是否连接成功。 最后,需要说明的是,在断开网络和连接网络,最好有一定的时间间隔。我的做法如下,仅供参考

[cpp] view plaincopy
  1. void MRasdial::reConToNet()
  2. {
  3. do {
  4. disconnect(); // 断开网络
  5. Sleep(4000);
  6. } while (true == isADSLConnect());
  7. qDebug()<<"net is dis";
  8. // 连接网络
  9. do {
  10. if (true == reConnect())
  11. break;
  12. qDebug()<<"connect to net";
  13. Sleep(4000);
  14. } while (false == isADSLConnect());
  15. emit reNetSuccess();
  16. }

最后这里提供几个相关信息的链接:

关于RasDial拨号错误代码的详解: Routing and Remote Access Error Codes

关于拨号函数RasDial详解:  RasDial

再谈Qt实现Rasdial拨号问题(说说项目中遇到的问题和解决方案)相关推荐

  1. 【原创】Performanced C++ 经验规则 第五条:再谈重载、覆盖和隐藏

    第五条:再谈重载.覆盖和隐藏 在C++中,无论在类作用域内还是外,两个(或多个)同名的函数,可能且仅可能是以下三种关系:重载(Overload).覆盖(Override)和隐藏(Hide),因为同名, ...

  2. 透过数字化转型再谈数据中台(三):一文遍历大数据架构变迁史

    编者按:<透过数字化转型再谈数据中台>系列连载 6-8 篇左右,作者结合自己在数据中台领域多年实践经验,总结了数据架构知识.BI 知识,以及分享给大家一些产业互联网实施经验.本文是系列文章 ...

  3. 再谈 Go 语言在前端的应用前景

    12 月 23 日,七牛云 CEO & ECUG 社区发起人许式伟先生在 ECUG Con 2018 现场为大家带来了主题为<再谈 Go 语言在前端的应用前景>的内容分享. 本文是 ...

  4. 浅谈 Qt 中 UDP 之 UdpSocket通信实例

    浅谈 Qt 中 UDP  写这篇博客的原因是Java大作业最近完成了一个简单的聊天室.也是基于UDP的.正好我们在学习Qt.所以我想能不能再qt中同样实现这样一个问题.于是我进行的代码的编辑.以及其他 ...

  5. 再谈JSON -json定义及数据类型

    再谈json 近期在项目中使用到了highcharts ,highstock做了一些统计分析.使用jQuery ajax那就不得不使用json, 可是在使用过程中也出现了非常多的疑惑,比方说,什么情况 ...

  6. C++_动态绑定,再谈const,new,delete

    C++_动态绑定,再谈const,new,delete

  7. 再谈HTTP2性能提升之背后原理—HTTP2历史解剖

    即使千辛万苦,还是把网站升级到http2了,遇坑如<phpcms v9站http升级到https加http2遇到到坑>. 因为理论相比于 HTTP 1.x ,在同时兼容 HTTP/1.1 ...

  8. 再谈工作的主动性和有效提问

    主动性是一个非常奇怪的词,每个人对这个词的理解都不一样.可能一个管理者对员工说,你要提高主动性,但是员工会非常苦恼,甚至崩溃:我都天天加班了,你居然还在谈提高主动性? 结合很多应届生在实际工作中遇到的 ...

  9. 再谈符号间干扰(一)

    在对话通信原理系列相关博文中,有这么一篇博文:通信系统之信道,这篇博文里面已经讲过符号间干扰(ISI),发生符号间干扰的原因在于信号带宽大于相干带宽,同一个意思的表达为:发送符号的周期小于最大时延扩展 ...

  10. 我的WCF之旅 (11): 再谈WCF的双向通讯-基于Http的双向通讯 V.S. 基于TCP的双向通讯...

    在一个基于面向服务的分布式环境中,借助一个标准的.平台无关的Communication Infrastructure,各个Service通过SOAP Message实现相互之间的交互.这个交互的过程实 ...

最新文章

  1. C语言写一函数交换两变量的值
  2. linux 重定向类型 超级块 i节点
  3. es6的Promise(承诺)
  4. Kafka实战-Flume到Kafka
  5. 如何在vc的拆分窗口中使用CFormView派生类
  6. HDU-3746-Cyclic Nacklace
  7. 基于 KubeVela 的 GitOps 交付
  8. 如何共享自己的mysql
  9. Linux下查看当前文件大小的命令
  10. 单链表的头插法和尾插法c语言实现
  11. 使用Mybatis Generator结合Ant脚本快速自动生成Model、Mapper等文件的方法
  12. Mysql数据库设计规范之二数据库字段设计规范
  13. ConcurrentProgramming:ThreadLocal(jdk8)
  14. java spring 加载bean,Spring多种加载Bean方式解析
  15. 安庆师范大学计算机学院书记,安庆师范大学计算机与信息学院导师教师师资介绍简介-施赵媛...
  16. 一般通话记录能保存多少条_有一手|2万炒股0一般能挣多少?
  17. SQL 2005/2008质疑修复
  18. android定位!每个程序员都必须掌握的8种数据结构!完整版开放下载
  19. vscode调试用的launch.json
  20. 邮件群发系统 php,QQ邮箱群发PHP源码

热门文章

  1. storm throw 口袋妖怪_pokemon go游戏术语都有哪些 口袋妖怪go玩法术语攻略
  2. map的基本使用-go篇
  3. 服务器销售工资如何计算公式,拿提成的工资怎么算的有公式吗
  4. 凌祯excel课程_她1篇Excel教程超10万人在学,想教你Excel入门到高阶,10倍提升工作效率!...
  5. C++ 模板函数 二分查找
  6. android系统 vender添加自定义的预编译的应用程序
  7. 【K8S】整体原理-K8S网络
  8. Vmware vcenter未授权任意文件上传(CVE-2021-21972)复现
  9. Linux 中文件压缩方法与tar打包详解
  10. linux关于系统管理、系统安全命令