socketTest
2018-02-10 本文已影响34人
倪大头
//调用
- (void)socketTest {
[singleSocket sharedInstance].socketHost = @"xxx.xxx.x.xxx";//host设定
[singleSocket sharedInstance].socketPort = 10000;// port设定
// 在连接前先进行手动断开
[singleSocket sharedInstance].socket.userData = SocketOfflineByUser;
[[singleSocket sharedInstance] cutOffSocket];
// 确保断开后再连,如果对一个正处于连接状态的socket进行连接,会出现崩溃
[singleSocket sharedInstance].socket.userData = SocketOfflineByServer;
[[singleSocket sharedInstance] socketConnectHost];
}
//singleSocket.h:
#import <Foundation/Foundation.h>
#import "AsyncSocket.h"
enum {
SocketOfflineByServer,// 服务器掉线,默认为0
SocketOfflineByUser, // 用户主动cut
};
@interface singleSocket : NSObject<AsyncSocketDelegate>
@property (nonatomic, strong) AsyncSocket *socket; // socket
@property (nonatomic, copy ) NSString *socketHost; // socket的Host
@property (nonatomic, assign) UInt16 socketPort; // socket的prot
@property (nonatomic, retain) NSTimer *connectTimer; // 计时器
+ (singleSocket *)sharedInstance;
- (void)socketConnectHost;//socket连接
- (void)cutOffSocket;//断开socket连接
@end
//singleSocket.m:
#import "singleSocket.h"
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>
#import <unistd.h>
@implementation singleSocket
+ (singleSocket *)sharedInstance {
static singleSocket *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc]init];
});
return sharedInstance;
}
//socket连接
- (void)socketConnectHost {
self.socket = [[AsyncSocket alloc]initWithDelegate:self];
NSError *error = nil;
[self.socket connectToHost:self.socketHost onPort:self.socketPort withTimeout:3 error:&error];
}
#pragma mark - 连接成功回调
- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port {
NSLog(@"socket连接成功");
//每隔s向服务器发送心跳包
self.connectTimer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(longConnectToSocket) userInfo:nil repeats:YES];//在longConnectToSocket方法中进行长连接需要向服务器发送的讯息
[self.connectTimer fire];
}
//心跳连接
- (void)longConnectToSocket {
//根据服务器要求发送固定格式的数据,假设为指令@"longConnect",但是一般不会是这么简单的指令
//NSString *longConnect = @"textStr";
//NSData *dataStream = [longConnect dataUsingEncoding:NSUTF8StringEncoding];
//[self.socket writeData:dataStream withTimeout:1 tag:1];
NSMutableData *socketData = [NSMutableData data];
//length 4个字节
uint32_t lengthbytes = 29;
NSData *lengthData = [NSData dataWithBytes:&lengthbytes length:sizeof(uint32_t)];
[socketData appendData:lengthData];
//type 1个字节
Byte typebytes[1] = {0x10};
NSData *typeData = [NSData dataWithBytes:typebytes length:1];
[socketData appendData:typeData];
//uid 4个字节
uint32_t uidbytes = (uint32_t)[AXUserModel sharedUseInfo].userId;
NSData *uidData = [NSData dataWithBytes:&uidbytes length:sizeof(uint32_t)];
[socketData appendData:uidData];
//oid(对方id) 4个字节
uint32_t oidbytes = (uint32_t)[AXUserModel sharedUseInfo].userId;
NSData *oidData = [NSData dataWithBytes:&oidbytes length:sizeof(uint32_t)];
[socketData appendData:oidData];
//经纬度
double longitudebytes = [AXManager sharedManager].currentCityMJLng;
NSData *longitudeData = [NSData dataWithBytes:&longitudebytes length:8];
double latitudebytes = [AXManager sharedManager].currentCityMJLat;
NSData *latitudeData = [NSData dataWithBytes:&latitudebytes length:8];
[socketData appendData:longitudeData];
[socketData appendData:latitudeData];
[self.socket writeData:socketData withTimeout:15 tag:1];
}
//数据发送成功
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag {
NSLog(@"%s",__func__);
//发送完数据手动读取,-1不设置超时
[sock readDataWithTimeout:-1 tag:tag];
}
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
// 对得到的data值进行解析与转换即可
[self.socket readDataWithTimeout:30 tag:0];
}
//切断socket
- (void)cutOffSocket {
self.socket.userData = SocketOfflineByUser;//声明是由用户主动切断
[self.connectTimer invalidate];
[self.socket disconnect];
}
//重连
- (void)onSocketDidDisconnect:(AsyncSocket *)sock {
NSLog(@"长链接断开 %ld",sock.userData);
if (sock.userData == SocketOfflineByServer) {
// 服务器掉线,重连
[self socketConnectHost];
}else if (sock.userData == SocketOfflineByUser) {
// 如果由用户断开,不进行重连
return;
}
}
@end