0612就业等多个文件企信通_第1页
0612就业等多个文件企信通_第2页
0612就业等多个文件企信通_第3页
0612就业等多个文件企信通_第4页
0612就业等多个文件企信通_第5页
已阅读5页,还剩72页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

XMPP应用项目—企信通讲师:Vincent_Guo企信通概述目标实现一款企业内部使用的通讯应用应用领域满足企业内部的即时通讯需求,为企业提供全方位的移动即时通讯解决方案功能列表(一期)用户登录、注册电子名片企业名册添加好友文本消息表情文字在线状态文件传输语音交流部门会议产品定位市场需求目前很多企业为了提高员工的工作效率以及防止公司内部资料泄密,会禁止员工在办公时间使用诸如腾讯QQ之类即时通讯软件但是即时通讯软件的即时性与便利性,的确能够有效地提升企业内部员工沟通的效率产品定位企信通定位企业级用户,为企业提供全方位的移动即时通讯解决方案在企业中,畅顺的沟通对生产效率、管理质量起到至关重要的作用。在异步通信已无法满足办公需求的形式下,好的即时沟通平台,能够帮助实现高效沟通企信通是针对这一市场需求开发的企业级即时通讯平台。企业员工可以轻松地通过服务器与企业其他组织架构的人员进行通讯,并采用丰富的沟通方式进行实时沟通。文本消息、文件传输、语音的形式满足不同办公环境下的沟通需求企信通着力于帮助企业员工提高工作效率,减少企业内部通讯费用,使团队和信息工作者进行更加高效的沟通开发平台移动平台:iOS6.0+服务器:Openfire

3.9.1数据库:MySQL

5.6开发工具:Xcode

5.0版本控制器:git

一期开发时间:5工作日开发计划第1天:项目搭建,用户登录&注册第2天:电子名片&企业名册第3天:添加好友&文本消息&表情文字第4天:发送图片及文件第5天:音频录制及压缩第6~8天:优化,测试工作内容分解迭代式开发新建项目1.

新建"企信通"项目,勾选git2.

导入XMPP框架文件3.

添加框架需要的依赖文件4.

设置设备运行方向,仅纵向5.

编译测试,有两条警告6.

将程序提交至本地代码库Storyboard规划系统由两个Storyboard构成Login.storyboard:负责实现用户登录及注册功能Main.storyboard:负责实现企信通的即时通讯主体功能,包括以下三个主要功能模块:企信通:人员之间的内部交流企业名册:企业通讯录我的名片:个人名片的信息设置文件夹约定及其他Lib:存放项目引用的第三方库、分类及工具等代码Login:存放用户登录注册相关文件IM:存放即时通讯主体功能文件,随着系统开发的进展,将进一步细化图片素材:鉴于开发周期,在一期开发中,暂时使用其他IM软件中的图片素材,如:微信、QQ等应用程序图标启动画面Main.StoryboardLogin.storyboard按钮图片的拉伸处理,以兼容iOS6.0由于图像切片功能仅在iOS7.0之后才能使用,为了保证应用程序能够兼容iOS6.0针对按钮图像拉伸,还需要用代码进行处理stretchableImageWithLeftCapWidthXMPP框架的基本应用//设置XMPPStream(void)setupStream;//销毁XMPPStream并注销已注册的扩展模块(void)teardownStream;//通知服务器器用户上线(void)goOnline;//通知服务器器用户下线(void)goOffline;//连接到服务器(void)connect;//与服务器断开连接(void)disconnect;XMPPStream的使用由于XMPPStream是基于myJID建立的长连接,因此在应用程序中应该仅被实例化一次(didFinishLaunchingWithOptions)如果程序视图多次实例化XMPPStream,应该终止程序运行,以提示程序员纠错XMPPStream除了负责设定应用程序的代理之外,还用于添加XMPP框架的扩展,例如电子名片、花名册、自动连接等当出现内存警告时,应用程序内部属性会被销毁,此时,应该在dealloc方法中,销毁并释放XMPPStream对象以及相关的扩展setupStream方法//0.方法被调用时,要求_xmppStream必须为nil,否则通过断言提示程序员,并终止程序运行!NSAssert(_xmppStream

==nil,@"视图多次实例化XMPPStream!");//1.实例化XMPPStream_xmppStream

=

[[XMPPStream

alloc]

init];//2.添加代理//由于所有网络请求都是做基于网络的数据处理,这些数据处理工作与界面UI无关。//因此可以让代理方法在其他线城中运行,从而提高程序的运行性能,避免出现应用程序阻塞的情况[_xmppStream

addDelegate:selfdelegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,

0)];//3.设置XMPP扩展模块//3.1

设置自动重新连接_xmppReconnect

=

[[XMPPReconnect

alloc]

init];//4.激活扩展模块//4.1

自动重新连接模块[_xmppReconnect

activate:_xmppStream];teardownStream方法//1.

取消XMPPStream代理[_xmppStream

removeDelegate:self];//2.

取消在setupStream方法中注册的所有模块//2.1

自动重连模块[_xmppReconnect

deactivate];//3.

断开连接[_xmppStream

disconnect];//4.

释放内存_xmppStream

=

nil;_xmppReconnect

=

nil;通知服务器上线和下线#pragma

mark

通知服务器用户上线(void)goOnline{//1.实例化一个”展现“,上线的报告,默认类型是"available"XMPPPresence

*presence=[XMPPPresence

presence];//2.发送Presence给服务器//服务器知道“我”上线后,只需要通知我的好友,而无需通知我,因此,此方法没有回调[_xmppStream

sendElement:presence];}#pragma

mark

通知服务器用户下线(void)goOffline{//1.实例化一个”展现“,下线的报告XMPPPresence

*presence

=

[XMPPPresence

presenceWithType:@"unavailable"];//2.发送Presence给服务器,通知服务器客户端下线[_xmppStream

sendElement:presence];}connect方法//1.如果当前XMPP长连接已经存在,则直接返回if

([_xmppStream

isConnected])

{return;}//2.指定用户名、主机(服务器),连接时不需要passwordNSString

*userName=[[LoginUser

sharedLoginUser]jidName];NSString

*hostName=[[LoginUser

sharedLoginUser]hostName];//判断hostName

&

userName是否存在内容,避免在初始调用时出现问题

if

([hostName

isEmptyString]||

[userName

isEmptyString]){return;}//3.设置XMPPStream的JID和主机[_xmppStream

setMyJID:[XMPPJID

jidWithString:userName]];[_xmppStream

setHostName:hostName];//4.开始连接[_xmppStream

connectWithTimeout:XMPPStreamTimeoutNone

error:nil];disconnect方法#pragma

mark

断开连接-(void)disconnect{//1.通知服务器下线[self

goOffline];//2.

XMPPStream断开连接

[_xmppStream

disconnect];}XMPP登录、注册示意图XMPPStreammyJIDhostNamehostName对应的服务器以myJID名义的长连接发送注册请求注册成功用户注册流程通知服务器上、下线发送验证请求验证成功用户登录流程Appdelegate-(void)loginToServer{//1.从文件中读取登录信息//2.登录到服务器}LoginController-(void)login{//1.将登录信息保存在本地一个//2.调用appdelegate的登文件录方}-(void)register文件

username:xxxpassword:xxxhostName:xxx登录流程建立连接代理方法#pragma

mark

连接完成-

(void)xmppStreamDidConnect:(XMPPStream

*)sender在此方法中,可以根据成员变量发送注册或验证请求//发送注册请求[_xmppStream

registerWithPassword:password

error:nil];//发送身份验证请求[_xmppStream

authenticateWithPassword:password

error:nil];身份验证代理方法#pragma

mark

身份验证成功-

(void)xmppStreamDidAuthenticate:(XMPPStream

*)sender通知服务器当前用户上线通知客户端用户登录成功#pragma

mark

密码错误,身份验证失败-

(void)xmppStream:(XMPPStream

*)senderdidNotAuthenticate:(DDXMLElement

*)error通知客户端用户身份验证失败注册用户代理方法#pragma

mark

注册成功-

(void)xmppStreamDidRegister:(XMPPStream

*)sender使用用户密码验证身份,从而触发登录成功后续操作#pragma

mark

注册失败(用户名已经存在)-

(void)xmppStream:(XMPPStream

*)senderdidNotRegister:(DDXMLElement

*)error通知客户端用户注册失败用户登录状态变化的处理UIStoryboard*storyboard

=

nil;if

(isUserLogon)

{//显示Main.storyboardstoryboard

=

[UIStoryboard

storyboardWithName:@"Main"

bundle:nil];}

else

{//显示Login.sotryboardstoryboard

=

[UIStoryboard

storyboardWithName:@"Login"

bundle:nil];}dispatch_async(dispatch_get_main_queue(),

^{//把Storyboard的初始视图控制器设置为window的rootViewController[self.window

setRootViewController:storyboard.instantiateInitialViewController];if

(!self.window.isKeyWindow){[self.window

makeKeyAndVisible];}});自动重新连接如果出现意外断线,XMPPReconnect会自动重新连接到XMPP服务器xmppReconnect

=

[[XMPPReconnect

alloc]

init];[_xmppReconnect

activate:xmppStream];电子名片——vCardvCard(或称做Versitcard)最早是由Versit联盟于1995年提出的,当时联盟成员包括苹果公司,AT&T科技(后来的朗讯),IBM及西门子。在

1996年十二月,格式的拥有权移至因特网邮件联盟(IMC),此联盟是由一些关注因特网电子邮件的公司所组成vCard标准的2.1版被电子邮件客户端广泛支持。3.0版是一个包含在RFC2425和RFC

2426中的IETF标准跟踪提案。vCard的常用文件扩展名是.vcf不同的程序对vCard标准实现亦不同。Mac

OS

X中的Address

Book允许把所有联系人导出到一个vcf文件,而Microsoft

Outlook只能每人一个文件vCard是电子名片的文件格式标准,一般附加在电子邮件之后,但也可以用于其它场合(如在因特网上相互交换)XMPP中电子名片的使用1.

XEP-0054提供了一种机制,可以通过XMPP发送电子名片2.

要使用个人名片首先需要在XMPPFramework.h中启用电子名片的扩展头文件:#import

"XMPPvCardCoreDataStorage.h"#import

"XMPPvCardTempModule.h"3.

定义属性及成员变量4.

为XMPPSteam添加电子名片扩展5.

在需要时使用电子名片定义电子名片属性及成员变量1.

在.h文件中添加如下定义//全局电子名片模块@property

(strong,

nonatomic,

readonly)

XMPPvCardTempModule*xmppvCardModule;2.

在.m中添加如下成员变量//电子名片数据存储模块XMPPvCardCoreDataStorage

*_xmppvCardStorage;为XMPPSteam添加电子名片扩展//实例化电子名片模块xmppvCardStorage

=

[XMPPvCardCoreDataStorage

sharedInstance];_xmppvCardModule

=

[[XMPPvCardTempModulealloc]initWithvCardStorage:_xmppvCardStorage];//激活电子名片模块[_xmppvCardModule

activate:_xmppStream];初次运行会自动生成一个SQLite数据库文件电子名片的使用#import

"XMPPvCardTemp.h”XMPPvCardTemp

*myCard

=

[[[selfappDelegate]

xmppvCardModule]myvCardTemp];//判断是否存在电子名片if

(myCard

==

nil)

{myCard

=

[XMPPvCardTemp

vCardTemp];myCard.nickname

=

[[LoginUser

sharedLoginUser]

userName];myCard.jid

=

[XMPPJID

jidWithString:[LoginUser

sharedLoginUser].myJIDName];[[self

appDelegate]

saveMyCard:myCard];}备注:XMPP框架中没有实现电话和电子邮件的方法,实例中使用note作为电话,mailer作为电子邮件使用XMPP中花名册的使用1.

要使用花名册首先需要在XMPPFramework.h中启用电子名片的扩展头文件:#import

"XMPPRoster.h"#import

"XMPPRosterCoreDataStorage.h"2.

定义属性及成员变量3.

为XMPPSteam添加花名册扩展4.

设置花名册代理5.

在需要时使用花名册定义花名册属性及成员变量在.h文件中添加如下定义//全局花名册模块@property

(strong,

nonatomic,

readonly)

XMPPRoster

*xmppRoster;//全局花名册数据存储模块@property

(strong,

nonatomic,

readonly)

XMPPRosterCoreDataStorage*xmppRosterStorage;为XMPPSteam添加花名册扩展//实例化花名册模块_xmppRosterStorage

=

[[XMPPRosterCoreDataStorage

alloc]

init];_xmppRoster

=

[[XMPPRoster

alloc]

initWithRosterStorage:_xmppRosterStorage];//*

设置花名册属性[_xmppRoster

setAutoFetchRoster:YES];[_xmppRoster

setAutoAcceptKnownPresenceSubscriptionRequests:YES];//激活花名册模块[_xmppRoster

activate:_xmppStream];//添加代理[_xmppRoster

addDelegate:selfdelegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,

0)];初次运行会自动生成一个SQLite数据库文件花名册的使用导入CoreData框架使用NSFetchedResultsController(抓取结果控制器)可以有效地管理从Core

Data抓取返回的数据结果,并为UITableView对象提供数据UITableView的数据源方法#pragmamark

表格分组数量return

[_fetchedResultsController

sections].count;#pragma

mark每个分组中的表格行数NSArray

*sectionData=

[_fetchedResultsControllersections];if

(section

<

sectionData.count)

{id

<NSFetchedResultsSectionInfo>

sectionInfo

=

sectionData[section];return

[sectionInfo

numberOfObjects];}return

0;#pragma

mark单元格(行)对象XMPPUserCoreDataStorageObject

*user

=

[_fetchedResultsController

objectAtIndexPath:indexPath];cell.textLabel.text

=

user.displayName;设置抓取结果控制器(1)//1.如果要针对CoreData做数据访问,无论怎么包装,都离不开NSManagedObjectContext//实例化NSManagedObjectContextNSManagedObjectContext

*context

=

[[xmppDelegatexmppRosterStorage]mainThreadManagedObjectContext];//2.实例化NSFetchRequest

NSFetchRequest

*request=[NSFetchRequestfetchRequestWithEntityName:@"XMPPUserCoreDataStorageObject"];//3.实例化一个排序NSSortDescriptor

*sort1

=

[NSSortDescriptor

sortDescriptorWithKey:@"jidStr"

ascending:YES];[request

setSortDescriptors:@[sort1]];//4.实例化_fetchedResultsController_fetchedResultsController

=

[[NSFetchedResultsController

alloc]initWithFetchRequest:requestmanagedObjectContext:context

sectionNameKeyPath:@"sectionNum"

cacheName:nil];设置抓取结果控制器(2)//5.设置代理[_fetchedResultsController

setDelegate:self];//6.查询数据NSError

*error

=

nil;if

(![_fetchedResultsController

performFetch:&error])

{NSLog(@"%@",

error.localizedDescription);}#pragma

mark-NSFetchedResults控制器代理方法

[self.tableView

reloadData];添加&删除好友在XMPP框架中提供的添加好友的机制是一种订阅(Subscription)机制,类似于微博中的关注,即A可以添加B为好友,但是B不一定要添加A为好友如果要实现双向添加和删除,可以将xmppRoster的autoAcceptKnownPresenceSubscriptionRequests属性设置为YES从客户端发送添加好友请求//判断是否已经是好友[[xmppDelegate

xmppRosterStorage]

userExistsWithJID:jidxmppStream:[xmppDelegate

xmppStream]];//发送好友订阅请求[[xmppDelegate

xmppRoster]

subscribePresenceToUser:jid];从客户端接收添加好友请求-

(void)xmppStream:(XMPPStream

*)sender

didReceivePresence:(XMPPPresence

*)presence{//1.取得好友当前类型(状态)NSString

*presenceType

=

[presence

type];//2.如果是用户订阅,则添加用户if

([presenceType

isEqualToString:@"subscribe"])

{//接收好友订阅请求[_xmppRoster

acceptPresenceSubscriptionRequestFrom:[presence

from]andAddToRoster:YES];}}删除好友[[xmppDelegate

xmppRoster]

removeUser:user.jid];用户状态XMPPUserCoreDataStorageObject中的sectionNum“0”-在线“1”-离开“2”-离线使用表格分组显示用户在线状态NSArray

*sections

=

_fetchedResultsController.sections;if

(section

<

sections.count)

{id

<NSFetchedResultsSectionInfo>

info

=

sections[section];NSInteger

state

=

[[info

name]

integerValue];switch

(state)

{

case

0:return

@"在线";break;case

1:return

@"离开";break;case

2:return

@"下线";break;}}return

@"未知";用户头像——XMPPvCardAvatarModule-

(UIImage

*)loadPhotoForUser:(XMPPUserCoreDataStorageObject

*)user{//判断好友数据表中是否存在用户头像if

(user.photo)

{//如果存在直接返回return

user.photo;}//如果不存在,从用户名片中获取NSData

*photoData

=

[[xmppDelegate

xmppvCardAvatarModule]

photoDataForJID:user.jid];if

(photoData)

{return

[UIImage

imageWithData:photoData];}return

[UIImage

imageNamed:@"DefaultProfileHead"];}后台支持#if

!TARGET_IPHONE_SIMULATOR[_xmppStream

setEnableBackgroundingOnSocket:YES];#endif实体能力(XEP-0115)实体能力用于广播和动态查询客户端、设备或通用实体的能力。为了最小化网络冲击,传输机制采用标准的XMPP出席信息广播(从而防止和服务发现数据相关的数据轮询的需要),能力信息可被缓存在单个会话中也可以贯穿多个会话,并且格式已经尽可能保持最小对于一个XMPP应用程序,经常需要(通常但不一定是一个客户端)根据从另一个应用收到的出席信息所了解到的能力采取不同的动作。例如:根据其他实体的能力显示不同系列的图标不发送XHTML-IM或者其他富文本给只支持纯文本的客户端比如手机只有当客户端支持Jingle和Jingle

RTP

Sessions

时,才允许VoIP的初始化如果另一个用户客户端不支持SI

File

Transfer,那么不显示“发送文件”按钮基于声明的订阅者兴趣,过滤Publish-Subscribe通知准备工作1——聊天界面布局搭建利用自动布局设置文本输入框针对底部的三个约束利用通知中心监听键盘变化情况[[NSNotificationCenter

defaultCenter]

addObserver:selfselector:@selector(keyboardStateChanged:)name:UIKeyboardWillChangeFrameNotification

object:nil];用户键盘变化时,通过更改约束,调整用户界面//1.

获取用户信息NSDictionary

*info

=

[notification

userInfo];//2.

取出键盘属性//2.1

键盘所占区域CGRect

rect

=

[[info

objectForKey:UIKeyboardFrameEndUserInfoKey]

CGRectValue];//2.2

键盘动画时长CGFloat

duration

=

[[info

objectForKey:UIKeyboardAnimationDurationUserInfoKey]floatValue];//2.3

取出屏幕区域CGRect

screenRect

=

[UIScreen

mainScreen].bounds;//3.

根据区域的y值判断键盘是显示还是隐藏if

(rect.origin.y

==

screenRect.size.height)

{//3.1

隐藏键盘}

else

{//3.2

显示键盘(216,252)}//4.

动画更新布局[UIView

animateWithDuration:durationanimations:^{[self.view

layoutIfNeeded];}];文本消息聊天-

(void)xmppStream:(XMPPStream

*)senderdidReceiveMessage:(XMPPMessage

*)message代理方法中如果message的isChatMessage属性为YES,表示接收到的消息是聊天消息message消息格式示例<message

xmlns="jabber:client"

to="lisi@liufan9-mac.local"

type="chat"

id="E326027C-C1C8-48F5-8E2E-FCA24A67F0E0"

from="liufan4@liufan9-mac.local/liufan9-mac"><body>hi</body><html

xmlns="

"><body

xmlns="

"

style="background-color:#e9e9e9;color:#000000;"><span

style="font-family:

'Helvetica';font-size:12px;">hi</span></body></html><x

xmlns="jabber:x:event"><composing/></x><active

xmlns="

"/></message>消息数据处理——XEP-0136激活XMPPMessageArchiving和XMPPMessageArchivingCoreDataStorage消息归档模块实例化查询结果控制器//1.获取数据管理上下文//2.

实例化NSFetcheRequest@"XMPPMessageArchiving_Message_CoreDataObject"];//3.

设置查询条件[request

setPredicate:[NSPredicate

predicateWithFormat:@"streamBareJidStr

='lisi@liufan9-mac.local'

AND

bareJidStr

=

'liufan4@liufan9-mac.local'"]];//4.

设置排序//5.实例化查询控制器//6.

设置代理//7.

启动查询NSError

*error

=

nil;if

(![_fetchedResultsController

performFetch:&error]){

NSLog(@"查询错误:%@",error.localizedDescription);}数据源方法#pragma

mark

数据行数(NSInteger)tableView:(UITableView

*)tableView

numberOfRowsInSection:(NSInteger)section{id<NSFetchedResultsSectionInfo>

info

=

_fetchedResultsController.sections[0];return

[info

numberOfObjects];}#pragma

mark

表格行(UITableViewCell

*)tableView:(UITableView

*)tableView

cellForRowAtIndexPath:(NSIndexPath

*)indexPath{static

NSString

*FromID

=

@"ChatFromCell";UITableViewCell

*cell

=

[tableView

dequeueReusableCellWithIdentifier:FromID

forIndexPath:indexPath];XMPPMessageArchiving_Message_CoreDataObject

*message

=

[_fetchedResultsControllerobjectAtIndexPath:indexPath];cell.textLabel.text

=

message.body;return

cell;}发送消息#pragma

mark-UITextField代理方法-

(BOOL)textFieldShouldReturn:(UITextField

*)textField{NSString

*str

=

[textField.text

trimString];XMPPMessage

*msg

=

[XMPPMessage

messageWithType:@"chat"

to:[XMPPJIDjidWithString:@”zhangsan.local"]];[msg

addBody:str];NSLog(@"%@",

msg);[[xmppDelegate

xmppStream]

sendElement:msg];return

YES;}滚动到表格末尾//计算表格行数id

<NSFetchedResultsSectionInfo>

info

=

_fetchedResultsController.sections[0];NSIndexPath

*indexPath=

[NSIndexPath

indexPathForRow:([info

numberOfObjects]-1)

inSection:0];[self.tableView

selectRowAtIndexPath:indexPath

animated:YESscrollPosition:UITableViewScrollPositionBottom];表情文字的输入在iOS中,表情文字是通过Unicode字符实现的Unicode(中文:万国码、国际码、统一码、单一码)是计算机科学领域里的一项业界标准。它对世界上大部分的文字系统进行了整理、编码,使得电脑可以用更为简单的方式来呈现和处理文字Unicode伴随着通用字符集的标准而发展,同时也以书本的形式对外发表。Unicode至今仍在不断增修,每个新版本都加入更多新的字符,目前最新的版本为第六版,已收入了超过十万个字符。Unicode涵盖的数据除了视觉上的字形、编码方法、标准的字符编码外,还包含了字符特性,如大小写字母Unicode备受认可,并广泛地应用于电脑软件的国际化与本地化过程。有很多新科技,如可扩展置标语言、Java编程语言以及现代的操作系统,都采用Unicode编码化时的约束代码——直接修改约束优化键盘变大/1.获小取键盘的目标区域NSDictionary

*info

=

notification.userInfo;CGRect

rect

=

[info[UIKeyboardFrameEndUserInfoKey]

CGRectValue];CGFloat

duration

=

[info[UIKeyboardAnimationDurationUserInfoKey]

floatValue];//2.根据rect的orgion.y可以判断键盘是开启还是关闭if

(rect.origin.y

==

[UIScreen

mainScreen].bounds.size.height)

{_noInputTextConstraint.constant

=

0.0f;}

else

{_noInputTextConstraint.constant

=

rect.size.height;}//用自动布局系统实现动画,调整位置[UIView

animateWithDuration:duration

animations:^{[self.view

layoutIfNeeded];}

completion:^(BOOL

finished)

{[self

scrollToTableBottom];}];自定义视图将文字输入处理部分代码抽离自定义InputToolView

输入工具视图完成按钮点击切换代码自定义EmoteSelectView实现表情选择功能表情符号的参照地址:预定义表情字符数组static

unichar

emotechars[28]

={0xe415,

0xe056,

0xe057,

0xe414,

0xe405,

0xe106,

0xe418,0xe417,

0xe40d,

0xe40a,

0xe404,

0xe105,

0xe409,

0xe40e,0xe402,

0xe108,

0xe403,

0xe058,

0xe407,

0xe401,

0xe416,0xe40c,

0xe406,

0xe413,

0xe411,

0xe412,

0xe410,

0xe059,};XMPP中的文件传输XEP-0096:

File

Transfer

这是传输文件的统一接口,客户端之间用它来协商到底采用那种具体的传输方式,包括以下三种:XEP-0047:

In-Band

ByteStreams

带内字节流,这个协议实际上用于小数据量传输,只是它用的字节流传输,所以也顺便说一下。带内,也就是夹带在XML流中,通过XMPP服务器中转传输。具体用法是把数据用base64编码放在XML流中传给对方。这个办法不好,base64编码效率很低,而且所有数据必须由服务器中转(字符串格式的数据中转)XEP-0066:

Out

of

Band

Data

带外字节流,带内不行就走带外,也就是不经过XMPP服务器。这个用法是在发起传输的客户端临时建立一个http服务(当然也可以是别的服务),把自己的IP和端口(通过XMPP消息)告诉接收方,让对方直接来下载。这个方法有一个问题,发送一方必须是公网IP,否则对方无法访问。注:目前Pandion,Linq支持这个XEPXEP-0065:

SOCKS5

Bytestreams

SOCKS5字节流,使用SOCKS5传输文件,有直连式和代理传输两种方式。发送方把预定的IP和端口(通过XMPP消息)告诉接收方。如果双方都在公网,采用SOCKS直接传输。如果任何一方在内网,经过SOCKS5代理服务器传输,发送方把代理服务器的IP和端口告诉给接收方。这里的SOCKS5代理服务器和通用的代理服务器稍有差别,因为它需要通过发送方提出的一个sessionID由XMPP服务器通知SOCKS5代理服务器把双方的SOCKS

通道连通,也就是激活。注:目前Psi,Linq支持这个XEPBase64Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。Base64编码可用于在HTTP环境下传递较长的标识信息采用Base64编码不仅比较简短,同时也具有不可读性,即所编码的数据不会被人用肉眼所直接看到直接使用字节流传输//发送数据XMPPMessage*msg

=

[XMPPMessagemessageWithType:@"img"

to:_bareJid];NSString

*str

=

[_sendData

base64Encoding];NSXMLElement

*bodyElement=

[NSXMLElement

elementWithName:@"imgData"

stringValue:str];[msg

addChild:bodyElement];//接收数据NSString

*imageString=

[[message

elementForName:@"imgData"]

stringValue];if

(imageString)

{NSData

*data

=

[[NSData

alloc]

initWithBase64EncodedString:imageStringoptions:NSDataBase64DecodingIgnoreUnknownCharacters];//将照片写入相册UIImage

*image

=

[UIImage

imageWithData:data];UIImageWriteToSavedPhotosAlbum(image,

nil,

nil,

nil);}TURNSocket——XEP65要使用服务器设置中,增加如下属性:xy.externalip//创建socket准备接收数据if

([TURNSocket

isNewStartTURNRequest:iq])

{TURNSocket

*socket

=

[[TURNSocket

alloc]

initWithStream:sender

ingTURNRequest:iq];[_turnSockets

addObject:socket];[socket

startWithDelegate:self

delegateQueue:dispatch_get_main_queue()];}接收成功代理方法NSMutableData

*data

=

[NSMutableData

data];

[socket

readDataToData:data

withTimeout:60.0f

tag:0];[data

writeToFile:path

atomically:YES];[_turnSockets

removeObject:sender];[socket

disconnectAfterWriting];使用jid建立socket连接方法-

(void)connectViaXEP65:(XMPPJID*)jid{if(jid

==

nil)

return;NSLog(@"Attempting

TURN

connection

to

%@",

jid);TURNSocket

*turnSocket

=

[[TURNSocket

alloc]

initWithStream:_xmppStream

toJID:jid];[_turnSockets

addObject:turnSocket];[turnSocket

startWithDelegate:self

delegateQueue:dispatch_get_main_queue()];}其他——判断IQ是否为SI请求-

(BOOL)isSIRequest:(XMPPIQ

*)iq{NSXMLElement

*si

=

[iq

elementForName:@"si"

xmlns:@""];NSString

*uuid

=

[[si

attributeForName:@"id"]stringValue];if(si

&&uuid

){return

YES;}return

NO;}界面小结企信通所有发生过联系的联系人聊天记录,最近聊天的内容显示在最上面单击每一条记录,可以进入与该联

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论