Swift移动开发技术前沿iOS进阶

iOS中长连接的那些事

2018-02-27  本文已影响1638人  景铭巴巴

我们组内部搞了一个公众号,大家支持一下,有不少好文章。iOS中长连接的那些事

一、长连接在iOS开发中的作用

一般的App的网络请求都是基于Http1.0进行的,使用的是NSURLConnection、NSURLSession或者是AFNetworking,Http1.0链接最显著的特点就是客户端每一次需要主动向服务端发送请求,都需要经历建立链接、发送请求、返回数据、关闭链接这几个阶段,是一种单向请求且无状态的协议。而有的时候,我们需要服务端主动往客户端进行推送服务的时候,这个时候长连接就起作用了。苹果提供的push服务apns就是典型的长连接的应用,IM应用、订单推送这些也是长连接的典型应用。长连接的特点是一旦通过三次握手建立链接之后,该条链路就一直存在,而且该链路是一种双向的通行机制,适合于频繁的网络请求,避免Http每一次请求都会建立链接和关闭链接的操作,减少浪费,提高效率。

二、通信网络的一些基本概念

长连接的一般实现方式都是基于TCP或者UDP协议完成的。这个时候我们就需要一些基本的通信网络概念。

2.1 OSI七层网络协议

开放系统互连参考模型 (Open System Interconnect 简称OSI)是国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)联合制定的开放系统互连参考模型,为开放式互连信息系统提供了一种功能结构的框架。


image

2.2、IP、TCP和Http

本文主要讲一下在网络层的IP协议、传输层的TCP协议和应用层的Http协议。这也是我们平时接触到最多的三个网络协议。

三、Socket

socket翻译为套接字,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信。它不属于OSI七层协议,它只是对于TCP,UDP协议的一套封装,让我们开发人员更加容易编写基于TCP、UDP的应用。


image

使用socket进行TCP通信的基本流程如下:


image

五、CocoaAsyncSocket

CocoaAsyncSocket是谷歌基于BSD-Socket写的一个IM框架,它给Mac和iOS提供了易于使用的、强大的异步套接字库,向上封装出简单易用OC接口。省去了我们面向Socket以及数据流Stream等繁琐复杂的编程,而且支持TCP或者UDP协议,支持IPv4和IPv6,支持TLS/SSL安全传输,并且是线程安全的。开源项目地址为https://github.com/robbiehanson/CocoaAsyncSocket

5.1、基于CocoaAsyncSocket实现的客户端代码

#import "GCDAsyncSocket.h"

@interface ViewController2 ()<GCDAsyncSocketDelegate>

@property (nonatomic, strong) GCDAsyncSocket *clientSocket;

@end

@implementation ViewController2

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor redColor];
    UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 400, 300, 60)];
    btn.backgroundColor = [UIColor orangeColor];
    [btn setTitle:@"发送数据" forState:UIControlStateNormal];
    [btn addTarget:self action:@selector(clickBtn) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn];
    
    self.clientSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    
    NSError *error = nil;
    [self.clientSocket connectToHost:@"127.0.0.1" onPort:12345 error:&error];
    if (error) {
        NSLog(@"error == %@",error);
    }
}

- (void)clickBtn{
    NSString *msg = @"发送数据: 你好\r\n";
    NSData *data = [msg dataUsingEncoding:NSUTF8StringEncoding];
    // withTimeout -1 : 无穷大,一直等
    // tag : 消息标记
    [self.clientSocket writeData:data withTimeout:-1 tag:0];
}

- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
{
    NSLog(@"链接成功");
    NSLog(@"服务器IP: %@-------端口: %d",host,port);
}

- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
    NSLog(@"发送数据 tag = %zi",tag);
    [sock readDataWithTimeout:-1 tag:tag];
}

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"读取数据 data = %@ tag = %zi",str,tag);
    // 读取到服务端数据值后,能再次读取
    [sock readDataWithTimeout:- 1 tag:tag];

}

- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
    NSLog(@"断开连接");
    self.clientSocket.delegate = nil;
    self.clientSocket = nil;
}
@end

5.2、服务端Socket使用nc命令代替

打开mac命令行终端 输入 nc -lk 12345

5.3、演示结果

六、补充知识

6.1、长连接为什么要保持心跳?

国内移动无线网络运营商在链路上一段时间内没有数据通讯后, 会淘汰NAT表中的对应项, 造成链路中断。而国内的运营商一般NAT超时的时间为5分钟,所以通常我们心跳设置的时间间隔为3-5分钟。

6.2、长连接选择TCP协议还是UDP协议?

使用TCP进行数据传输的话,简单、安全、可靠,但是带来的是服务端承载压力比较大。

使用UDP进行数据传输的话,效率比较高,带来的服务端压力较小,但是需要自己保证数据的可靠性,不作处理的话,会导致丢包、乱序等问题。

如果你的技术团队实力过硬,你可以选择UDP协议,否则还是使用TCP协议比较好。据说腾讯IM就是使用的UDP协议,然后还封装了自己的私有协议,来保证UDP数据包的可靠传输。

6.3、服务端单机最大TCP连接数是多少?

理论最大值:server通常固定在某个本地端口上监听,等待client的连接请求。不考虑地址重用的情况下,即使server端有多个ip,本地监听端口也是独占的,因此server端tcp连接4元组中只有remote ip(也就是client ip)和remote port(客户端port)是可变的,因此最大tcp连接为客户端ip数×客户端port数,对IPV4,不考虑ip地址分类等因素,最大tcp连接数约为2的32次方(ip数)×2的16次方(port数),也就是server端单机最大tcp连接数约为2的48次方。

实际最大值:上面给出的是理论上的单机最大连接数,在实际环境中,受到机器资源、操作系统等的限制,特别是sever端,其最大并发tcp连接数远不能达到理论上限。在unix/linux下限制连接数的主要因素是内存和允许的文件描述符个数(每个tcp连接都要占用一定内存,每个socket就是一个文件描述符),另外1024以下的端口通常为保留端口。对server端,通过增加内存、修改最大文件描述符个数等参数,单机最大并发TCP连接数超过10万,甚至上百万 是没问题的,国外 Urban Airship 公司在产品环境中已做到 50 万并发 。在实际应用中,对大规模网络应用,还需要考虑C10K ,C100k问题。

七、参考文章

IP,TCP 和 HTTP
玩转iOS开发:iOS中的Socket编程
iOS即时通讯,从入门到“放弃”
单机最大tcp连接数

八、联系方式

新浪微博
github
简书首页

上一篇下一篇

猜你喜欢

热点阅读