高级知识点之进阶
1、什么是Socket?
Socket又称之为“套接字”,是系统提供的用于网络通信的方法。它的实质并不是一种协议,没有规定计算机应当怎么样传递消息,只是给程序员提供了一个发送消息的接口,程序员使用这个接口提供的方法,发送与接收消息。
Socket描述了一个IP、端口对。它简化了程序员的操作,知道对方的IP以及PORT就可以给对方发送消息,再由服务器端来处理发送的这些消息。所以,Socket一定包含了通信的双发,即客户端(Client)与服务端(server)。
2、Socket的通信过程?
每一个应用或者说服务,都有一个端口。比如DNS的53端口,http的80端口。我们能由DNS请求到查询信息,是因为DNS服务器时时刻刻都在监听53端口,当收到我们的查询请求以后,就能够返回我们想要的IP信息。所以,从程序设计上来讲,应该包含以下步骤:
1)服务端利用Socket监听端口;
2)客户端发起连接;
3)服务端返回信息,建立连接,开始通信;
4)客户端,服务端断开连接。
3、Socket双方如何建立起连接?
以下过程用代码表示:
Server端:
1 intport = 2000;
2 IPEndPointServerEP = newIPEndPoint(IPAddress.Any,port);
3 Socketserver = newSocket(AddressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp);
4 server.Bind(ServerEP);
5 server.Listen(0);
Client端:
1 intport = 2000;
2 IPAddressserverip = IPAddress.Parse("192.168.1.100");
3 IPEndPointEP = newIPEndPoint(server,port);
4 Socketserver = newSocket(AddressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp);
5 server.Bind(EP);
当服务器端接收到来自客户端的连接以后,需要新建一个socket来处理远端的信息。
下面一段代码应该在服务器端:
1 Socketclient =server.Accept();
以上很简单的几行代码,将在以后的网络编程中经常用到,后面还会有同步通讯、异步通讯、线程、委托与事件等等
4、套接字(socket)概念
套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。
应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个 TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。应用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。
5、建立socket连接
建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket,另一个运行于服务器端,称为ServerSocket。
套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。
服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。
客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。
6、SOCKET连接与TCP连接
创建Socket连接时,可以指定使用的传输层协议,Socket可以支持不同的传输层协议(TCP或UDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接。
7、Socket连接与HTTP连接
由于通常情况下Socket连接就是TCP连接,因此Socket连接一旦建立,通信双方即可开始相互发送数据内容,直到双方连接断开。但在实际网络应用中,客户端到服务器之间的通信往往需要穿越多个中间节点,例如路由器、网关、防火墙等,大部分防火墙默认会关闭长时间处于非活跃状态的连接而导致 Socket 连接断连,因此需要通过轮询告诉网络,该连接处于活跃状态。
而HTTP连接使用的是“请求—响应”的方式,不仅在请求时需要先建立连接,而且需要客户端向服务器发出请求后,服务器端才能回复数据。
很多情况下,需要服务器端主动向客户端推送数据,保持客户端与服务器数据的实时与同步。此时若双方建立的是Socket连接,服务器就可以直接将数据传送给客户端;若双方建立的是HTTP连接,则服务器需要等到客户端发送一次请求后才能将数据传回给客户端,因此,客户端定时向服务器端发送连接请求,不仅可以保持在线,同时也是在“询问”服务器是否有新的数据,如果有就将数据传给客户端。
8、说说对环信的理解
环信是一款即时通讯的服务提供商,环信使用的是XMPP协议,他是对XMPP的二次开发;
环信实现了视频、语音等附件的发送功能,给使用者节省了时间成本,不需要公司自己搭建聊天服务器;
环信实现了数据缓存,会把聊天记录添加到数据库,会把附件下载到本地
9、环信中的图片消息及语音消息是怎么实现的?
图片消息:首先从相册或者相机获取图片对象,将其存到沙盒或者转换成NSData,然后构造图片消息(EMImageMessageBody:initWithData/initWithLocalPath);当收到图片消息时,我们能够从消息体中解析出图片的路径(本地、网络),然后根据路径得到对应的图片
语音消息:首先通过AVAudioRecorder进行录音,然后将录音文件保存到沙盒或转换成NSData,构造语音消息(EMVoiceMessageBody:initWithData/initWithLocalPath);当接收到语音消息时,我们可以通过消息体解析出附件的路径(本地、网络),然后通过AVAudioPlayer进行播放
10、环信中是怎么实现好友管理的?
环信中的好友管理都与IEMContactManager有关
获取好友列表:getContactsFormServer
添加好友:addContact
收到好友请求:didReceiveFriendInvitation
删除好友:deleteContact
加入黑名单:addUserToBlackList
11、环信与公司自己的服务器是怎么结合使用的?
环信中有自己的一套用户信息,但是比较少,此时我们需要在自己的服务器中创建自己的用户表,该表保存了用户所有的信息(用户名、密码、性别等),同时还保存了环信的账号和密码,当用户登录时,会先登录自己的服务器,成功后再登录环信
12、环信中单聊与群聊是怎么区分的?
环信中的消息有三种类型:单聊(EMChatTypeChat)/群聊(EMChatTypeGroupChat)/聊天室(EMChatTypeRoom),然后我们根据消息的chatType进行区分
13、环信中消息的分发
每条消息都有自己的会话ID,我们可以根据会话ID来进行区分
14、怎么在环信中实现聊天记录
环信中自带聊天记录的功能,如果我们想要自己实现,我们可以将聊天信息放到本地数据库或服务器
15、怎么通过环信实现阅后即焚功能?
我们可以通过消息扩展配合已读回执进行实现
流程:
A-->B 发送阅后即焚消息
1)在消息中标明,该消息需要阅后即焚,用到EMMessage的ext属性,该属性是一个字典,我们可以在字典中设置两个key,一个代表是否阅后即焚,一个代表消息的ID
2)当B接收到消息之后,我们需要对该消息进行分析,看它是否需要阅后即焚,如果需要,则在B阅读了该消息之后,调用sendHaseReadResponse,发送已读回执
3)当A收到已读回执后,根据消息的ID,将消息从会话中删除
16、离线消息
用户只是退到了后台,并未退出账号:远程推送
用户退出了账号:环信有处理该情况的方法
17、环信中气泡聊天拉气泡而不改变气泡的形状
1-(UIImage*)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWithtopCapHeight:(NSInteger)topCapHeight;(iOS 5之前)
2-(UIImage*)resizableImageWithCapInsets:(UIEdgeInsets)capInsets;(iOS 5)
3)-(UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsetsresizingMode:(UIImageResizeingMode)resizingMode;(iOS 6以后)
以上三种方法,均可以实现将图片从中间区域拉伸,而保证图片的四周保持不变
18、iOS内购中,获取商品列表时,获取返回的商品数量为0
1、查看一下后台itunesConnect中该商品的状态,若颜色为红色则重新编辑一下商品信息。
2.确保商品ID作为参数是否正确,调试一下传值过程中是否被重置为空。
19、iOS内购中,此APPID尚未在iTunesStore使用过。点一下“检查”登录。
1.更换设备(有可能是越狱设备,能装上提审的ipa包)
2.ipa包archive的是否正确(是用发布还是测试签名生成的)
3.新的内购商品后台编辑上架后,若服务端收不到验证需要在后台新开版本。
20、iOS内购中,出现无法连接appstore商店提示
确保打包的时候用的是测试签名而不是发布签名(由于越狱机器是可以安装上发布包的,所以测试的时候最好使用未越狱的机器)。
21、iOS内购中,如果遇到消耗型的提示已经购买过的,那是因为你没有设置完成交易,导致系统认为你的交易没有完成所以认为你还在买同一个单子?
正确做法应该是在交易成功时,即SKPaymentTransactionStatePurchased下调用[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
22、iOS内购中,在app里添加IAP,必须要注册自己的产品标识符(product identifiers)。产品标识符是什么?
产品标识符(Product Identifiers)是一串字符串,它用来识别你在应用内贩卖的每件商品。App Store用产品标识符来检索产品信息,标识符只能包含大小写字母(A-Z)、数字(0-9)、下划线(-)、以及圆点(.)。你可以任意排列这些元素,但我们建议你创建标识符时使用反向域名,比如 com.companyname.application.productid
备注:产品标识符和Apple ID以及Bundle ID没有关系,它们看起来可能比较像Bundle ID,但是两者是不一样的。所以,在代码里你不能用Apple ID或者Bundle ID代替产品标识符。
22、iOS内购中,怎么创建产品标识符?
IAP表单(TheIn-App Purchases form)是用来生成IAP产品的,它包含了产品ID的字段,这个字段必须要填到表里。这个字段可以为你的产品指定产品标识符。你可以按下面的步骤来创建产品标识符:
1.登入iTunes Connect, 点击主页面上的Manage YourApplications模块。
2.进入Manage Your Apps 页面,你可以看到你所有的应用列表。选择你想要创建IAP的产品的app,在下个页面中点击Manage In-App Purchases按键,然后在点击创建。
3.选择IAP产品的类型。iTunes Connect会带你进入IAP表单,在这个表单里有“保存”按键。完整填写Product ID以及表单里的其他字段。
注意事项:产品标识符一旦创建无法修改,此外,如果应用审核没有通过,这个产品标识符也无法再次使用。
24、iOS内购中,如何在app中如何使用产品标识符?
首先创建SKProductsRequest,然后把产品标识符列表传至initWithProductIdentifiers 来读取产品信息。
当在Sandbox 环境测试In-App Purchase 时,为什么我得到的是“Payment requests are restricted to products returned as valid viaStore Kit’s didReceiveResponse method”错误信息?
执行In-App Purchase的app的用户界面必须有App Store允许的可供购买的产品。在你决定在用户界面展示用于购买的产品之前,你的app必须先向App Store发送一个产品请求。
StoreKit提供了两种支付支付请求的解决办法:
[SKPaymentpaymentWithProductIdentifier:PRODUCT_ID] [SKPaymentpaymentWithProduct:YOUR_SKPRODUCT_OBJECT] 苹果建议您使用[SKPayment paymentWithProduct:YOUR_SKPRODUCT_OBJECT] 使用这个方法可以确保你一直处于有效的产品支付请求状态,同时也确保用户可以购买你的产品。所以,务必只展现App Store返回的产品信息。了解更多有关于app内产品展现信息,请查看In-App Purchase 编程指南的 Feature Delivery 部分。
25、iOS内购中,In-App Purchase有几种类型?
In-AppPurchase共有3中类型
Consumable:一次性购买,最简单的类型,不用保存历史记录。
Nonconsumable:每个产品,用户只买一次,此后就可以在自己的所有设备上看到该产品。
Subscriptions:订阅模式允许多次购买末一个产品,但是购买后,用户可以在自己的所有设备上看到该产品。
26、iOS内购中,iOS 中使用 IAP 方式在程序内购买的内容在重装系统后还需要再次购买吗? 比如Camera+内的滤镜。
不必。以 Camera+ 为例,Menu 里最下方的选项 Restore purchases 即可帮你解锁已经购买的滤镜。任何实现了 IAP 功能的 App 基本都会提供这一选项,或者在第二次购买时提示已购。消耗类(如游戏金币)需要购买。 功能类不需要购买,有些应用提供“Restore purchases”,没有的可以再次尝试购买,会提示已付费。
27、iOS内购中,IAP 能做限时免费吗? 想做一个免费下载、部分内容免费,但是阅读更多内容需要付费解锁的阅读应用。这样可以把IAP的价格限时免费为0吗?
可以的,你可以设定价格为0时就不走IAP了。
28、iOS内购中,创建产品ID的时候,选择多少钱的时候选错了,程序还未提交,还能修改吗?
可以的,在应用程序的信息中。
升级iOS5 GM的过程中恢复备份出了问题,导致In-App Purchase也丢失了。有没有办法恢复?在iPad上曾经进行过一些In-App Purchase,但是在升级iOS5 GM的过程中恢复备份出了问题,导致除了恢复升级前的所有应用程序之外,其余个人信息一概丢失。iTunes上可以查询到购买记录。具体来说,买的是Splashtop的把iPad作为第二显示器的软件,Xdisplay。
In-AppPurchase 分好几种,最常见的是 Non-Consumable,就是只需要用户购买一次的。如果是这种类型的,再购买一次同一个商品就能够恢复了,不会收取额外费用。如果 app 做得好的话,应该提供一个 Restore 功能,以专门恢复以前购买过的 Non-Consumable 的商品。
29、iOS内购中,如何核实receipt(iOS)?
第一次一般使用产品的URL核实收据。如果你收到一个21007状态代码,那么接下来要用sandbox URL。当app处于测试状态或者在sandbox环境下进行检测,或者上架App Store,你可以使用这种方法,从而避免在URL之间进行切换,注明:21007 状态码表明receipt是一个sandbox receipt。
30、支付宝错误
在 openssl_wrapper.h中#import <Foundation/Foundation.h>库即可
31、支付宝错误Util/openssl_wrapper.m:11:9:‘rsa.h’ file not found
(1),万年老坑,只要你接入支付宝百分百要遇到的问题,所以习以为常吧
(2),在Build setting中搜索search,找到Header Search Paths,添加$(PROJECT_DIR)/openssl和$(PROJECT_DIR) 如下图:
(3),重要 问题说三遍,这是网络找到的到答案后继续有同样的坑,自己的解决方案,
HeaderSearch Paths $(PROJECT_DIR)/ali中输入这个
FrameworkSearch Paths 和 Library Search Paths 继续是$(inherited) 和 $(PROJECT_DIR)/ali
‘rsa.h’file not found 的解决方案
(4),由于后期多项目的接入,让我知道一个算是万能方法吧,就是始终保持HeaderSearch Paths 和 Library Search Paths 都能找到你导入的openssl的正确路径即可,已尝试多遍,是能解决以上问题(求黑)
32、微信支付错误:拉起微信支付后,在微信支付注册在友盟之后仍然跳转到微信还是一个确定按钮,点击确定按钮回到自己的应用
第一步获取prepayId,这一步往往都不会有什么错误,根着官方文档都不会出现什么问题,坑在第二步发送跳转
1、注意一下 nonceStr 需要是第一步里生成的 nonceStr,而不是重新生成。
2、sign 需要重新针对5个字段进行签名:partnerIdprepayId package nonceStr timeStamp 不需要传入appid或者openid
需要传入appid
3、package = @"Sign=WXPay" 注意服务器传来的"="会不会被转义成 %3D
4、sign的确需要大写。
33、如果你app同时使用了友盟分享(含微信分享)和微信支付。如果你没有处理好这个两个SDK register的顺序,那就很不幸,也会出现这种情况。
(如何出现这种情况,请看我的测试步骤:1、杀掉微信进程、2、删除自己开发的app、3、重新同步自己的app到设备,点击微信支付)
两者register的顺序:如果是先调用微信registerApp、然后调用友盟的 [UMSocialWechatHandler setWXAppId:WXAppID appSecret:[NSStringstringWithBundleNameForKey:@"WXAppSecret"] url:url] ,然后按照我测试的步骤,应该就会出现。
解决办法:改变两者的register步骤。先调用友盟,然后调用微信。
34、支付宝支付:Redefinition of 'RSA' as differentkind of symbol 多为sdk集成时产生的坑,因为我们公司在集成支付宝之前,有用过RSA加密,导致重名问题
由于支付宝中的openssl中的rsa.h文件与RSA加密有重名冲突。改掉公司自己之前导入RSA的命名。
35、支付宝支付:RSA密钥生成命令步骤如下:
(1)生成RSA私钥
(2)openssl>genrsa -out rsa_private_key.pem 1024
生成RSA公钥
(3)openssl>rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
将RSA私钥转换成PKCS8格式
(4)openssl>pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM-nocrypt
注意:“>”符号后面的才是需要输入的命令。
(5)把公钥上传到支付宝,然后把pkcs8-topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt 这条命令产生的私钥用在下面设置中就好
36、iOS集成支付宝,IOS9.0及以上版本的报错:error: "This app is not allowed to query for scheme alipay”?
近期苹果公司iOS 9系统策略更新,限制了http协议的访问,此外应用需要在“Info.plist”中将要使用的URL Schemes列为白名单,才可正常检查其他应用是否安装。
37、在调试移动支付接口,客户端的时候报错,提示为:failurecalling remote service,请问是什么原因?
主要原因是私钥没有转pkcs8导致的;
其次是http不要放在UI里面,放在UI里面http报错,导致支付包sendorder的时候出现异常,导致failure calling remote service 这个错误的发生。最简单的解决办法:<uses-sdkandroid:minSdkVersion="5"></uses-sdk>。
38、在调试移动支付接口的时候报ALI69错误?
报错含义就是没权限,请检查:
1、检查收款账号是否是签约账号;
2、检查是否签约了移动支付产品。
40、SVN,’.’ is not a working copy.Can’t open file‘.svn/entries’: 系统找不到指定的路径。
原因是输入的访问路径不正确,如svn://192.168.6.200/如果最后少写了“/”,就会出现这种错误提示。
41、“Commit failed。……You have toupdate yourworking copyfirst” 提交失败,需要首先执行更新操作。
多人同时修改同一文件,在提交前其他人已经抢先提交到SVN服务器中,导致该错误;解决方法:对工作复本中的文件进行更新即可。
42、更新时提示文件发生冲突:“One ormore files are not a conflicted state。” 多人同时修改同一文件的同一部分,SVN无法自动进行合并,会导致该错误;对工作复本中的文件和服务器的文件进行比较,手工合并即可。
43、“Commit failed;File alreadyexists”提交失败,文件**已存在。
版本管理系统在改变你的计算机上的工作副本时,是非常的小心的。在做任何事情之前,它都尽可能把您的意图写到你的计算机上的日志文件中去。但如果偶然地操作中断了(例如:突然停电了,您的计算机死机了),那么日志文件记录就可能同您最后的工作状态不一致。一种建议解决途径:先把要提交的东西拷出来放到其它目录,再更新本地文件,然后把拷出来的文件重新放回去提交。
44、Working copy’**’locked.Pleaseexecute the ’Clean up’command. version客户端在提交内容之前会在本地的工作拷贝写日志,防止其他客户端再次作操作,如果这个提交过程中发生错误,就会存在未清理的日志,解决这个问题之需要执行“清理”操作,整理你的计算机上的工作副本,清理错误的日志记录,使您可以继续操作。
45、执行cleanup时,出现错误“version reported an error while doing a cleanup!” '**'is not a working copy directory ”
遇到这种情况,先删除隐藏文件夹.svn中的tmp下面的临时文件,再执行cleanup。
46、使用友盟,点击微信分享,弹框说微信未安装(实际已经安装了)
A、在info.plist中加入安全域名白名单(右键info.plist用sourcecode打开)
B、在info.plist的NSAppTransportSecurity下新增NSAllowsArbitraryLoads并设置为YES,指定所有HTTP连接都可正常请求
47、应用跳转(SSO等)
如果你的应用使用了如SSO授权登录或跳转分享功能,在iOS9下就需要增加一个可跳转的白名单,指定对应跳转App的URL Scheme,
否则将在第三方平台判断是否跳转时用到的canOpenURL时返回NO,进而只进行webview授权或授权/分享失败。
同样在info.plist增加
<key>LSApplicationQueriesSchemes</key>
<array>
<!-- 微信 URL Scheme 白名单-->
<string>wechat</string>
<string>weixin</string>
</array>
48、百度地图,如果您只在Xib文件中使用了BMKMapView,没有在代码中使用BMKMapView,编译器在链接时不会链接对应符号。
需要在工程属性中显式设定:在Xcode的Project -> Edit Active Target ->Build Setting -> Other Linker Flags中添加-ObjC
49、百度地图,由于iOS9改用更安全的https,为了能够在iOS9中正常使用地图SDK,请在"Info.plist"中进行如下配置,否则影响SDK的使用。
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
50、如果在iOS9中使用了调起百度地图客户端功能,必须在"Info.plist"中进行如下配置,否则不能调起百度地图客户端。
<
key>LSApplicationQueriesSchemes</key>
<array>
<string>baidumap</string>
</array>
51、自iOS SDKv2.5.0起,为了对iOS8的定位能力做兼容,做了相应的修改,开发者在使用过程中注意事项如下:
需要在info.plist里添加(以下二选一,两个都添加默认使用NSLocationWhenInUseUsageDescription):
NSLocationWhenInUseUsageDescription ,允许在前台使用时获取GPS的描述
NSLocationAlwaysUsageDescription ,允许永久使用GPS的描述
52、在使用Xcode6进行SDK开发过程中,需要在info.plist中添加:Bundle display name ,且其值不能为空(Xcode6新建的项目没有此配置,若没有会造成manager start failed)
53、确认项目中添加mapapi.bundle文件以及添加方法正确,不能删除或随意更改其中files文件夹下的内容.
注:mapapi.bundle中存储了定位、默认大头针标注View及路线关键点的资源图片,还存储了矢量地图绘制必需的资源文件。如果您不需要使用内置的图片显示功能,则可以删除bundle文件中的image文件夹。您也可以根据具体需求任意替换或删除该bundle中image文件夹的图片文件。添加方式:将mapapi.bundle拷贝到您的工程目录,直接将该bundle文件托拽至Xcode工程左侧的Groups&Files中即可。若您需要替换定位、指南针的图标,请保留原文件名称,否则不显示替换的新图片,默认大头针标注与路线关键点的新图片名称可自定义名称。
54、app在前后台切换时,需要使用下面的代码停止地图的渲染和openGL的绘制(V2.10.0后不需要再调用):
- (void)applicationWillResignActive:(UIApplication *)application{
[BMKMapViewwillBackGround];//当应用即将后台时调用,停止一切调用opengl相关的操作
}
- (void)applicationDidBecomeActive:(UIApplication *)application{
[BMKMapViewdidForeGround];//当应用恢复前台状态时调用,回复地图的渲染和opengl相关的操作
}