iOS App 连接外设的几种方式
原创作者: Max_Marry
文章地址: http://www.jianshu.com/p/852bf92c5c92
随着近年来车联网和物联网的兴起,智能家居和智能硬件的逐步火热,越来越多的 App 被用来跟硬件设备进行来连接,获取硬件相关信息用以展示或者发送指令控制硬件来提供服务。
iOS App 连接外设的常用方式可以分为三大类:
网络端口
建立 Socket 使用 TCP/IP 协议族进行通信,天然支持多通道,想要几个通道就建几个 Socket 就可以。它主要有三种方式,
Wi-Fi 连接
优点:
简单,不需要集成 MFi 芯片
只要对应的硬件有无线网卡,然后将手机和硬件连接到同一个局域网中就可以使用 Socket 通过网络协议通信
缺点:
无线连接信号容易受到干扰,不太稳定,容易断开
如果硬件使用的场合没有公共 Wi-Fi,就需要手机自建热点共享,硬件进行热点接入,操作步骤较多,对用户来说学习使用成本较高,并且热点共享要求手机本身的数据移动网络是稳定的,在没有移动数据网络信号的地方,热点无法建立。
USB 热点共享
这个其实跟 Wi-Fi 中的热点共享非常类似,也不需要集成 MFi 芯片。
优点:
USB 热点共享,走的是有线,不容易受到干扰,更稳定,
iPhone 可以边使用可以边充电
缺点:
操作步骤比较复杂,需要先打开个人热点共享
NCM
就是把 USB 端口虚拟成标准的网络端口,然后手机和外设就能通过有线网络直连了,可以理解成手机和外设通过一跟网线连起来了,然后就可以用 Socket 通过 TCP,UDP 进行通信了。
优点:
有线连接,非常稳定,带宽足够
不依赖移动网络信号
缺点:
需要集成 MFi 芯片并进行 MFi 认证,有一定门槛
除了 CarPlay,其他跟 iPhone 连接的外设都不能使用 NCM 的方式跟 iPhone 上的 App 进行连接和通信
EAP
EAP 全拼是 External Accessory Protocol,即外部设备协议。这个是苹果推荐使用的外设连接方式。需要外设集成 MFi 芯片进行 MFi 认证。手机端开发相对简单,只要集成 iOS 系统提供的一个框架 ExternalAccessory.framework,并且在 info.plist 中配置好协议字符串 (Supported external accessory protocols),当 iOS 设备通过 USB 或者蓝牙连接到对应硬件时,iOS 系统会把符合 MFi 认证要求的外设抽象成了一个流对象,App 通过指定的协议字符串来创建一个 EASession 类的实例来访问到该流对象,就能通过 NSInputStream 和 NSOutputStream 跟硬件件进行通信了。
EASession 模式:它的带宽相对较低,但是允许同时通过多个协议字符串创建多个会话,也就是说直接支持多通道
Native Transport 模式:它的带宽足够大,理论值是 100MB 以上,但是不支持多通道,如果业务层需要支持多数据通道的话需要 App 自己进行通道的复用与拆分,并且 Native Transport 需要 iPhone 工作在 USB Host 模式,硬件需要支持 USB 模式切换
关于如何使用 EAP 跟外部设备进行通信,可以参考苹果官方的 Demo (https://developer.apple.com/library/content/samplecode/EADemo/Introduction/Intro.html)进行入门和学习。
BLE
BLE 即低功耗蓝牙,是 iOS7.0 以后才支持的连接方式。
优点:不需要集成 MFi 芯片做认证,功耗低,手机端开发也相对简单,集成 iOS 系统提供的 CoreBluetooth.framework 即可
缺点:带宽很低,一般适合于只需要传输少量数据的场景。比如各种智能硬件,像智能水杯,智能体重计,运动手环等,都是采用这种连接方式
总结一下,图中带 MFi 字样的表示该连接方式需要硬件集成 MFi 芯片,做 MFi 认证。关于苹果的 MFi 认证,对 iOS 开发中来说其实是一个比较陌生并且繁琐的 Topic,原因如下:
网上鲜有资料,Google 基本上查不到。 因为 MFi 认证是由硬件生产商主导进行的,苹果首先对硬件生产商的实力 (质量,信誉,生产规模) 有很苛刻的要求,满足要求的才有进行 MFi 认证的资格。满足 MFi 认证资格要求的硬件生产商,提交了 MFi 产品计划后才能得到苹果 MFi 开发的官方文档,这个文档是带水印的,不允许外泄
MFi认证周期很长,过程也很复杂
苹果官方沟通渠道很窄,电话打不通,邮件回复不及时
关于 MFi 申请的一些事情
什么是 MFi 认证?
苹果 MFi 认证,是苹果公司(Apple Inc.)对其授权配件厂商生产的外置配件的一种标识使用许可,是 Apple 公司 “Made for iOS” 的英文缩写。
为什么要做 MFi 认证?
从苹果角度来看,为了更好的巩固苹果的生态圈,只有集成了有
MFi 芯片,才能跟 iPhone、iPod,iPad 进行连接通信。而只有经过了 MFi 认证的企业才能批量购买 MFi 芯片,并且都 MFi 芯片的供销链条都有很严格的监督管理,所以这样苹果可以严格控制只有那些满足苹果规范和要求的外设才能加入到苹果生态圈。从生产厂商来看,经过苹果官方授权,配件产品能完美兼容苹果智能设备。提交 MFi 认证过程中,硬件设备需要经过苹果要求的
ATS 自测以及苹果的严格测试,产品质量更有保证。消费者也更加信任经过了 MFi 认证授权的配件;最后成功获得 MFi 授权这也成为技术与质量实力的一种标志,因为 MFi 认证通过率仅 2%,其中大部分企业因为申请资格不符合直接被拒绝。从 iOS 开发人员来看,MFi 认证是由硬件生产商主导进行申请的,是苹果对外设配件的一种认证和授权。但是很多外设跟苹果进行连接,并不只是跟 iOS 设备硬件或者 iOS 系统配合就可以完成对应的功能 (比如充电、CarPlay、播放 iPod 音乐 (A2DP)、接听蓝牙电话 (HPF) 或者提供 GPS 输入源等)。很多时候为了实现特定的需求,需要由 iOS App 的配合,由 iOS App 跟对应外设进行连接和通信,传输相关的控制命令对外设进行控制,或者传输相关的外设数据进行展示。iOS App 跟外设的连接方式有网络、EAP 和 BLE,其中 EAP 是苹果官方推荐的跟外设连接的方式。只有经过 MFi 认证的外设才能使用 EAP 跟 App 进行通信。
如何做 MFi 认证?
MFi 认证的流程比较复杂,可以归纳总结为三个部分,如下图所示。
其中黄色背景标注的部分是可能跟 iOS App 开发者相关的。
一、申请人提交申请资料
首先,收集公司资料信息,这些资料主要包括了认证负责人联系信息,企业情况介绍,公司组织架构、企业网站,物料品质控制以及 ISO 体系证书等资料。然后是在苹果 MFi 官网(mfi.apple.com)上进行注册,并提交第一步收集到的公司资料,进行账号申请。
接下来苹果会进行 MFi 体系审核。这个是非常关键的一个步骤。 主要考察公司对 MFi 芯片的管理体系,看公司是否有规范的流程和系统来管理 MFi 芯片,能有效防止转售芯片或者挪用芯片 (把芯片用到未通过 MFi 认知的项目上),苹果会安排专人或者代理公司来抽查。
如果 MFi 体系审核过了,苹果还会对公司其他情况进行考察,来评估该公司是否满足 MFi 会员的资格。审核的标准主要看公司相关资质,是否有较大的生产规模;是否拥有自主品牌;品牌在业内是否有较高的地位 (主要表现为各类荣誉);是否曾为其他国际知名企业供货;研发人员是否达到苹果要求的人数等,申请者一定保证申报资料的真实性,苹果公司都会一一核实。
如果这些条件都满足,恭喜你公司成为了 MFi 会员,能够有资格购买样品芯片,并且拿到苹果提供的 MFi 官方开发文档,该文档的每一页都是带有申请人姓名水印的,禁止对外公开,如果被发现,有可能会被取消 MFi 会员资格。据说大部分的企业都会被卡在会员资格审核这一步。
二、提交产品计划,研发和自测
如果你的公司是属于那幸运的那一小部分通过了 MFi 会员资格审核,拿到了苹果的 MFi 研发官方文档,也购买了 MFi 样品芯片,那么就可以提交产品计划,进行产品研发和自测了。
提交产品计划是非常关键的一步,需要根据要研发的公司产品的形态、所用技术方案和需要支持的 iOS 设备、iOS 的相关信息都进行详细的描述,其中比较重要信息有。
(1) 附件概览 (Accessory Overview)
技术方案 (Technology) 如果你是做支持 CapPlay 的车机,那么就选择 CarPlay,否则都应该选择 iAP;如果你的硬件需要跟 iPhone 连接,并且处理相关业务,而不仅仅是充电线或者数据线,那么在 Components 里应该选择 Authentication coprocessor。
(2) 固件和硬件 (Firmware & Hardware)
现在所有的 MFi 认证的硬件都需要支持 iAP2 协议,所以必须要选
iAP2 或者同时支持 iAP2 和 iAP1。然后外设硬件跟苹果设备是如何通信的,是使用 USB 的 Host 模式,还 USB 的 Devices 模式,还是串口或者蓝牙,这个需要根据产品的需求、特性进行选择。
(3) 选择硬件所支持的 iAP2 的特性
(4) 选择所支持的苹果设备型号
根据产品的设计选择所需要支持的苹果设备型号,包括 iPad,iPhone 和 iPod 的各种型号。
(5) App 相关的信息
这部分也是 iOS 开发者需要重点关注的部分,包括 App 的版本号,BundleID 和协议字符串以及 iOS App 的主要功能特性描述,这部分信息需要跟最后送 MFi 审核时附带的 App 测试包的信息保持一致。提交了产品计划之后,就可以拿到 PPID (Product Plan ID)。这个 PPID 也是跟 iOS App 开发者需要关注的。当 App 开发完成,提交 AppStore 上线时,需要在版本审核备注信息里带上这个 PPID,否则审核是过不了的。
接下来就可以进行产品研发了。主要是硬件生成商需要根据苹果提供的开发文档进行硬件和驱动认证程序的开发。而 iOS App 开发者则主要是需要成 iOS 系统提供的一个系统框架 ExternalAccessory.framework,并且在 info.plist 中配置好协议字符串 (Supported external accessory protocols)。当 iOS 设备通过
USB 线或者蓝牙连接到对应硬件时,iOS 系统会把符合 MFi 认证要求的外设抽象成了一个流对象,App 通过指定的协议字符串来创建一个 EASession 类的实例来访问到该流对象,就能通过
NSInputStream 和 NSOutputStream 跟硬件件进行通信了。这部分功能实现可以参考苹果官方的 EADemo( https://developer.apple.com/library/content/samplecode/EADemo/Introduction/Intro.html )进行入门和学习。
产品研发完成后需要进行 ATS (Accessory Test System) 自测,并提供自测报告。ATS 自测苹果会提供 ATS Box 的测试工具和软件,主要是针对硬件进行电气特性相关的测试,包括各个节点的电压电流值是否满足苹果要求,然后传输带宽是否稳定,是否达到苹果要求等等。
自测完成之后就可以把硬件和所配套的软件 (iOS App 的 ipa 安装包) 送到苹果指定的测试实验室进行认证测试。iOS 开发者在这个步骤需要关注的是如何打包 ipa 包。因为如果直接用开发证书打包,那么苹果测试人员的 iPhone 不在你开发证书的设备列表中,是无法安装的。如果用企业证书打包的话,可能 AppStore 发布证书对应的 BundleID 跟企业证书的 BundleID 不一致,所以也不可行。所以推荐的做法是,等到产品研发完成和自测之后,就带上产品计划中拿到的 PPID,提交 AppStore 进行审核。等审核通过之后,就可以直接从 AppStore 下载对应的 ipa 安装包,配合硬件一起送 MFi 认证测试了。
三、测试审核和批量生产
这个阶段也是硬件生产商主导进行的,跟 iOS App 开发者关系不大。当硬件的 MFi 认证送审通过之后,还需要对产品的包装也提交认证和审核。审核通过之后,就可以获得苹果授权进行 MFi 芯片的批量购买,然后根据销售计划进行硬件的批量生产和销售了。
整个 MFi 认证的周期大概需要3个月到半年的时间,并且每次提交认证测试都需要支付一笔600美金的测试费用,所寄去测试的硬件测试样品苹果也是不会寄回来的。
iOS 外设连接黑科技,不需要 MFi 认证,实现 USB 连接
USBMuxd,利用这种连接方式不需要做 MFi 认证,支持 iPhone 上的 App 跟外设通过进行通信,非常方便。
基本原理
iPhone 的 iOS 系统中自带了 USBMuxd 服务,该服务能够实现
USB-TCP 协议的转换,能够把 USB 的端口映射到本机 (localhost) 的 TCP 端 (基于 Unix Domain Socket )。只需要在外设端也实现一个 USBMuxd 服务,并指定端口映射关系, 那
iPhone 的 App 和外设上的应用就可以使用 Socket 进行 TCP 进行通信了。
一个开源实例
开源项目 peertalk( https://github.com/rsms/peertalk ) 就是一个完整的使用 USBMuxd 方式实现 iPhone App 跟 Mac App 进行 TCP 通信的例子。因为 Mac OS 系统中天生就自带了 USBMuxd 服务,所以 peertalk 的 Mac 端程序是比较简单的。外设一般都不会是 Mac 系统,而是 Android 或者 Linux 系统,那怎么办呢?那就自己在系统中集成 USBMuxd 服务,这里可以利用到 libimobiledevice( https://github.com/libimobiledevice ) 实现在外设上集成 USBMuxd 服务。
MFi iOS App 端开发步骤
与附件设备通讯的 App 需设备支持的协议,这些协议由设备制造商维护,可是自定义或标准协议,标准协议可与其他设备通信,iOS不负责这些协议的维护。
为防止命名空间冲突,推荐使用反 DNS 形式命名协议,如
com.apple.myProtocol、com.dji.video、com.dji.protocol、com.dji.common。
1、编程步骤
1.1、引入框架与头文件
外部附件框架 (ExternalAccessory.framework) 为 App 与附件设备通信提供了桥梁。因此,在 Xcode 项目中,需要为每个与附件设备通信相关的项目添加 ExternalAccessory.framework。
下一步是引入头文件 #import <ExternalAccessory/ExternalAccessory.h>
。
1.2、声明App支持的协议
不声明协议直接调用EA框架的类会崩溃。
使用 UISupportedExternalAccessoryProtocols 键在 Info.plist 中声明支持的协议,值为数组,数组的元素为支持的协议,元素的顺序任意且不限数量。这些值只用于判断 App 与附件设备的通信能力。当App与设备通信时,具体通信协议由我们编程决定。
当附件设备插入 iOS 设备时,系统才知道 App 可被新插入的设备启动。若当前已安装的 App 都没注册协议,则系统可能到 App Store 去搜索支持新设备声明的协议的 App。
UISupportedExternalAccessoryProtocols
对应的值虽说可参考UISupportedExternalAccessoryProtocols( https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/iPhoneOSKeys.html#//apple_ref/doc/uid/TP40009252-SW4 ),实际此链接并没给出有帮助的信息,《MFi Accessory Interface Specification for Apple Devices》也没给出所谓标准协议的字符串值。
1.3、开始通信
创建 EASession。此对象管理与附件设备交互的情况,它与底层系统工作,在设备上来回传输数据。一旦会话建立,数据通过
NSInputStream 和 NSOutputStream 的实例在 App 中传输。收发的数据包的格式由与附件设备通信的协议决定。接收数据。使用自定义委托对象,监视 NSInputStream 实例可从附件设备接收数据。
发送数据。向 NSOutputStream 写入数据包即可发送至附件设备。
1.4、一个读取外接设备的示例
Info.plist 中加入 Supported external accessory protocols,值为 com.apple.p1。这个只是令系统认为我们的应用有能力与外接设备沟通,这里使用 Lightning USB Camera Adapter 测试。
读取外接设备信息代码:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSMutableString *info = [[NSMutableString alloc] initWithCapacity:1024];
EAAccessoryManager *manager = [EAAccessoryManager sharedAccessoryManager];
NSArray<EAAccessory *> *accessArr = [manager connectedAccessories];
for (EAAccessory *access in accessArr) {
for (NSString *proStr in access.protocolStrings) {
[info appendFormat:@"protocolString = %@\n", proStr];
}
[info appendFormat:@"\n"];
[info appendFormat:@"manufacturer = %@\n", access.manufacturer];
[info appendFormat:@"name = %@\n", access.name];
[info appendFormat:@"modelNumber = %@\n", access.modelNumber];
[info appendFormat:@"serialNumber = %@\n", access.serialNumber];
[info appendFormat:@"firmwareRevision = %@\n", access.firmwareRevision];
[info appendFormat:@"hardwareRevision = %@\n", access.hardwareRevision];
[info appendFormat:@"dockType = %@\n", access.dockType];
}
dispatch_async(dispatch_get_main_queue(), ^{
label.text = info;
});
});
运行结果为:
manufacturer = Apple
name = Apple USB Camera Adapter
modelNumber = A1440
serialNumber =
firmwareRevision = 1.0.0
hardwareRevision = 1.0.0
dockType = (null)
1.5、与外接设备交互数据的示例
如下代码展示与 DXO One 相机通信。
在非 UI 线程中打开设备,否则可能导致程序崩溃。
EAAccessoryManager *manager = [EAAccessoryManager sharedAccessoryManager];
NSArray<EAAccessory *> *accessArr = [manager connectedAccessories];
if (accessArr.first) {
EASession *session = [[EASession alloc] initWithAccessory:accessArr.firstObject forProtocol:@"com.dxo.one.protocol"];
if (!session) return;
NSInputStream *inputStream = [session inputStream];
if (!inputStream) {
// LOG inputStream = null
}
inputStream.delegate = self;
[inputStream open];
}
实现 NSStreamDelegate 协议
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode {
// LOG stream & event code
switch (eventCode) {
case NSStreamEventNone:
break;
case NSStreamEventOpenCompleted:
// 开始读取
break;
case NSStreamEventHasBytesAvailable:
// 获取可读数据大小,读取流才有效。
break;
case NSStreamEventHasSpaceAvailable:
// 获取可写空间大小,写入流才有效。
break;
case NSStreamEventErrorOccurred:
// 出错处理
break;
case NSStreamEventEndEncountered:
// 读取结束
break;
}
}
2、ExternalAccessory框架
1、EAAccessory
提供一个已连接的设备的信息,如制造商,固件版本等。
2、EAAccessoryManager
协调MFi设备与iOS设备之间的工作。
3、EASession
用来创建 App 与附件设备之间的通信通道。
4、EAWiFiUnconfiguredAccessory
提供未配置的 MFi Wireless Accessory Configuration 设备的信息给 App。
5、EAWiFiUnconfiguredAccessoryBrowser
让 App 访问 MFi Wireless Accessory Configuration 进程。
3、开发技巧
Lightning 接了设备则不能连接计算机,所以直观的做法是,将日志用 UITextView 显示出来。写成日志就得每次都拔掉设备,插上电脑,如此反复。
另一个办法是,通过蓝牙测试传输协议,手机连接电脑,可单步调试。验证完再用 Lightning 连接设备联调。
因本人目前在做关于 iOS App 连接外设方面的工作,因此搜集查找相关信息,文章中信息出自于以下简友:我是云峰小罗、熊皮皮,在此对两位的分享表示感谢。
相关文章:

Android深度探索(卷1)HAL与驱动开发第五章总结
开发板是开发和学习嵌入式技术的主要硬件设备,开发板的型号和种类很多,目前流行的是基于S3C6410 ARM11架构的开发板,S3C6410是由三星公司推出的一款低功耗,高性价比的RISC处理器,它基于ARM11内核,可广泛应用…

controlfile
1、如何恢复控制文件 Your database instance is started using the server parameter file (SPFILE). Control files are multiplexed and stored on different disks. Because of a disk failure, you lost one of these control files. You replaced the damaged disk. What…

Spring servlet
1、修改pom.xml文件,添加以下内容: 代码: <dependency><groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> <dependency> <groupId>org.apac…

iOS传感器:实现一个随屏幕旋转的图片
作者 非典型技术宅 关注 2017.05.24 17:22* 字数 1568 阅读 351评论 7喜欢 14在写上一个动画系列的时候学到了非常多的知识,也认识了很多人。例如受邀进入了某个神秘的动效组织,全是一线的大神啊。有UI的大牛、UED的大神、iOS的大神。加入组织可以阅读这…

构建之法-读后感
大二快结束,从大二初开始接触项目的工程开发,到现在也差不多一年了。之前一直在用c# 结合winform开发一些简单的桌面应用,也看过一些是实验室学长们用c#和其他多种技术结合 开发出来的系统, 接触过其源代码,为深入了解…

Java 理论与实践: 非阻塞算法简介——看吧,没有锁定!(转载)
简介: Java™ 5.0 第一次让使用 Java 语言开发非阻塞算法成为可能,java.util.concurrent 包充分地利用了这个功能。非阻塞算法属于并发算法,它们可以安全地派生它们的线程,不通过锁定派生,而是通过低级的原子性的硬件原…

pring Boot与MyBatista的集成
1、准备数据库环境,在MySQL数据库中,创建一个名为microservice的数据库,在microservice中创建表tb_user,并在表中插入3条数据; 2、创建项目,添加依赖。 3、编写配置文件,在application.properti…

iOS中UIDynamic物理仿真详解
本文中所有代码演示均有GitHub源码,点击下载 UIDynamic简介 简介: UIKit动力学最大的特点是将现实世界动力驱动的动画引入了UIKit,比如动力,铰链连接,碰撞,悬挂等效果,即将2D物理引擎引入了UIKi…

ADO与ADO.NET的区别与介绍
1. ADO与ADO.NET简介ADO与ADO.NET既有相似也有区别,他们都能够编写对数据库服务器中的数据进行访问和操作的应用程序,并且易于使用、高速度、低内存支出和占用磁盘空间较少,支持用于建立基于客户端/服务器和 Web 的应用程序的主要功能。但是A…

cucumber 文件目录结构和执行顺序
引用链接:http://www.cnblogs.com/timsheng/archive/2012/12/10/2812164.html Cucumber是Ruby世界的BDD框架,开发人员主要与两类文件打交 到,Feature文件和相应的Step文件。Feature文件是以 feature为后缀名的文件,以Given-When-T…

Spring Boot与Redis的集成
1、在Linux中安装Redis。 1.1、在线下载软件 1.2、安装软件 1.3、修改配置文件 1.4、启动Redis; 2、添加Redis起步缓存,在pom.xml中添加Spring Boot支持Redis的依赖配置。 3、添加缓存注解。 3.1、在引导类Application.java中,添加EnableCac…

Redis3.0 配置文件说明
背景: 以前有篇文章已经结果过了,现在复习一下,对Redis3.0进行说明: 参数说明: #redis.conf # Redis configuration file example. # ./redis-server /path/to/redis.conf################################## INCLUDES…
Core ML 文档翻译
概览 借助 Core ML,您可以将已训练好的机器学习模型,集成到自己的应用当中。 所谓已训练模型 (trained model),指的是对一组训练数据应用了某个机器学习算法后,所生成的一组结果。举个例子,通过某个地区的历史房价来训…

jquery radio 取值
网上流行的说法就是 $(input[nameaaa][checked]).val()能取到选中项的value,但我测试后发现只在IE下有效,在firefox和Chrome中不论选中哪一项,或者不选,取到的值都是第一项的value正确做法应该是 $("input[nameaaa]:checked&…

Spring Boot与ActiveMQ的集成
1、ActiveMQ软见得安装配置 1.1、上传软件包并解压 1.2、配置并启动 1.3、浏览器验证 2、添加ActiveMQ起步依赖; 3、创建消息队列对象,在Application.java中编写一个创建消息队列的方法,其代码展示如下; 4、创建消息生产者&#…
iOS图片精确提取主色调算法iOS-Palette(附源码)
源码可见:[直接点击] 1.背景 图像提取主色调来增强浸入式交互体验的场景越来越常见,如知乎网页版的个人主页,Instagram的图片色调筛选。那如何去获得一张照片的主色调呢?Google在Android.support.v7里,给出了一个叫做Palette(调色…

jQuery UI 之 LigerUI 快速入门
LigerUI 快速开发UI框架 LigerUI 是基于jQuery 的UI框架,其核心设计目标是快速开发、使用简单、功能强大、轻量级、易扩展。简单而又强大,致力于快速打造Web前端界面解决方案,可以应用于.net,jsp,php等等web服务器环境。 LigerUI有如下主要特…

HTML5标签学习之~~~
<article> 标签 article 字面意思为“文章”。在web页面中表现为独立的内容,如一篇新闻,一篇评论,一段名言,一段联系方式。这其中包括两方面,一为整个页面的主旨内容,另外就是一些辅助内容。<arti…

将Spring Boot项目打包成jar包war包
任务一:将Spring Boot项目打包成jar包 1、在pom.xml文件中添加依赖 2、通过cmd命令行来进行打包jar包(首先进入项目的目录中) 3、进入项目中的target目录下查看包 4、使用命令执行jar包; 5、浏览器查看输出结果 任务二࿱…
手把手教你在应用里用上iOS机器学习框架Core ML
2017-06-10 Cocoa开发者社区2017年的WWDC上,苹果发布了Core ML这个机器学习框架。现在,开发者可以轻松的使用Core ML把机器学习功能集成到自己的应用里,让应用变得更加智能,给用户更牛逼的体验。 Core ML是做什么的 我们知道&…

Linux服务器安装JDK、Tomcat配置web网站
安装JDK cd /usr/java/jdk【打开目录】 tar -xvzf jdk-7u79-linux-x64.gz【解压安装包】 vi ~/.bashrc【编辑环境变量】############################export JAVA_HOME/usr/java/jdk/jdk1.7.0_79export JAVA_BIN$JAVA_HOME/binexport JAVA_LIB$JAVA_HOME/libexport CLASSPATH.…

sql help cs
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Configuration;using System.Data;using System.Data.SqlClient;using System.Collections; /// <summary> /// SQLHelper 的摘要描述 /// </summary>publ…

Spring Cloud应用开发(一:使用Eureka注册服务)
1、搭建maven父工程; 注:在MyEclipse中,创建一个Maven父工程cloud,并在工程的pom.xml中添加Spring Cloud的版本依赖等信息。 2、搭建服务端工程。 注:在父工程cloud中,创建Maven子模块ms-spring-eureka-s…
SRWebSocket源码浅析(上)
2017-06-12 涂耀辉 Cocoa开发者社区一. 前言: WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——可以通俗的解释为服务器主动发送信息给客户端。 区别于MQTT、XMPP等聊天的应用层协议,它是一个传输通讯协…

Mason 简单笔记
Mason的对象 ------------------------------- Request对象 Mason有两个全局预处理对象叫做:$r和$m $r是mod_perl的请求对象,它提供了Perl的API来执行Apache的请求。 $r->;uri #获得用户请求的地址 $r->;content_type #获得…

多级页表如何节省内存
在谈到多级页表的优势的时候,很多地方都是这么说的:32位地址空间的分页系统,如果页面大小为4KB,则每个进程可达1M个页,假设每个页表项占用4个字节,这样每个进程仅仅页表项就占用了4MB连续的内存空间。 那么…

Spring Cloud应用开发(二:实现服务间的调用)
1、搭建订单服务工程。 注:在父工程cloud中,创建Maven子模块ms-spring-eureka-server; 1.1、添加依赖,在pom文件中添加Eureka依赖; 1.2、写配置文件,在配置文件中添加Eureka服务实例的端口号、服务端地址等…

webSocket详解
前言 本文会用实例的方式,将iOS各种IM的方案都简单的实现一遍。并且提供一些选型、实现细节以及优化的建议。 注:文中的所有的代码示例,在github中都有demo: iOS即时通讯,从入门到“放弃”?(demo) 可以打…

2013多校第三场
hdu 4629 题意:给你n个三角形,问覆盖1~n次的面积各是多少,n < 50; 分析:取出所有端点和交点的x坐标,排序,然后对于每一段xi~xi1的范围的线段都是不相交的,所以组成的 面积要么是三角形&#…

React+Reflux博客实践
年初用ReactExpressMongodb写的一个简单的博客。分享给各位朋友参考。 前端:ReactReact RouterRefluxReact-BootstrapWebpack后端:Express(Node.js)Ejs(Index)Mongoose(mongodb) 博客Demo地址:http://itdotaerblog.herokuapp.comGithub Addre…