了解 IP 协议是网络层的, TCP, UDP是传输层的, socket是回话层的.
TCP与DUP 的区别
TCP: 是传输控制协议,通过三次握手完成连接,数据大小不限制.
UDP: 用户数据报协议,不需要建立连接,每一数据报大小在64K之内,不可靠
所以 TCP 多用与像访问网站, 等需要服务端, 用户端,两方配合的应用. 而UDP 通常用户像多媒体共享这样的, 只管把数据发出去,具体个人有没有在, 有没有卡, 对共享发布者不影响.
TCP 与HTTP 的关系
TCP协议: 网络传递, 信息管理的一些规范,可以理解为 计算机之间统一使用的传输规范, (理解为:规定两个人直接交流的方式口头交流, 书面交流.)
HTTP:超文本传输协议协议 是基于 TCP,确定交流的语言用汉语还是用英语.
总的来说, TCP确定的是传输的方式, 二 HTTP 是在传输方式的基础上, 确定数据传输的格式.
socket 和 HTTP 的关系
Socket : 网络通信的实质就是 socket之间的通信, HTTP协议的传输实质就是socket的传输.
HTTP: 连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接, 所以HTTP是短链接
socket: 理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去, 所以socket是长连接.
实际上socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。
Socket: 分为流式Socket:针对面向连接的TCP服务应用,数据报式Socket:面向无连接的UDP服务应用.
使用Socket 可以只传输数据本身,而不用进行XML封装.
实例代码 使用的是系统提供的方法实现的. GCDAsyncSocket 对系统的方法进行了封装, 实例没有使用这个
/// 1 创建与服务器之间的链接,
-(void)creatConnectToServer{
// 1.0 三次握手
// CFAllocatorRef alloc:为通道开辟内存空间,如果传入 NULL就使用默认的
// CFStringRef host : 服务器IP地址
// UInt32 port : 服务器的端口号
// CFReadStreamRef *readStream :输入流
// CFWriteStreamRef *writeStream :输出流
NSString * host =@"192.168.0.1";
int port =12345;
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (__bridgeCFStringRef)host , port, &readStream, &writeStream);
// 1.0.1 为了操作方便将 C语言的CFReadStreamRef, CFWriteStreamRef ,转化成OC语言的
inputStream = (__bridgeNSInputStream *)readStream;
outputStream = (__bridgeNSOutputStream *)writeStream;
// 1.1 为输入输出流设置代理
inputStream.delegate =self;
outputStream.delegate =self;
// 1.2 将输入输出流添加到主运行循环中 ,实现循环监听
/*
由于通常情况下Socket连接就是TCP连接,因此Socket连接一旦建立,通信双方即可开始相互发送数据内容,直到双方连接断开。但在实际网络应用中,客户端到服务器之间的通信往往需要穿越多个中间节点,例如路由器、网关、防火墙等,大部分防火墙默认会关闭长时间处于非活跃状态的连接而导致 Socket 连接断连,因此需要通过轮询告诉网络,该连接处于活跃状态。
*/
[inputStreamscheduleInRunLoop:[NSRunLoopmainRunLoop]forMode:NSDefaultRunLoopMode];
[outputStreamscheduleInRunLoop:[NSRunLoopmainRunLoop]forMode:NSDefaultRunLoopMode];
// 1.3 打开输入输出流
[inputStreamopen];
[outputStreamopen];
}
/// 2. 实现代理
- (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) {
caseNSStreamEventNone:
break;
caseNSStreamEventOpenCompleted:
// 连接成功
break;
caseNSStreamEventHasBytesAvailable:
// 有数据可读
[selfcreatReadRerverMessage];
break;
caseNSStreamEventHasSpaceAvailable:
// 可以发送数据
break;
caseNSStreamEventErrorOccurred:
// 出现错误,连接断开
break;
caseNSStreamEventEndEncountered:
// 正常断开连接
// 需要 1.关闭输入输出流, 2从主循环中移除
[inputStreamclose];
[outputStreamclose];
[inputStreamremoveFromRunLoop:[NSRunLoopmainRunLoop]forMode:NSDefaultRunLoopMode];
[outputStreamremoveFromRunLoop:[NSRunLoopmainRunLoop]forMode:NSDefaultRunLoopMode];
break;
default:
break;
}
}
/// 3 实现登录点击登录时调用
-(void)creatLogin{
// 登录是向服务器发送消息,是输出流
// 登录的格式是,按照服务器的格式来写的,如本例服务器端规定 iam表示登录请求,那么前端要发起登录请求,就必须用 iam
//
NSString *login =@"iam: xiaoming";
NSData *data = [logindataUsingEncoding:NSUTF8StringEncoding];
// (const uint8_t *)buffer接收的是一个 char类型数组,所以要用data转一下
// maxLength: 表示传输login的长度,这里是将 login全部传输
[outputStreamwrite: data.bytesmaxLength:data.length];
}
/// 4 读取服务器发送的消息需要在代理实现方法里调用
-(void)creatReadRerverMessage{
//4.0 定义一个缓存区,从服务器读取的数据先放到缓存区,再转成相应格式
uint8_t buf[1024];
// 4.1 读取数据 ,返回的是实际接收到的数据长度
NSInteger len = [inputStreamread:bufmaxLength:sizeof(buf)];
// 4.2 转化格式
NSString *receiverStr = [[NSStringalloc]initWithBytes:buflength:lenencoding:NSUTF8StringEncoding];
NSLog(@"%@", receiverStr);
}
/// 5 向服务器发送消息,这个与登录类似,不同的是根据服务器的要求,登录与消息的格式不同
-(void)creatSendMessageToSever:(NSString *)message{
// 消息的格式,服务器要求用 msg表示所以要拼接
NSString *str = [NSStringstringWithFormat:@"msg: %@",message];
NSData *data = [strdataUsingEncoding:NSUTF8StringEncoding];
[outputStreamwrite:data.bytesmaxLength:data.length];
}
本文参考 http://www.2cto.com/net/201211/166537.html