ios之multipath TCP
之前研究过这个,今天有人问起,回想了半天才想起来具体的技术细节,所以作下简要笔记,已备下次回顾之用。
在IOS7以后的版本中,当iphone连接硬件wifi热点,跟硬件建立tcp socket连接时,怎么才能同时保证可以通过手机自身的4G上internet,在android上这个是做不到的,但iphone可以,这场景就用到multipath TCP。
之前研究过这个,今天有人问起,回想了半天才想起来具体的技术细节,所以作下简要笔记,已备下次回顾之用。
在IOS7以后的版本中,当iphone连接硬件wifi热点,跟硬件建立tcp socket连接时,怎么才能同时保证可以通过手机自身的4G上internet,在android上这个是做不到的,但iphone可以,这场景就用到multipath TCP。
2017像以往的任何一个年头一样,在挣扎和匆忙中过去了。
一月的时候,女儿出生了,令我无比幸福,因为只能和妻子两个人来照看孩子,有了孩子后,老婆性情大变,也开始了我结婚以来的抑郁时刻(我们相识10年,结婚6年)。
三月的时候我的母亲意外车祸去世了,我无比痛苦,开始时常会一个人默默流泪,想念我的母亲或者曾经的某刻时光,我感觉自己抑郁了,或者这本身只是老了的一种表现,我不得而知。
年底左右的时候,借钱和贷款买了地铁口的小产权,不知道是生活的一个进阶还是屈服,然而这个喜悦丝毫不能让我从老婆带来的抑郁中走出来。
由于只能我们两个抚养小孩,我上班她全职,再加上她对小孩近乎变态的怜爱和呵护,这让他筋疲力尽,异常暴躁,而我看在眼里,也只能默默忍受这一切的改变,毕竟她是为了女儿,而我因此要责怪她或者女儿,显然不可能。也许这是人生的必经阶段,也许这是婚姻的不可避免,我无可选择。
因为母亲去世,要打官司赔偿,只能把工作辞掉,准备做好持久战的准备,所以在处理完母亲的事故后,四月底重新入职到了现在的公司。
因为是曾经的同学的极力邀请,所以在据掉了一家以色列的初创公司后,开始了一年多的开发历程。
昨天还收到那个以色列公司的创始人的微信拜年,感觉时光匆匆。
目前的公司是北京公司的深圳分部,也就是初创公司,入职的时间也是新公司的注册成立时间,前期就几个主力人员,基本每个人负责一款独立的产品或者软件。
先是四月开始,要完成一款路由器的开发,因为以往软硬件的积累以及linux的开发经验,很快就从零开始完成一款基于openwrt的行业设备的软件开发,其中一半多的时间是梳理需求和设计业务场景和平台通讯接口协议,开发和测试差不多一半时间。但是因为商务订单的问题,这款演示和测试完成后就暂停了。
这期间,因为大家都没有开发过微信公众号,因为自己有后台开发的经验,就一个人主动承担了公司的微信服务公众号的后台开发,基于php的,一个多月就完成了设计和开发,期间为了按计划完成,取消了提前两个月预定的十一探亲机票,还好按计划完成,也算不枉取消机票的损失。但完成自我目标的喜悦完全可以忽略金钱的损失,内心很高兴。完成项目后,请假一周,回家探亲,让父亲看了下他的孙女,父亲不善言语,但知道他看到孙女很高兴。
11月的时候公司因为想争取一个NBIOT的项目,承诺快速给客户演示样机,又进入到了加班加点的样机开发中,后面还出差成都一周进行现场测试,实测下来NB在做定位tracker方面,目前的芯片方案和运营商服务还不是很成熟,后来测试完了后,因为还达不到GSM的移动稳定性,同时客户也是没有实际的业务订单,也只是想看看NB的效果,所以也只能暂告段落。
完成NB的演示后,就进入了政府的牧场项目中,目前的北京总公司资源很丰富,项目真多。这个项目是和内蒙政府做牧场的牲畜定位追踪和食品安全追溯系统。加班加点的在1月25完成第一期的实地场测。签署了第一批350万的订单,然后就紧接着迎来的农历新年放假。据说放假前,公司拿到了项目款,算是总算干了一个进账的项目吧。
放假期间要完成以下的任务:
1.整个系统的需求文档,因为我是整个项目的产品经理,所以需要统筹整体方案(硬件,平台,app)
2.产品的几个相关app原型和交互设计,年后主要做app的产品经理,将基本完成的硬件firmware的代码交接给其他开发同事。
3.现有硬件fireware的概要设计和详细设计
回来的路上开始看“创业维艰”,今天终于看完了,算是对这几天闲暇愧疚的一个慰藉吧,这是一本很好的书,希望有空能单独写一篇读书笔记。
还有一个小小的喜悦是拿到了驾照,工作这么多年来,一直都很忙,创业和上班,没有时间,今年因为考虑小孩的未来需要,终于下决心抽空把驾照考了。
这几天每天都是吃吃吃,每天都有相邻和亲戚来串门或者拜访,不得闲暇,今日有空,故记录流水账,以慰愧疚。
总的来说,因为自己做事的风格以及对自己的要求,工作都很忙,但今年格外忙,在加上母亲的意外和孩子的出生,2017是我人生中最煎熬的一年,希望未来越来越好。
特别感谢一直以来支持的朋友,如果没有你们一直以来的支持和关心,我可能在抑郁和压力中作出令人不敢想象的决定,在这里默默谢谢你们,也祝你们未来越来越好。
好久不搞stm8了,但朋友请教,还是帮忙确认下。主要是确认STM8的看门狗用法和喂狗时间问题,网上大把的代码样例,但是还是要刨根问底弄清楚细节,才可以用,否则就是埋雷。
大概的调用样例代码:
#define SYS_IWDG_OPEN IWDG_KR=0xCC;
#define SYS_IWDG_FEED IWDG_KR=0xAA;
void SystemIWDG_Config(void)
{
CLK_ICKCR|=S3;
while((CLK_ICKCR&S4)==0);
//STM8单片机需先执行0xCC指令,即先打开IWDG模块,否则IWDG工作不正常
IWDG_KR=0xCC; //启动看门狗
IWDG_KR=0x55; //使能模块访问
IWDG_RLR=0xFF; //溢出时间
IWDG_PR=0x06; //256分频 38000/256=148HZ T=6.7ms
IWDG_KR=0xAA; //装载IWDG->RLR
}
代码的解释请参见以下的网络内容:
STM8独立看门狗介绍 独立看门狗模块可以用于解决处理器因为硬件或软件的故障所发生的错误。它由一个内部的128kHz的LSI阻容振荡器作为时钟源驱动,因此即使是主时钟失效时它仍然照常工作。
键寄存器(IWDG_KR) 地址偏移值:0x00
预分频寄存器(IWDG_PR) 地址偏移值:0x01
重装载寄存器(IWDG_RLR) 地址偏移值:0x02
IWDG寄存器映像和复位数值
|
---|
官方手册原始内容,124页:
http://www.st.com/content/ccc/resource/technical/document/reference_manual/9a/1b/85/07/ca/eb/4f/dd/CD00190271.pdf/files/CD00190271.pdf/jcr:content/translations/en.CD00190271.pdf
本地下载备份:en.CD00190271
根据芯片手册中时钟的配置:
文章开头样例代码的看门狗最大喂狗时间大约1.725秒(38K时钟)
系统升级到最新的sierra后,执行pod update 失败:
zcj-macair:qinmi alex$ pod update -bash: /usr/local/bin/pod: /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby: bad interpreter: No such file or directory zcj-macair:qinmi alex$ brew install ryby Updating Homebrew... ==> Using the sandbox xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun Error: git cannot be built with any available compilers. Install GNU's GCC brew install gcc Error: Git must be installed and in your PATH! Error: No available formula with the name "ryby" ==> Searching for similarly named formulae... Error: No similarly named formulae found. ==> Searching taps... Error: No formulae found in taps.
按照提示安装对应的程序时,进一步提示错误,发现是xcrun错误。
更新xcrun环境:xcode-select --install
更新ruby:brew install ruby
更新pod:gem install cocoapods
设置 /etc/config/network:
config interface 'lan'
option ifname 'eth0.1 ra0'
option type 'bridge'
option proto 'dhcp'
option macaddr '00:0C:43:00:00:40'
按照模块的使用手册,我们知道设备的usb会虚拟出5个串口设备。
在openwrt中默认是支持usb转uart的驱动的,默认是可以支持此设备的,我们只要在menuconfig中选择相应的开关就可以完成支持
Kernel Modules → USB Support <*> kmod-usb2 <*> kmod-usb-ohci <*> kmod-usb-serial <*> kmod-usb-serial-option -*- kmod-usb-serial-wwan <*> kmod-usb-core
在网路上有大量的扫描程序和爬虫在扫描肉鸡,其中一个最常用的方式就是扫描ssh权限。这种肉鸡主要用来【翻腔】或者DDOS或者挖矿等,总之是可以牟利的。
新注册的vps,还没多久就发现:
There were 2816 failed login attempts since the last successful login.
而避免被暴力的一种简单的方法就是强制密钥登陆。
然后私钥就可以用来在客户端登录时使用,如果密钥没密码,就可以实现无密码登录了
作为一个ios开发者,在你调试APNs时,正常的情况下你需要弄好证书给到后台的同事上线到测试环境,然后才能开始测试调试推送的相关功能。
如果这个过程遇到证书错误,后台代码错误,苹果变更接口等,等到能调试ios的功能,需要等到好久的时间。
那么ios可以独立调试APNs的相关功能吗?当然可以,Knuff就是一款简洁简单的推送调试工具。下面的以MAC的为介绍对象,其他平台的请自行理解。
软件界面如下:
Custom:自定义模式,可以自行选择证书,我们测试自己的应用,就用这个模式
Knuff iOS: Knuff iOS表示使用Knuff的证书,直接推送给Knuff配套的ios应用。
Choose:选择推送的push证书,我们需要选择我们证书,关于如何生成正确的证书,请自行google。
Production:选择证书后,就会出现这个选择,production表示appstore证书,推送给appstore版本的APP。
Sandbox:表示开发调试的非AppStore版本。
Priority:测试时可随意选择。
Payload:表示要推送的报文,具体字段含义这里就不展开了,请自行了解。
Token:device token,在注册苹果 APNs服务时获取的。参考代码如下:
注册服务
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings
settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge)
categories:nil]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
回调事件
调用didRegisterForRemoteNotificationsWithDeviceToken
至此我们就可以开始测试了,通过这个工具我们就能轻易的测试我们的device token是否正确,测试我们生成的证书是否正确。给自己发送任意想测试的payload。
have fun!
关于APNs的工作原理,网上有大量的文章,建议学习apple的官方文档。通过APNs我们就可以通过服务器想APP推送想要的内容和事件。从而实现通知或者激活应用的目的。本文我们讲介绍如何搭建php的APNs推送以及如何实现静默推送。
经过多方的验证,目前推荐这个:
https://github.com/immobiliare/ApnsPHP
想要通过苹果服务器推送信息,必须要有合法的证书。很多人在推送这部分花了很多时间,很多情况是没搞清楚失败到底是代码的问题还是证书的问题。所以,我们需要先验证证书的合法和正确性。
推送时,我们要制作推送证书,我们要选择正确的类型,具体的制作过程可自行搜索,最终的证书类型如下:
先前我的文章推荐过Knuff,经过深入的实践,这里我推荐Easy APNS Provider,可以从MAC store下载。相比较Knuff,EAP更加的稳定强大。通过工具我们就可以先行验证证书的正确性,避免后面定位问题浪费更多的时间。
[2020.03.31更新]:另一款值得推荐的是: https://github.com/noodlewerk/NWPusher
在MAC上用客户端向苹果发送推送服务器请求时,我们选择上面安装的证书就可以了。
上面我们讲了怎么选择正确的客户端证书,当我们使用php 服务器推送时,我们还要做些额外的工作:
#生成cert.pem
openssl pkcs12 -clcerts -nokeys -out cert.pem -in cert.p12
#生成key.pem(先输出导出key.p12时设置的密码P*d, 然后设置一个新的密码,如pushpwd,这个密码后面php推送时要设置)
openssl pkcs12 -nocerts -out key.pem -in key.p12
#合并成ck.pem
cat cert.pem key.pem > ck.pem
这个软件包的最新版本支持HTTP2,如果你的PHP的版本支持HTTP2,建议优先使用。开发包里面自带了几个sample,简单配置后基本就可以使用。这里我们以sample_push.php为测试对象。
如图所示,配置要点如下:
测试通过的返回如下:
Fri, 13 Jan 2017 13:31:35 +0100 ApnsPHP[15355]: INFO: Trying tls://gateway.sandbox.push.apple.com:2195... Fri, 13 Jan 2017 13:31:35 +0100 ApnsPHP[15355]: INFO: Connected to tls://gateway.sandbox.push.apple.com:2195. Fri, 13 Jan 2017 13:31:35 +0100 ApnsPHP[15355]: INFO: Sending messages queue, run #1: 1 message(s) left in queue. Fri, 13 Jan 2017 13:31:35 +0100 ApnsPHP[15355]: STATUS: Sending message ID 1 [custom identifier: Message-Badge-3] (1/3): 167 bytes. Fri, 13 Jan 2017 13:31:36 +0100 ApnsPHP[15355]: INFO: Disconnected.
在上面我们提到了设备的device token,那么调试阶段如何获取这个token呢?在我们发起了注册请求后,系统会触发相应的消息回调。相关的参考代码如下:
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
//读取APNS token
NSString* _deviceToken = [[[[deviceToken description]
stringByReplacingOccurrencesOfString: @"<" withString: @""]
stringByReplacingOccurrencesOfString: @">" withString: @""]
stringByReplacingOccurrencesOfString: @" " withString: @""];
QMLogDebug(@"apns token:%@",_deviceToken);
NSUserDefaults * userDefault = [NSUserDefaults standardUserDefaults];
[userDefault setObject:_deviceToken forKey:APNSTOKEN];
[userDefault synchronize];
}
上面的deviceToken就获取了我们需要的token。这里的deviceToken是NSData对象,可以手动导出二进制,然后这个导出文件就可以在测试客户端中使用。
除了ck.pem证书,我们的项目还需要 entrust_root_certification_authority.pem 这个证书,一共两个证书。
ios最新的版本中已经支持了静默推送,静默推送时,客户端会收到消息,执行相应的动作,但不会做任何给用户的提示。在普通的推送中我们可以通过如下的代码实现静默推送的效果:
{
"aps" : {
"badge" : 0
}
}
但是苹果还是专门定义了一个开关来表示静默推送 "content-available" : 1,由于此开关优先级较低,在静默推送的报文中不能出现alert,sound 等,否则就会变成普通推送。
静默推送的payload如下:
{
"aps" : {
"content-available" : 1
}
}
静默推送的前提:
参考:
How to generate a Push Notification certificate and download the Entrust Root Authority certificate
首选当时letsencrypt了,官方网站是:https://letsencrypt.org. 网上大把文章,但按照本人一贯的习惯还是去官网,避免被过时的信息误导,反而浪费更多的时间。
官方推荐的是cetrbot:https://certbot.eff.org/
根据本人的系统,实际的文档路径:https://certbot.eff.org/#centosrhel7-nginx
首先需要安装certbot:
默认centos7是不支持certot,你需要先安装EPEL:https://fedoraproject.org/wiki/EPEL#How_can_I_use_these_extra_packages.3F
实际的安装包为:https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
下载后安装rpm。然后执行:
sudo yum install certbot
一路‘y’,安装完成:
Installed:
certbot.noarch 0:0.9.3-1.el7
Dependency Installed:
dialog.x86_64 0:1.2-4.20130523.el7 pyOpenSSL.x86_64 0:0.13.1-3.el7 python-cffi.x86_64 0:1.6.0-5.el7
python-chardet.noarch 0:2.2.1-1.el7_1 python-enum34.noarch 0:1.0.4-1.el7 python-idna.noarch 0:2.0-1.el7
python-ipaddress.noarch 0:1.0.16-2.el7 python-ndg_httpsclient.noarch 0:0.3.2-1.el7 python-parsedatetime.noarch 0:1.5-3.el7
python-ply.noarch 0:3.4-10.el7 python-psutil.x86_64 0:2.2.1-1.el7 python-pycparser.noarch 0:2.14-1.el7
python-requests.noarch 0:2.6.0-1.el7_1 python-six.noarch 0:1.9.0-2.el7 python-urllib3.noarch 0:1.10.2-2.el7_1
python-zope-component.noarch 1:4.1.0-1.el7 python-zope-event.noarch 0:4.0.3-2.el7 python-zope-interface.x86_64 0:4.0.5-4.el7
python2-acme.noarch 0:0.9.3-1.el7 python2-certbot.noarch 0:0.9.3-1.el7 python2-configargparse.noarch 0:0.11.0-1.el7
python2-cryptography.x86_64 0:1.3.1-3.el7 python2-dialog.noarch 0:3.3.0-6.el7 python2-mock.noarch 0:1.0.1-9.el7
python2-pyasn1.noarch 0:0.1.9-7.el7 python2-pyrfc3339.noarch 0:1.0-2.el7 pytz.noarch 0:2012d-5.el7
Complete!
在已经有webserver运行的情况下,certbot推荐我们使用“webroot”插件。可以实现在不暂停web服务的情况下更新证书。
webroot:不需要停机你的web服务
certbot certonly --webroot -w AAA -d BBB
BBB是你要支持的域名,AAA是BBB当前已经可以访问的目录。
standalone:需要停机你当前服务器的80端口的服务
certbot certonly --standalone -d xxx.com
以上每一条命令生成一个对立的目录,如果是多个域名就是合在一起的一个文件。如果要每个域名都生成独立的目录和文件,就要执行多次。
成功后:
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/xxx/fullchain.pem. Your cert
will expire on 2017-03-18. To obtain a new or tweaked version of
this certificate in the future, simply run certbot again. To
non-interactively renew *all* of your certificates, run "certbot
renew"
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
手动在nginx的conf中配置相关的路径就可以了:
ssl_certificate /etc/letsencrypt/live/xxx/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/xxx/privkey.pem;
certbot renew
证书没有过期的话,我们可以撤销:
[root@rxblog certbot-0.22.2]# ./certbot revoke --cert-path /etc/letsencrypt/archive/xxx.com/cert1.pem
Saving debug log to /var/log/letsencrypt/letsencrypt.log
-------------------------------------------------------------------------------
Would you like to delete the cert(s) you just revoked?
-------------------------------------------------------------------------------
(Y)es (recommended)/(N)o: Y
-------------------------------------------------------------------------------
Deleted all files relating to certificate iwwenbo.com.
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
Congratulations! You have successfully revoked the certificate that was located
at /etc/letsencrypt/archive/iwwenbo.com/cert1.pem
-------------------------------------------------------------------------------
如果证书已经过期了,我们只能删除了
certbot delete --cert-name example.com
OK,暂时告一段落。