华为AnyOffice eSDK 手机端内外网通信的正确姿势

华为AnyOffice实现了一整套移动平台接入方案和管理方案,但是其提供eSDK对开发者并不是很友好,比如eSDK提供了都是第七层HTTP协议的API,只能使用它提供的几个类进行操作,很不灵活而且局限性比较高,通过本文可以帮助你解决以下几个问题。

注:本文的讨论基于华为eSDK RC10 2017年9月的版本,RC10版的Demo,L4v*n模式


1、通过eSDK传输非HTTP协议的其他TCP协议的数据,比如FTP,SFTP,SSH,POP3,SMTP,即时通讯框架等。

2、通过eSDK实现内网外网自由访问,用于集成第三方地图,消息推送等。

3、通过eSDK使用Retrofit,Volley,OKHttp等网络框架访问内网

4、通过eSDK使用HTTPS协议内网Web服务


首先以Android端为例,简单强调一下eSDK提供的访问内网的接口有如下几个

SvnHttpClient:继承于DefaultHttpClient,通过该类发送的数据会通过隧道,获取方式new SvnHttpClient();使用SvnHttpClient与DefaultHttpClient不冲突,也就是说你可以同时用SvnHttpClient走内网,用DefaultHttpClient走公网


HttpURLConnection: 获取方式URLConnectionFactoryHelper.setURLStreamHandlerFactory(),该设置不可逆;执行之后所有通过HttpURLConnetion发出的请求都是隧道内请求,没执行的时候是可以访问公网的,所以HttpURLConnection只能在公网和内网中选择一个通信,但不会影响SvnHttpClient和WebView的网络访问规则


WebView:获取方式SvnWebViewProxy.getInstance().setWebViewUseSVN(WebView),该设置不可逆;参数为Android原生WebView的引用,设置后该WebView就通过隧道进行通讯,注意没设置之前是可以访问公网,设置之后只能访问内网。此处要特别注意:一旦设置了WebView走内网,那么HttpURLConnection,DefaultHttpClient就都自动全部变成内网了,此时你就相当于开启了全局的HTTP代理,非常容易出问题。


SvnSocket:继承与java.net.Socket;获取方式 new SvnSocket();不影响其他程序的网络访问规则;该类实现了原生Socket的大部分方法,比如最重要的getInputStream和getOutputStream,但是比如setKeepAlive()这样的方法就没有实现,如果调用直接就会报Exception。。有了它,我们就可以通过Socket编程实现一个四层的TCP隧道,这个是科学使用eSDK的关键所在。


那么使用华为eSDK需要如下几个原则:


一、一定不能使用 SvnWebViewProxy.getInstance().setWebViewUseSVN(WebView) 

因为一旦执行了该条语句,那么会在手机里建立一个全局的HTTP代理,所以不管HttpClient还是HttpURLConnection还是其他的WebView,在执行过该条语句之后全部不能连接公网,只能走内网了,这不是我们想看到的


二、并不是走内网v*n就不能访问公网

不要忘了SDK建立v*n时候的网关是一台放在公网上的主机,所以即使你的HttpClient,HttpURLConnection 设置了走SVN通道,他们把请求发到了你的SVN网关,SVN网关也会把你的请求发送到公网上再返回给你。就像你平时在家用v*n一样的效果。所以当你设置成走内网时发现还能访问到百度等公网网站就觉得自己代码写错了是自己吓唬自己。验证方法就是,对于WebView,可以打开http://www.baidu.com 搜索ip,就会显示你当前的公网IP,判断这个公网IP是网关IP还是你自己手机的IP即可。对于HttpClient和HttpURLConnection,OkHttp,Socket等可以发送http请求到http://www.ip111.cn,查看返回的数据,能看到你的公网IP,如下图

(注1:该页面为华为官方提供的Android Demo 可以在公网和内网两个选项中切换,非常好用)

(注2:要想实现手机端通过网关访问公网,那么网关主机的防火墙限制要松一些,详细的说就是不要只允许RELATED和ESTABLESHED连接通过而拒绝SYN包,再详细点说就是-m state --state RELATED,ESTABLISHED -j ACCEPT 然后默认DROP这种语句不要出现)

华为AnyOffice eSDK 手机端内外网通信的正确姿势    华为AnyOffice eSDK 手机端内外网通信的正确姿势

3、内网连接就走127.0.0.1,公网原先怎么走还怎么走

通过SvnSocket我们可以建立一条连通手机与后端应用服务器的TCP隧道,所有TCP的上层协议都可以走,比如HTTP(s),FTP,SSH,POP3,SMTP,即时通讯,甚至你的APP使用了JAVA NIO,AIO这样也不在话下。其他的SvnHttpClient,SvnHttpURLConnection,SvnWebView等eSDK提供的控件完全就没有用了,通过TCP隧道,我们可以把真实服务器比如192.168.1.2:80映射到手机的8080端口,然后我们只需修改程序,把程序原来的目标地址从192.168.1.2:80改为127.0.0.1:8080就实现了内网数据走v*n隧道,访问本地的8080端口和访问远程的80端口效果是一模一样的,而且不影响其他的程序工作,尤其是需要接外网的比如地图,消息推送,用户行为统计等功能,而且你可以方便的使用各类网络框架,Retrofit,Okhttp,xmpp,mina等等了。


隧道建立起来之后,就可以通过反向代理的原理,通过Android原生网络库或者原生浏览器访问本地端口达到访问远程内网服务器的功能了,效果如下图,使用手机随便一个浏览器访问127.0.0.1:9090就如同访问远程的80端口


华为AnyOffice eSDK 手机端内外网通信的正确姿势

对于Android端我直接在华为官方Demo上添加了开启隧道的功能页面,SvnSocket实现TCP的隧道的方法和下载Demo可以看我上一篇博客《华为AnyOffice eSDK建立TCP端口转发隧道

华为AnyOffice eSDK 手机端内外网通信的正确姿势

对于iOS端我只写了建立隧道的Objc代码,可以到《Objective-C (iOS)实现TCP反向代理(Port forward隧道)》查看如何在iOS端建立隧道