WebSocket同HTTP一样也是应用层的协议,但是它是一种双向通信协议,是建立在TCP之上的。Socket 是TCP/UDP协议的API,发生在传输层。
WebSocket与HTTP的区别
相同点
- 都是一样基于TCP的,都是可靠性传输协议。
- 都是应用层协议。
- WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息。HTTP是单向的。
- WebSocket是需要握手进行建立连接的。
特点
- WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要HTTP协议的。
WebSocket与Socket的关系
Socket其实并不是一个协议,而是为了方便使用TCP或UDP而抽象出来的一层,是位于应用层和传输控制层之间的一组接口。
“Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口,提供一套调用TCP/IP协议的API。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。”
当两台主机通信时,必须通过Socket连接,Socket则利用TCP/IP协议建立TCP连接。TCP连接则更依靠于底层的IP协议,IP协议的连接则依赖于链路层等更低层次。WebSocket就像HTTP一样,则是一个典型的应用层协议。
总结:Socket是传输控制层接口,WebSocket是应用层协议。
连接webSocket
NSURL *url = [NSURL URLWithString:@"ws://127.0.0.1:8090"];
self.websocket = [[SRWebSocket alloc] initWithURL:url];
self.websocket.delegate = self;
[self.websocket open];
发送心跳
dispatch_async(dispatch_get_main_queue(), ^{
// 为了方便其他地方调用是不是可以抽取出来一个销毁方法
// if (self.heartTimer) {
// [self.heartTimer invalidate];
// self.heartTimer = nil;
// }
[self destoryHeartBeat];
__weak typeof(self) weakSelf = self;
self.heartTimer = [NSTimer scheduledTimerWithTimeInterval:15 repeats:YES block:^(NSTimer * _Nonnull timer) {
//尽量简单 节约
//发送心跳 和后台可以约定发送什么内容
//一般可以调用ping 我这里根据后台的要求 发送了data给他
NSData *heartData = [@"heartBeat" dataUsingEncoding:NSUTF8StringEncoding];
[weakSelf.websocket sendPing:heartData];
NSLog(@"heartBeat");
// 也可以不断发
//[weakSelf.websocket send:@"heartBeat"];
}];
// 注意别被UI影响
[[NSRunLoop currentRunLoop] addTimer:self.heartTimer forMode:NSRunLoopCommonModes];
});
// 发送消息
[self.websocket send:self.contentTF.text];
// 断开处理
if (self.websocket) {
[self.websocket close];
self.websocket.delegate = nil;
self.websocket = nil;
[self destoryHeartBeat];
}
SRWebSocketDelegate
// 接受消息
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message{
NSLog(@"接收到了:%@",message);
}
// 建立连接的回调
- (void)webSocketDidOpen:(SRWebSocket *)webSocket{
NSLog(@"webSocket 建立连接打开了");
// 建立连接成功,开启心跳
[self 心跳];
}
// 错误回调
- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error{
NSLog(@"发生错误:%@",error);
[self 断开socket];
}
// 关闭错误原因
- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean{
NSLog(@"错误码:%ld---reason:%@ ---wasClean:%d",code,reason,wasClean);
}
// 接收到pong信息
- (void)webSocket:(SRWebSocket *)webSocket didReceivePong:(NSData *)pongPayload{
// NSString *pingStr =
NSLog(@"接收到了pong 信息 %@",pongPayload);
}
// Return YES to convert messages sent as Text to an NSString. Return NO to skip NSData -> NSString conversion for Text messages. Defaults to YES.
- (BOOL)webSocketShouldConvertTextFrameToString:(SRWebSocket *)webSocket{
// NO 就是不要把data转成string
return YES;
}