摘要: 无论是从 Local DNS 解析域名,获取到 IP 列表,还是从第三方的 DNS 解析服务中,获取到域名对应的 IP 列表。我们获得多个 IP 后,总是想选取一个最优的 IP 使用,本文主要探讨如何在客户端探测 IP 的连接性以及连接速度,保证返回可用性最好的IP,以达到“IP优选”的目的。

移动端 IP 优选方案
1. IP 优选目的
无论是从 Local DNS 解析域名,获取到 IP 列表,还是从第三方的 DNS 解析服务中,获取到域名对应的 IP 列表。我们获得多个 IP 后,总是想选取一个最优的 IP 使用,本文主要探讨如何在客户端探测 IP 的连接性以及连接速度,保证返回可用性最好的IP,以达到“IP优选”的目的。

2. 新浪开源的 httpdns 的 sdk 里的测速逻辑
新浪开源一个 HTTPDNSLib ,里面包含了测速逻辑,GitHub地址如下:

《HTTPDNSLib-for-iOS》
《HTTPDNSLib》
我们以该 sdk 里的测速逻辑为例进行原理解析。

3. IP 测试实现原理
使用 linux socket connect 和 select 函数实现的。 基于以下原理:

即使套接口是非阻塞的。如果连接的服务器在同一台主机上,那么在调用connect 建立连接时,连接通常会立即建立成功,我们必须处理这种情况。
源自Berkeley的实现(和Posix.1g)有两条与select 和非阻塞IO相关的规则:
A. 当连接建立成功时,套接口描述符变成可写;
B. 当连接出错时,套接口描述符变成既可读又可写。

详细的测速实现如下,原理参考注释:

以 iOS 实现为例:

- (int)testSpeedOf:(NSString *)ip port:(int16_t)port {NSString *oldIp = ip;//request time outfloat rtt = 0.0;//sock:将要被设置或者获取选项的套接字。int s = 0;struct sockaddr_in saddr;saddr.sin_family = AF_INET;// MARK: - 设置端口,这里需要根据需要自定义,默认是80端口。saddr.sin_port = htons(port);saddr.sin_addr.s_addr = inet_addr([ip UTF8String]);//saddr.sin_addr.s_addr = inet_addr("1.1.1.123");if( (s=socket(AF_INET, SOCK_STREAM, 0)) < 0) {NSLog(@"ERROR:%s:%d, create socket failed.",__FUNCTION__,__LINE__);return 0;}NSDate *startTime = [NSDate date];NSDate *endTime;//为了设置connect超时 把socket设置称为非阻塞int flags = fcntl(s, F_GETFL,0);fcntl(s,F_SETFL, flags | O_NONBLOCK);//对于阻塞式套接字,调用connect函数将激发TCP的三次握手过程,而且仅在连接建立成功或者出错时才返回;//对于非阻塞式套接字,如果调用connect函数会之间返回-1(表示出错),且错误为EINPROGRESS,表示连接建立,建立启动但是尚未完成;//如果返回0,则表示连接已经建立,这通常是在服务器和客户在同一台主机上时发生。int i = connect(s,(struct sockaddr*)&saddr, sizeof(saddr));if(i == 0) {//建立连接成功,返回rtt时间。 因为connect是非阻塞,所以这个时间就是一个函数执行的时间,毫秒级,没必要再测速了。close(s);return 1;}struct timeval tv;int valopt;socklen_t lon;tv.tv_sec = HTTPDNS_SOCKET_CONNECT_TIMEOUT;tv.tv_usec = 0;fd_set myset;FD_ZERO(&myset);FD_SET(s, &myset);// MARK: - 使用select函数,对套接字的IO操作设置超时。/**select函数select是一种IO多路复用机制,它允许进程指示内核等待多个事件的任何一个发生,并且在有一个或者多个事件发生或者经历一段指定的时间后才唤醒它。connect本身并不具有设置超时功能,如果想对套接字的IO操作设置超时,可使用select函数。**/int maxfdp = s+1;int j = select(maxfdp, NULL, &myset, NULL, &tv);if (j == 0) {NSLog(@"INFO:%s:%d, test rtt of (%@) timeout.",__FUNCTION__,__LINE__, oldIp);rtt = HTTPDNS_SOCKET_CONNECT_TIMEOUT_RTT;close(s);return rtt;}if (j < 0) {NSLog(@"ERROR:%s:%d, select function error.",__FUNCTION__,__LINE__);rtt = 0;close(s);return rtt;}/**对于select和非阻塞connect,注意两点:[1] 当连接成功建立时,描述符变成可写; [2] 当连接建立遇到错误时,描述符变为即可读,也可写,遇到这种情况,可调用getsockopt函数。**/lon = sizeof(int);//valopt 表示错误信息。// MARK: - 测试核心逻辑,连接后,获取错误信息,如果没有错误信息就是访问成功/*!* //getsockopt函数可获取影响套接字的选项,比如SOCKET的出错信息* (get socket option)*/getsockopt(s, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon);//如果有错误信息:if (valopt) {NSLog(@"ERROR:%s:%d, select function error.",__FUNCTION__,__LINE__);rtt = 0;} else {endTime = [NSDate date];rtt = [endTime timeIntervalSinceDate:startTime] * 1000;}close(s);return rtt;
}

移动端 IP 优选方案相关推荐

  1. Android 模块 -- 基于XMPP协议的手机多方多端即时通讯方案

    目   录 基于XMPP协议的手机多方多端即时通讯方案................................................................. 1 目   录 ...

  2. 广和通携手中国联通研究院、中科创达现网验证全球首例5G模组端到端多切片方案

    当前5G处于规模发展的关键时期,5G行业模组成熟发展是推进5G规模应用的关键环节.目前5G模组价格仍然较高,行业需求较为碎片化,且5G最具特色的功能5G网络切片尚未在行业模组上探索出成熟端到端解决方案 ...

  3. esp32cam 服务端远程视频方案

    esp32cam 服务端远程视频方案 说明 本方案为esp32cam 服务端 浏览器 三端联合使用.将服务端部署在公网即可远程使用,没有远程需求,可以直接在局域网使用.代码无需修改. 本文取缔了esp ...

  4. 华为发布全球首个全性能端到端HSDPA商用方案

    华为发布全球首个全性能端到端HSDPA商用方案     " 手机上网可以比目前的家用ADSL快10倍? "日前,华为技术有限公司( " 华为 ")在北京举行的2 ...

  5. 基于XMPP协议的手机多方多端即时通讯方案

    原文地址为: 基于XMPP协议的手机多方多端即时通讯方案 基于XMPP协议的手机多方多端即时通讯方案 目   录 基于XMPP协议的手机多方多端即时通讯方案...................... ...

  6. 深度揭秘阿里移动端高性能动态化方案Weex

    2016年Qcon大会首日,阿里巴巴资深总监.淘宝移动平台.阿里百川负责人庄卓然宣布移动端高性能动态化方案Weex即时内测,并将于6月开源.此消息一出,群情汹涌,在座的程序猿.攻城狮们纷纷拿起手机扫码 ...

  7. 谈谈我的移动端rem适配方案

    最近有点怀疑人生,毕竟一个人写前端,有时候会怀疑自己理解的一些东西包括用法有没有符合标准.趁着这阵子闲下来,翻了翻别人的rem适配博客,发现有点绕口,怪自己是个强迫症,啥都要自己去试试结果并从中理解, ...

  8. //获取本地IP地址和对端IP地址

    1 //获取本地IP地址 2 CHAR * GetLocalIpAdrr(int fd) 3 { 4 struct sockaddr_in stHost; 5 memset(&stHost, ...

  9. 人人都能掌握的Java服务端性能优化方案

    转载自 人人都能掌握的Java服务端性能优化方案 作为一个Java后端开发,我们写出的大部分代码都决定着用户的使用体验.如果我们的代码性能不好,那么用户在访问我们的网站时就要浪费一些时间等待服务器的响 ...

最新文章

  1. c语言函数的可选性自变量
  2. 【C 语言】变量本质 ( 变量概念 | 变量本质 - 内存空间别名 | 变量存储位置 - 代码区 | 变量三要素 )
  3. java 之持久化和序列化(反序列化)
  4. Python:利用collections库实现统计单个字或单个字母的频率统计并进行降序输出、统计一个列表内重复元素并以字典形式输出
  5. realloc invalid pointer错误解析
  6. 基于嵌入式操作系统VxWorks的多任务并发程序设计――中断与任务
  7. jsoup 简单应用
  8. Spring Boot学习总结(11)——SpringBoot的Starter依赖包及作用
  9. Java基础学习总结(114)——System之系统变量和环境变量
  10. 中兴网信“智慧旅游”亮相2016国际孔子文化节
  11. abp vnext token失效时间设置
  12. 吴恩达机器学习课程资源(笔记、中英文字幕视频、课后作业,提供百度云镜像!)
  13. 网管软件如何部署?网管常用软件
  14. c语言用乘法,c语言口诀(用c语言编写乘法口诀)
  15. 3、查询省会(Python实现多行输入,以回车结束输入)
  16. 【转】Java Hotspot G1 GC的一些关键技术
  17. 福利贴——爬取美女图片的Java爬虫小程序代码
  18. MySQL3:连接查询、子查询及正则表达式查询
  19. 电影《黑客帝国》的真正含义,人类进化的终结吗?
  20. NSDate 转为NSString 时差的问题

热门文章

  1. mongoose 批量修改字段_WordPress图片路径批量替换方法
  2. swift 原生给h5发消息_Swift - 使用HTML5进行iOS开发(将HTML5打包成iOS应用)
  3. java打印已经被加载的类_使用URLClassLoader加载类,不会报错,但被加载类中的内容也没有打印出来...
  4. python商城源码_自学Python才几天,就成功编写出俄罗斯方块游戏,附自学教程
  5. python中newfile是干嘛用的_Python基础介绍 | File I\O 读写文件
  6. wpf 按钮样式_键盘 | 01.在程序集间引用样式
  7. 国基金评委:关键科学问题的凝练不到位,容易被评审专家“灭掉”
  8. 基础研究到底要基础到什么程度?
  9. 从1到N迈向从0到1:华为创新理念升级详解
  10. 感动 ∣她养我长大,我陪她到老!90后女孩带痴呆症养母读研