网络基本结构
OSI七层模型:
物理层:定义的是设备的标准
数据链路层:定义了对比特流的包装
网络层:定义了传输的路径
传输层:定义了传输数据的协议(常见的各种HTTP、TCP、UDP等等)
会话层:定义了收发数据对象的协议
表示层:定义了两个终端可识别的协议
应用层:用户使用软件的层次
网络世界中最重要的就是协议,各种各样的协议。
数据传输的时候会用到一个socket套接字协议。套接字工作在传输层到应用层之间。
认识TCP
TCP是传输控制协议。数据传输的大小在传输中不受限制。通过三次握手完成通道的建立,是可靠传输。所谓的可靠传输就是会不断询问其接收的进度直至完成接收。
请求HTTP网页就是基于TCP协议建立的。我们想要访问一个网页,就是通过三次握手的协议从服务器建立连接的。但HTTP协议是数据格式协议。
认识UDP
UDP也是一个传输协议,但是UDP是不可靠的传输协议,因为两个终端并不需要建立连接,数据的大小限定在64K之内,发了之后就不管对方有没有收到了。
网络通信要素
需要:IP地址、端口号、传输协议、URL。
端口号用于对进程的一个逻辑地址的标示,其中0~1024是系统保留用的端口号,开发中不要设置1024以下的端口号用。
Telent协议可以确认服务器有没有开启,在开发过程中偶尔会遇到服务器访问不到的情况,有可能是服务器没有开启,这个时候只需要用telent协议去访问以下端口。
telent 127.0.0.1 80
socket
本地进程间的通信可以通过PID来确定彼此,然后借由共享内存的方式等来完成通信。
网络上的两个进程进行通信则需要确定彼此的IP与端口号,通过传输层的协议(TCP、UDP等)进行通信。
socket的特点就是在TCP/UDP上增加一个端口绑定。
由于端口号是被进程独占的,因此socket通信经常与进程通信划上等号。
socket通信的步骤
提供服务
将服务与自己的ip、端口绑定
监听任何到这个ip和端口的TCP请求
接受or拒绝 建立这个TCP请求
读写数据
断开TCP链接
基本上互联网所有的服务都是基于socketAPI。
在iOS中实现socket连接
@interface ViewController()<NSStreamDelegate>
@property (nonatomic, strong)NSInputStream* inputStream;
@property (nonatomic, strong)NSOutputStream* outputStream;
@end
-(void)connectToServer{
//第一个参数:CFAllocatorRef _Null_unspecified alloc传递的是输入输出流的一个内存分配,默认可以传NULL
//第二个参数:CFSocketNativeHandle sock 传的是服务器的地址,由参数类型可看出是字符串类型。
//第三个参数:UInt32 port 传的是端口号,Int类型即可。
//第四、五个参数:CFReadStreamRef CFWriteStreamRef 是输入输出流
NSString* host = @"127.0.0.1";
int port = 12345;
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)host, port, &readStream, &writeStream);
//将C语言处理好的输入输出流转换成OC对象
NSInputStream* inputStream = (__bridge NSInputStream *)(readStream);
NSOutputStream* outputStream = (__bridge NSOutputStream *)(writeStream);
self.inputStream = inputStream;
self.outputStream = outputStream;
//设置输入输出流的代理
inputStream.delegate = self;
outputStream.delegate = self;
//因为主运行循环是监听界面变化与触控事件的,而网络事件的监听也应该添加到主运行循环中。
[inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
//打开输入输出流
[inputStream open];
[outputStream open];
}
//当连接上后,就会有事件响应在输入输出流上,我们代理就要接受,现在来实现代理方法:
-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{
/*事件类型
NSStreamEventNone = 0,
NSStreamEventOpenCompleted = 1UL << 0, //连接建立成功
NSStreamEventHasBytesAvailable = 1UL << 1, //有数据可读
NSStreamEventHasSpaceAvailable = 1UL << 2, //可发送数据
NSStreamEventErrorOccurred = 1UL << 3, //有错误发生,连接失败
NSStreamEventEndEncountered = 1UL << 4 //正常的断开链接
*/
switch (eventCode) {
case NSStreamEventOpenCompleted:
NSLog(@"NSStreamEventOpenCompleted连接建立成功");
break;
case NSStreamEventErrorOccurred:
NSLog(@"NSStreamEventErrorOccurred有错误发生,连接失败");
break;
case NSStreamEventHasBytesAvailable:
NSLog(@"NSStreamEventHasBytesAvailable有数据可读");
break;
case NSStreamEventEndEncountered:
NSLog(@"NSStreamEventEndEncountered正常的断开链接");
break;
case NSStreamEventHasSpaceAvailable:
NSLog(@"NSStreamEventHasSpaceAvailable可发送数据");
break;
case NSStreamEventNone:
NSLog(@"NSStreamEventNone无事");
break;
default:
NSLog(@"default");
break;
}
}
使用socket实现登录
登录是要发送数据给服务器的,所以使用的是输出流相关的API。
- (void)login{
//发送登录请求,使用的是输出流
//拼接登录请求指令
NSString* loginRequest = @"user:xiaoHong";
//uint8_t* 字符数组
NSData* data = [loginRequest dataUsingEncoding:NSUTF8StringEncoding];
[self.outputStream write:data.bytes maxLength:data.length];
}
读取数据
- (void)readMessage{
//取得缓冲区
uint8_t message[1024];//定义了最大长度为1024字节的缓冲区数组
//读取服务器返回的数据,messageLen为缓冲区里数据实际的大小
NSInteger messageLen = [self.inputStream read:message maxLength:sizeof(message)];
NSString* messageCon = [[NSString alloc]initWithBytes:message length:messageLen encoding:NSUTF8StringEncoding];
NSLog(@"message:%@",messageCon);
}
发送数据
- (void)sendMessage:(NSString*)message{
//同样发送数据是向服务器发送请求,使用的是输出流
//拼接套接字语法,一般情况下,服务器端约定消息为msg:
NSString* msg = [@"msg:" stringByAppendingString:message];
NSData* data = [msg dataUsingEncoding:NSUTF8StringEncoding];
[self.outputStream write:data.bytes maxLength:data.length];
}
在异步中使用Socket
视频看到第三天B02节
CoreData
CoreData中几乎不用写数据库操作语句就能完成数据的本地化存储。
CoreData和iOS中的模型对象相联系在一起,只需要操作模型对象的增删改查就可以完成数据的增删改查,不用写SQL语句。
CoreData的存储方式
SQLite NSSQLiteStoreType
XML NSXMLStoreType
Binary NSBinaryStoreType
内存存储 NSInMemoryStoreType
CoreData的核心对象
NSManagedObjectContext 用途:负责应用与数据库之间的交互
NSPersistentStoreCoordinator 用途:添加持久化数据库,如SQLite
NSManagedObjectModel 用途:代表CoreData的模型文件
NSEntityDescription 用途:用于描述实体
XMPP是一个用于即时通讯的一个框架。
数据存储采用的是CoreData