蓝懿ios技术交流和心得分享16.1.25

什么是Socket,XMPP?

Jul 29, 2014

什么是scoket?

  • Socket又称"套接字”
  • 网络上的两端通过建立一个双向的通信连接实现数据的交换,这个端就称为一个socket

  • 应用程序通常通过"套接字"向网络发出请求或者应答网络请求

网络通信的要素

网络上的请求就是通过Socket来建立连接然后互相通信

http:192.168.0.1:80/login

  • IP地址

(网络上主机设备的唯一标识)

  • 端口号

(定位程序)

  • 用于标示进程的逻辑地址,不同进程的标示
  • 有效端口:0~65535,其中0~1024由系统使用或者保留端口,开发中建议使用1024以上的端口
  • 传输协议

(用什么样的方式进行交互)

  • 通讯的规则
  • 常见协议:TCP、UDP

TCP&UDP

TCP(传输控制协议)

  • 建立连接

,形成传输数据的通道

  • 在连接中进行大数据传输

(数据大小不收限制)

  • 通过三次握手(请求,回应,确认)

完成连接,是可靠协议,安全送达

  • 必须建立连接,效率会稍低

关于三次握手

第一次握手:客户端尝试连接服务器

,向服务器发送syn包(同步序列编号Synchronize Sequence Numbers),syn=j,客户端进入SYN_SEND状态等待服务器确认

第二次握手:服务器接收客户端syn包并确认

(ack=j+1),同时向客户端发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态

第三次握手:客户端收到服务器的SYN+ACK包

,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手

UDP(用户数据报协议)

  • 将数据及源和目的封装成数据包中,不需要建立连接
  • 因为无需连接,因此是不可靠协议
  • 每个数据报的大小限制在64K之内
  • 不需要建立连接,速度快
  • 常用于视频广播

等场景

UDP是一种无连接的传输层协议,它主要用于不要求分组顺序到达的传输中,分组传输顺序的检查与排序由应用层完成,提供面向事务的简单不可靠信息传送服务。UDP 协议基本上是IP协议与上层协议的接口。UDP协议适用端口分别运行在同一台设备上的多个应用程序。

UDP提供了无连接通信,且不对传送数据包进行可靠性保证,适合于一次传输少量数据,UDP传输的可靠性由应用层负责。

UDP报文没有可靠性保证、顺序保证和流量控制字段等,可靠性较差。但是正因为UDP协议的控制选项较少,在数据传输过程中延迟小、数据传输效率高,适合对可靠性要求不高的应用程序,或者可以保障可靠性的应用程序,如DNS、TFTP、SNMP等。

实现Socket服务端监听

  • 实现Socket的监听方法有:

  • 1. 使用C语言实现
  • 2. 使用CocoaAsyncSocket

第三方框,内部是对C的封装

  • Telnet命令 telnet 192.168.10.10 5288

  • telnet命令是连接 服务器上的某个端口对应的服务

Socket编程案例

通过Socket编程编写 "群聊服务器" 与 "群聊客户端"

  • <群聊服务器>
  • 新建命令行项目
  • 使用CocoaAsyncSocket

第三方框,将GCDAsyncSocket的.h和.m文件复制到项目中

#import "ServerSocket.h"
#import "GCDAsyncSocket.h"

@interface ServerSocket ()
/** 服务端Socket */
@property (nonatomic, strong) GCDAsyncSocket *ServerSocket;
/** 存放客户端Socket的数组 */
@property (nonatomic, strong) NSMutableArray *clientSocketArray;
@end

@implementation ServerSocket
/** clientSocketArray的懒加载 */
- (NSMutableArray *)clientSocketArray{
    if (!_clientSocketArray) {
        _clientSocketArray = [NSMutableArray array];
    }
    return _clientSocketArray;
}

- (instancetype)init{
    if (self = [super init]) {
        // 1. 创建服务端Socket对象
        self.ServerSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];
    }
    return self;
}

- (void)start{
    // 2. 绑定端口,马上监听端口
    NSError *error = nil;
    [self.ServerSocket acceptOnPort:5288 error:&error];

    if (!error) {
        NSLog(@"服务端开启成功");
    }else{
        NSLog(@"服务端开启失败");
    }
}

#pragma mark - GCDAsyncSocketDelegate
// 接收到客户端 连接请求
- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket{
#warning 将新连接的客户端保存起来,避免断开
    [self.clientSocketArray addObject:newSocket];

    NSLog(@"连接上的客户端 %ld", self.clientSocketArray.count);


#warning 如果想要接收数据,必须要监听数据的读取
    [newSocket readDataWithTimeout:-1 tag:0];
}


// 接收到客户端的数据
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
    // 将二进制数据转换为字符串
    NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"%@", str);

#warning 进行数据读取之前一定要先写这句
    [sock readDataWithTimeout:-1 tag:0];

    // 把数据发送给其他客户端
    for (GCDAsyncSocket *client in self.clientSocketArray) {
        if (client != sock) {
            [client writeData:data withTimeout:-1 tag:0];
        }
    }
}
@end

注:iOS项目 会自动开启主运行循环,而 命令行项目 必须手动开启

  • 运行程序,服务端就开始运行了

  • 终端充当客户端,输入以下命令来连接10086服务器:

  • telnet 192.168.10.10 5288
  • 其中 192.168.10.10

为服务器的IP地址,5288为服务器端口号

  • <群聊客户端>
#import "ViewController.h"
#import "GCDAsyncSocket.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *inputViewBottom;
@property (weak, nonatomic) IBOutlet UIView *inputView;
@property (weak, nonatomic) IBOutlet UIButton *sendButton;
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (weak, nonatomic) IBOutlet UITextField *textField;

/** 客户端Socket */
@property (nonatomic, strong) GCDAsyncSocket *clientSocket;
/** 存放数据的数组 */
@property (nonatomic, strong) NSMutableArray *dataSource;
@end

@implementation ViewController

static NSString * const cellID = @"cell";

/** dataSource的懒加载 */
- (NSMutableArray *)dataSource{
    if (!_dataSource) {
        _dataSource = [NSMutableArray array];
    }
    return _dataSource;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    // 1. 连接服务器
    // 1.1 创建客户端Socket对象
    GCDAsyncSocket *clientSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];
    // 1.2 连接
    NSError *error = nil;
    [clientSocket connectToHost:@"192.168.1.102" onPort:5288 error:&error];
    if (error) {
        NSLog(@"%@", error);
    }
    self.clientSocket = clientSocket;

    // 注册cell
    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:cellID];
}


#pragma mark - GCDAsyncSocketDelegate
// 2. 监听数据读取
/**
 *  连接到服务器后调用
 */
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{
    NSLog(@"与服务器连接成功,建立了通信连接");

#warning 客户端连接成功后,要监听数据读取
    [sock readDataWithTimeout:-1 tag:0];
}

/**
 *  与服务器断开连接时调用
 */
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{
    NSLog(@"与服务器断开连接 %@", err);
}

/**
 *  接收数据
 */
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
    NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"%@ %@", str, [NSThread currentThread]);

    // 准备读取下次的数据
    [sock readDataWithTimeout:-1 tag:0];

    // -----刷新表格
    [self.dataSource addObject:str];
#warning 当前所有的代理都是在子线程调用
    // 回到主线程刷新表格
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        [self.tableView reloadData];
    }];

}


#pragma mark - Table View Data Source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return self.dataSource.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:cellID];
    cell.textLabel.text = self.dataSource[indexPath.row];

    return cell;
}


- (IBAction)sendBtnClick{
    // 获取用户输入的文字
    NSString *text = self.textField.text;
    if (text.length == 0) {
        return;
    }

    // 发送
    [self.clientSocket writeData:[text dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];

    // 刷新表格
    [self.dataSource addObject:text];
    [self.tableView reloadData];
}

- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag{
    NSLog(@"数据发送成功");
}

@end

短连接与长连接

短连接

连接

->传输数据->关闭连接

HTTP是无状态的,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接

也可以这样说:短连接是指SOCKET连接后发送后接收完数据后马上断开连接。

长连接

连接

->传输数据->保持连接 ->传输数据-> 。。。 ->关闭连接

长连接指建立Socket连接后不管是否使用都保持连接

,但安全性较差。

关于长连接我们在介绍推送通知

的时候接触过

Socket层上的协议

  • Socket层上的协议指的数据传输的格式
  • HTTP协议的传输格式

http1.1- content-type

:multipart/form-data,- 

content-length

:188,- 

body

:username=zhangsan&password=123456

  • XMPP协议,是一款即时通讯协议
  • 可扩展消息处理现场协议)是基于可扩展标记语言(XML)的协议,它用于即时消息(IM)以及在线现场探测。这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息

传输格式:

  zhangsan
   lisi
   一起吃晚上
  • HTTP/XMPP 等协议 定义了数据传输的格式
  • TCP/UDP 等定义了数据传输的方式

 

什么是XMPP?

  • XMPP:The Extensible Messaging and Presence Protocol(可扩展通讯和表示协议)

  • XMPP是一种基于XML的即时通讯协议

,XMPP的官方文档是RFC 3920

  • 这个文档定义了登录,退出,获取好友,发送消息等等的XML数据传输协议

XMPP是一个典型的C/S

架构,基本的网络形式是客户端通过TCP/IP连接到服务器,通过Socket建立连接,然后在之上传输XML流

XMPP是一种类似于HTTP协议的一种数据传输协议,其过程就如同“解包装--〉包装”的过程。只需要理解其接收的类型及返回的类型,便可以很好的利用XMPP来进行数据通讯

XMPP官方网站——http://xmpp.org

环信简介

环信是在XMPP的基础上进行二次开发,将基于移动互联网的即时通讯能力,如单聊、群聊、发语音、发图片、发位置、实时音频、实时视频等,通过云端开放的 Rest API 和客户端 SDK 包的方式提供给开发者和企业。让App内置聊天功能和以前网页中嵌入分享功能一样简单。

SVN使用技巧

Jun 11, 2014

常见的源代码管理工具

CVS

  • 开启版本控制之门
  • 1990年诞生,“远古时代”的主流源代码管理工具

SVN

  • 全称是Subversion,集中式版本控制之王者
  • 是CVS的接班人,速度比CVS快,功能比CVS多且强大
  • 在国内软件企业中使用最为普遍(70%~90%)

GIT

  • 一款伟大的分布式源代码管理工具
  • 目前被越来越多的开源项目使用
  • 不过在国内企业尚未大范围普及

SVN客户端命令

svn checkout :下载服务器的代码到本地 (简写svn co)
svn commit :将改动的文件提交到服务器(简写svn ci)
svn update :更新服务器的代码到本地 (简写svn up)

svn add :向本地的版本控制库中添加新文件
svn delete、svn remove :从本地的版本控制库中删除文件(简写svn del、svn rm)
svn move :移动文件或者目录或文件更名
svn mkdir :创建纳入版本控制下的新目录
svn revert :撤销之前的一切修改
svn merge :将两个版本之间的差异合并到当前文件
svn info :查看文件的详细信息 
svn diff :查看不同版本的区别
svn log :查看日志信息
svn list :列出版本库下的文件和目录列表
svn status :查看文件状态(简写svn st)
svn help :获取帮助信息(比如svn help ci)
svn lock :加锁
svn unlock :解锁

svn st 显示的文件状态

第1列状态说明:描述文件被添加、删除或其他修改
--------------------------------------------------------------------------------
' ' 没有修改
'A' 被添加到本地代码仓库
'C' 冲突
'D' 被删除
'I' 被忽略
'M' 被修改
'R' 被替换
'X' 外部定义创建的版本目录
'?' 文件没有被添加到本地版本库内
'!' 文件丢失或者不完整(不是通过svn命令删除的文件)
'~' 受控文件被其他文件阻隔

检出

将项目检出(下载) 至本地
svn checkout URL  [PATH]
svn co URL  [PATH]
注意:这里的中括号[ ]代表可选(可以省略)

示例
svn checkout  https://192.168.1.106/svn/Weibo/ /Users/Documents/workspace
https://192.168.1.106/svn/Weibo/代表的是:代码仓库的远程地址
/Users/Documents/workspace代表的是:将代码下载到本地的哪个路径
如果省略/Users/Documents/workspace的路径,就下载到命令行当前所在的路径

提交

将改动过的文件提交至服务器
svn commit  -m "注释"  [PATH]
svn ci  -m "注释"  [PATH]
注意:一定要养成写注释的良好习惯

示例
svn commit  -m “修改了User.m文件” /Users/Desktop/workspace/Weibo/branches/User.m
/Users/Desktop/workspace/Weibo/branches/User.m代表的是:提交哪个文件到服务器
如果省略/Users/Desktop/workspace/Weibo/branches/User.m的路径,就将命令行所在路径中所有改动过的文件提交到服务器

添加

提交一个新建的文件到服务器,需要2个步骤
添加新建的文件到本地的版本控制库中:svn add
提交刚才的添加操作到服务器:svn commit

如果直接提交一个没有添加到本地版本控制库中的文件,会报下面的错误
is not a working copy


向本地的版本控制库中添加一个新文件
svn add PATH

示例
svn add /Users/Desktop/workspace/Weibo/branches/User.m
/Users/Desktop/workspace/Weibo/branches/User.m代表的是:添加哪个文件到版本控制库中

删除

删除服务器上的某个文件,需要做2个步骤
将文件从本地的版本控制库中移除:svn delete 、svn remove
提交刚才的删除操作到服务器:svn commit

将文件从本地的版本控制库中移除
svn delete PATH

示例
svn delete /Users/Desktop/workspace/Weibo/branches/User.m
/Users/Desktop/workspace/Weibo/branches/User.m代表的是:将哪个文件从版本控制库中移除

更新

将服务器的最新代码更新到本地
svn update [PATH]

示例
svn update /Users/lnj/Desktop/workspace/Weibo/branches/User.m
/Users/lnj/Desktop/workspace/Weibo/branches/User.m代表的是:更新哪个文件的内容
如果省略/Users/lnj/Desktop/workspace/Weibo/branches/User.m的路径,就更新命令行所在路径的所有内容

将文件恢复至某个版本
svn update -r 版本号 [PATH]

服务端版本回退
svn merge -r 当前版本号:回退版本号 .
    .代表更新所有的文件,想更新单个文件可以直接写文件名

冲突解决

(p) postpone            对比(这个比较好)
(mc) mine-conflict      使用我的
(tc) theirs-conflict    使用对方的


svn resolved 文件名 : 解决完冲突后删除生成的临时文件

学习ios  重要还是要理清楚思路  在做或者看老师代码的时候 自己多想想为什么  不要自己看着就抄       另外还是要推荐一下 蓝懿IOS这个培训机构  和刘国斌老师刘国斌老师还是很有名气的,听朋友说刘老师成立了蓝懿iOS,,老师讲课方式很独特,能够尽量让每个人都能弄明白,有的比较难懂的地方,如果有的地方还是不懂得话,老师会换个其它方法再讲解,这对于我们这些学习iOS的同学是非常好的,多种方式的讲解会理解得更全面,这个必须得给个赞,嘻嘻,还有就是这里的学习环境很好,很安静,可以很安心的学习,安静的环境是学习的基础,小班讲课,每个班20几个学生,学习氛围非常好,每天都学到9点多才离开教室,练习的时间很充裕,而且如果在练习的过程中有什么困难,随时可以向老师求助,不像其它机构,通过视频教学,有的甚至学完之后都看不到讲师本人,问点问题都不方便,这就是蓝懿与其它机构的区别,相信在刘国斌老师的细心指导下,每个蓝懿学员都能找到满意的工作,加油!

  •                                                                   写博客第一百零七天;

                                                                              QQ:565803433

你可能感兴趣的:(蓝懿ios技术交流和心得分享16.1.25)