iOS socket 实现tcp和服务器长链接的简单使用心得
首先iOS端用了一个第三方的框架
GCDAsyncSocket
当然这个是CocoaAsyncSocket框架里面的一部分
Github下载地址https://github.com/robbiehanson/CocoaAsyncSocket
首先这个框架不能直接使用,因为直接使用的话会收不到服务器发过来的信息代理方法会不响应;
原因似乎是因为内存管理方面的会释放掉代理,具体的不太清楚
所以自己写一个单列初始化GCDAsyncSocket实现其代理,然后自定义代理就可以接受消息了
单列代码.h文件如下
#import <Foundation/Foundation.h>
#import "GCDAsyncSocket.h"
@protocol TcpManagerDelegate <NSObject>
-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port;
-(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err;
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag;
-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag;
@end
@interface TcpManager : NSObject
@property(strong,nonatomic) GCDAsyncSocket *asyncsocket;
@property(nonatomic,strong)id<TcpManagerDelegate>delegate;
+(TcpManager *)Share;
-(BOOL)destroy;
@end
.m文件如下
#import "TcpManager.h"
@interface TcpManager() <GCDAsyncSocketDelegate>
@end
@implementation TcpManager
+(TcpManager *)Share
{
static TcpManager *manager=nil;
static dispatch_once_t once;
dispatch_once(&once, ^{
manager=[[TcpManager alloc]init];
manager.asyncsocket=[[GCDAsyncSocket alloc]initWithDelegate:manager delegateQueue:dispatch_get_main_queue()];
});
return manager;
}
-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
{
if ([self.delegate respondsToSelector:@selector(socket:didConnectToHost:port:)]) {
[self.delegate socket:sock didConnectToHost:host port:port];
}
}
-(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
if ([self.delegate respondsToSelector:@selector(socketDidDisconnect:withError:)]) {
[self.delegate socketDidDisconnect:sock withError:err];
}
}
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
if ([self.delegate respondsToSelector:@selector(socket:didReadData:withTag:)]) {
[self.delegate socket:sock didReadData:data withTag:tag];
}
// [sock disconnect];
}
-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
if ([self.delegate respondsToSelector:@selector(socket:didWriteDataWithTag:)]) {
[self.delegate socket:sock didWriteDataWithTag:tag];
}
}
-(NSTimeInterval)socket:(GCDAsyncSocket *)sock shouldTimeoutWriteWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length
{
NSLog(@"timeout");
return 0;
}
-(BOOL)destroy
{
[_asyncsocket disconnect];
return YES;
}
@end
具体的使用如下
TcpManager *tcp = [TcpManager Share];
tcp.delegate = self;
socket = tcp.asyncsocket;
if (![socket connectToHost:@"服务器IP" onPort:服务器监听端口号 error:nil]) {
NSLog(@"fail to connect");
}
刚才定义的代理方法如下
//链接服务器成功回调
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{
if (self.time == nil) {
self.time = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(checkLongConnectByServe) userInfo:nil repeats:YES];
[self.time fire];
}
}
// 心跳连接
-(void)checkLongConnectByServe{
// 向服务器发送固定可是的消息,来检测长连接
NSString *longConnect = @"connect";
NSData *data = [longConnect dataUsingEncoding:NSUTF8StringEncoding];
[socket writeData:data withTimeout:3 tag:1];
[socket readDataWithTimeout:30 tag:2];
}
//收到信息回调
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
NSString * string = [[NSString alloc]
initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"didReadData===========>%@",string);
}
-(void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket{
NSLog(@"===========>didAcceptNewSocket");
}
-(void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err{
NSLog(@"===========>断开了");
}
//信息发送成功回调
-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag{
NSLog(@"===========>写入成功");
}